diff --git a/Makefile b/Makefile index 5904a3f967e..7e76ac915fc 100644 --- a/Makefile +++ b/Makefile @@ -239,7 +239,7 @@ _MAKE+= MK_META_MODE=no _TARGET_ARCH= ${TARGET:S/pc98/i386/:S/arm64/aarch64/} .elif !defined(TARGET) && defined(TARGET_ARCH) && \ ${TARGET_ARCH} != ${MACHINE_ARCH} -_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/aarch64/arm64/:C/powerpc64/powerpc/:C/powerpcspe/powerpc/:C/riscv64/riscv/} +_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/aarch64/arm64/:C/powerpc64/powerpc/:C/powerpcspe/powerpc/:C/riscv64(sf)?/riscv/} .endif .if defined(TARGET) && !defined(_TARGET) _TARGET=${TARGET} diff --git a/Makefile.inc1 b/Makefile.inc1 index c48be4c0033..b718afeef05 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -364,6 +364,7 @@ KNOWN_ARCHES?= aarch64/arm64 \ powerpc64/powerpc \ powerpcspe/powerpc \ riscv64/riscv \ + riscv64sf/riscv \ sparc64 .if ${TARGET} == ${TARGET_ARCH} @@ -676,9 +677,6 @@ _worldtmp: .PHONY .endif .else rm -rf ${WORLDTMP}/legacy/usr/include -# XXX - These can depend on any header file. - rm -f ${OBJTREE}${.CURDIR}/lib/libsysdecode/ioctl.c - rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/kdump_subr.c .endif .for _dir in \ lib lib/casper usr legacy/bin legacy/usr diff --git a/UPDATING b/UPDATING index fb869480ebc..3240f5f5c56 100644 --- a/UPDATING +++ b/UPDATING @@ -130,7 +130,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW: 20160527: CAM will now strip leading spaces from SCSI disks' serial numbers. - This will effect users who create UFS filesystems on SCSI disks using + This will affect users who create UFS filesystems on SCSI disks using those disk's diskid device nodes. For example, if /etc/fstab previously contained a line like "/dev/diskid/DISK-%20%20%20%20%20%20%20ABCDEFG0123456", you should diff --git a/bin/dd/dd.c b/bin/dd/dd.c index 56f8efef7a5..a13213dcc8c 100644 --- a/bin/dd/dd.c +++ b/bin/dd/dd.c @@ -48,10 +48,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include +#include #include #include #include @@ -92,6 +95,10 @@ main(int argc __unused, char *argv[]) jcl(argv); setup(); + caph_cache_catpages(); + if (cap_enter() == -1 && errno != ENOSYS) + err(1, "unable to enter capability mode"); + (void)signal(SIGINFO, siginfo_handler); (void)signal(SIGINT, terminate); @@ -125,6 +132,8 @@ static void setup(void) { u_int cnt; + cap_rights_t rights; + unsigned long cmds[] = { FIODTYPE, MTIOCTOP }; if (in.name == NULL) { in.name = "stdin"; @@ -133,13 +142,20 @@ setup(void) in.fd = open(in.name, O_RDONLY, 0); if (in.fd == -1) err(1, "%s", in.name); + if (caph_limit_stdin() == -1) + err(1, "unable to limit capability rights"); } getfdtype(&in); + cap_rights_init(&rights, CAP_READ, CAP_SEEK); + if (cap_rights_limit(in.fd, &rights) == -1 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (files_cnt > 1 && !(in.flags & ISTAPE)) errx(1, "files is not supported for non-tape devices"); + cap_rights_set(&rights, CAP_WRITE, CAP_FTRUNCATE, CAP_IOCTL); if (out.name == NULL) { /* No way to check for read access here. */ out.fd = STDOUT_FILENO; @@ -156,13 +172,27 @@ setup(void) if (out.fd == -1) { out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE); out.flags |= NOREAD; + cap_rights_clear(&rights, CAP_READ); } if (out.fd == -1) err(1, "%s", out.name); + if (caph_limit_stdout() == -1) + err(1, "unable to limit capability rights"); } getfdtype(&out); + if (cap_rights_limit(out.fd, &rights) == -1 && errno != ENOSYS) + err(1, "unable to limit capability rights"); + if (cap_ioctls_limit(out.fd, cmds, nitems(cmds)) == -1 && + errno != ENOSYS) + err(1, "unable to limit capability rights"); + + if (in.fd != STDERR_FILENO && out.fd != STDERR_FILENO) { + if (caph_limit_stderr() == -1) + err(1, "unable to limit capability rights"); + } + /* * Allocate space for the input and output buffers. If not doing * record oriented I/O, only need a single buffer. diff --git a/bin/echo/Makefile.depend b/bin/echo/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/bin/echo/Makefile.depend +++ b/bin/echo/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/bin/sleep/Makefile.depend b/bin/sleep/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/bin/sleep/Makefile.depend +++ b/bin/sleep/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/cddl/contrib/opensolaris/cmd/ztest/ztest.c b/cddl/contrib/opensolaris/cmd/ztest/ztest.c index 5fc571774e3..bfc80e3b028 100644 --- a/cddl/contrib/opensolaris/cmd/ztest/ztest.c +++ b/cddl/contrib/opensolaris/cmd/ztest/ztest.c @@ -1371,7 +1371,6 @@ ztest_log_write(ztest_ds_t *zd, dmu_tx_t *tx, lr_write_t *lr) itx->itx_private = zd; itx->itx_wr_state = write_state; itx->itx_sync = (ztest_random(8) == 0); - itx->itx_sod += (write_state == WR_NEED_COPY ? lr->lr_length : 0); bcopy(&lr->lr_common + 1, &itx->itx_lr + 1, sizeof (*lr) - sizeof (lr_t)); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c index ef10e0bc7e9..1216a389e23 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c @@ -1057,46 +1057,6 @@ dt_action_printm(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value + sizeof(uintptr_t); } -static void -dt_action_printt(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) -{ - dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp); - - dt_node_t *size = dnp->dn_args; - dt_node_t *addr = dnp->dn_args->dn_list; - - char n[DT_TYPE_NAMELEN]; - - if (dt_node_is_posconst(size) == 0) { - dnerror(size, D_PRINTT_SIZE, "printt( ) argument #1 must " - "be a non-zero positive integral constant expression\n"); - } - - if (addr == NULL || addr->dn_kind != DT_NODE_FUNC || - addr->dn_ident != dt_idhash_lookup(dtp->dt_globals, "typeref")) { - dnerror(addr, D_PRINTT_ADDR, - "printt( ) argument #2 is incompatible with " - "prototype:\n\tprototype: typeref()\n" - "\t argument: %s\n", - dt_node_type_name(addr, n, sizeof (n))); - } - - dt_cg(yypcb, addr); - ap->dtad_difo = dt_as(yypcb); - ap->dtad_kind = DTRACEACT_PRINTT; - - ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF; - - /* - * Allow additional buffer space for the data size, type size, - * type string length and a stab in the dark (32 bytes) for the - * type string. The type string is part of the typeref() that - * this action references. - */ - ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value + 3 * sizeof(uintptr_t) + 32; - -} - static void dt_action_commit(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) { @@ -1169,9 +1129,6 @@ dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) case DT_ACT_PRINTM: dt_action_printm(dtp, dnp->dn_expr, sdp); break; - case DT_ACT_PRINTT: - dt_action_printt(dtp, dnp->dn_expr, sdp); - break; case DT_ACT_RAISE: dt_action_raise(dtp, dnp->dn_expr, sdp); break; diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c index e748ff2b3ad..e4580a8ab34 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cg.c @@ -1353,40 +1353,6 @@ dt_cg_inline(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) } } -static void -dt_cg_func_typeref(dtrace_hdl_t *dtp, dt_node_t *dnp) -{ - dtrace_typeinfo_t dtt; - dt_node_t *addr = dnp->dn_args; - dt_node_t *nelm = addr->dn_list; - dt_node_t *strp = nelm->dn_list; - dt_node_t *typs = strp->dn_list; - char buf[DT_TYPE_NAMELEN]; - char *p; - - ctf_type_name(addr->dn_ctfp, addr->dn_type, buf, sizeof (buf)); - - /* - * XXX Hack alert! XXX - * The prototype has two dummy args that we munge to represent - * the type string and the type size. - * - * Yes, I hear your grumble, but it works for now. We'll come - * up with a more elegant implementation later. :-) - */ - free(strp->dn_string); - - if ((p = strchr(buf, '*')) != NULL) - *p = '\0'; - - strp->dn_string = strdup(buf); - - if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_EVERY, buf, &dtt) < 0) - return; - - typs->dn_value = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type); -} - typedef struct dt_xlmemb { dt_ident_t *dtxl_idp; /* translated ident */ dt_irlist_t *dtxl_dlp; /* instruction list */ @@ -2002,8 +1968,6 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) switch (dnp->dn_kind) { case DT_NODE_FUNC: { - dtrace_hdl_t *dtp = yypcb->pcb_hdl; - if ((idp = dnp->dn_ident)->di_kind != DT_IDENT_FUNC) { dnerror(dnp, D_CG_EXPR, "%s %s( ) may not be " "called from a D expression (D program " @@ -2011,15 +1975,6 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp) dt_idkind_name(idp->di_kind), idp->di_name); } - switch (idp->di_id) { - case DIF_SUBR_TYPEREF: - dt_cg_func_typeref(dtp, dnp); - break; - - default: - break; - } - dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp); dnp->dn_reg = dt_regset_alloc(drp); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c index 04c022b7ad0..de574a33026 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c @@ -1537,314 +1537,6 @@ dt_print_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) return (err); } -int -dt_print_memory(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr) -{ - int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET); - size_t nbytes = *((uintptr_t *) addr); - - return (dt_print_bytes(dtp, fp, addr + sizeof(uintptr_t), - nbytes, 50, quiet, 1)); -} - -typedef struct dt_type_cbdata { - dtrace_hdl_t *dtp; - dtrace_typeinfo_t dtt; - caddr_t addr; - caddr_t addrend; - const char *name; - int f_type; - int indent; - int type_width; - int name_width; - FILE *fp; -} dt_type_cbdata_t; - -static int dt_print_type_data(dt_type_cbdata_t *, ctf_id_t); - -static int -dt_print_type_member(const char *name, ctf_id_t type, ulong_t off, void *arg) -{ - dt_type_cbdata_t cbdata; - dt_type_cbdata_t *cbdatap = arg; - ssize_t ssz; - - if ((ssz = ctf_type_size(cbdatap->dtt.dtt_ctfp, type)) <= 0) - return (0); - - off /= 8; - - cbdata = *cbdatap; - cbdata.name = name; - cbdata.addr += off; - cbdata.addrend = cbdata.addr + ssz; - - return (dt_print_type_data(&cbdata, type)); -} - -static int -dt_print_type_width(const char *name, ctf_id_t type, ulong_t off, void *arg) -{ - char buf[DT_TYPE_NAMELEN]; - char *p; - dt_type_cbdata_t *cbdatap = arg; - size_t sz = strlen(name); - - ctf_type_name(cbdatap->dtt.dtt_ctfp, type, buf, sizeof (buf)); - - if ((p = strchr(buf, '[')) != NULL) - p[-1] = '\0'; - else - p = ""; - - sz += strlen(p); - - if (sz > cbdatap->name_width) - cbdatap->name_width = sz; - - sz = strlen(buf); - - if (sz > cbdatap->type_width) - cbdatap->type_width = sz; - - return (0); -} - -static int -dt_print_type_data(dt_type_cbdata_t *cbdatap, ctf_id_t type) -{ - caddr_t addr = cbdatap->addr; - caddr_t addrend = cbdatap->addrend; - char buf[DT_TYPE_NAMELEN]; - char *p; - int cnt = 0; - uint_t kind = ctf_type_kind(cbdatap->dtt.dtt_ctfp, type); - ssize_t ssz = ctf_type_size(cbdatap->dtt.dtt_ctfp, type); - - ctf_type_name(cbdatap->dtt.dtt_ctfp, type, buf, sizeof (buf)); - - if ((p = strchr(buf, '[')) != NULL) - p[-1] = '\0'; - else - p = ""; - - if (cbdatap->f_type) { - int type_width = roundup(cbdatap->type_width + 1, 4); - int name_width = roundup(cbdatap->name_width + 1, 4); - - name_width -= strlen(cbdatap->name); - - dt_printf(cbdatap->dtp, cbdatap->fp, "%*s%-*s%s%-*s = ",cbdatap->indent * 4,"",type_width,buf,cbdatap->name,name_width,p); - } - - while (addr < addrend) { - dt_type_cbdata_t cbdata; - ctf_arinfo_t arinfo; - ctf_encoding_t cte; - uintptr_t *up; - void *vp = addr; - cbdata = *cbdatap; - cbdata.name = ""; - cbdata.addr = addr; - cbdata.addrend = addr + ssz; - cbdata.f_type = 0; - cbdata.indent++; - cbdata.type_width = 0; - cbdata.name_width = 0; - - if (cnt > 0) - dt_printf(cbdatap->dtp, cbdatap->fp, "%*s", cbdatap->indent * 4,""); - - switch (kind) { - case CTF_K_INTEGER: - if (ctf_type_encoding(cbdatap->dtt.dtt_ctfp, type, &cte) != 0) - return (-1); - if ((cte.cte_format & CTF_INT_SIGNED) != 0) - switch (cte.cte_bits) { - case 8: - if (isprint(*((char *) vp))) - dt_printf(cbdatap->dtp, cbdatap->fp, "'%c', ", *((char *) vp)); - dt_printf(cbdatap->dtp, cbdatap->fp, "%d (0x%x);\n", *((char *) vp), *((char *) vp)); - break; - case 16: - dt_printf(cbdatap->dtp, cbdatap->fp, "%hd (0x%hx);\n", *((short *) vp), *((u_short *) vp)); - break; - case 32: - dt_printf(cbdatap->dtp, cbdatap->fp, "%d (0x%x);\n", *((int *) vp), *((u_int *) vp)); - break; - case 64: - dt_printf(cbdatap->dtp, cbdatap->fp, "%jd (0x%jx);\n", *((long long *) vp), *((unsigned long long *) vp)); - break; - default: - dt_printf(cbdatap->dtp, cbdatap->fp, "CTF_K_INTEGER: format %x offset %u bits %u\n",cte.cte_format,cte.cte_offset,cte.cte_bits); - break; - } - else - switch (cte.cte_bits) { - case 8: - dt_printf(cbdatap->dtp, cbdatap->fp, "%u (0x%x);\n", *((uint8_t *) vp) & 0xff, *((uint8_t *) vp) & 0xff); - break; - case 16: - dt_printf(cbdatap->dtp, cbdatap->fp, "%hu (0x%hx);\n", *((u_short *) vp), *((u_short *) vp)); - break; - case 32: - dt_printf(cbdatap->dtp, cbdatap->fp, "%u (0x%x);\n", *((u_int *) vp), *((u_int *) vp)); - break; - case 64: - dt_printf(cbdatap->dtp, cbdatap->fp, "%ju (0x%jx);\n", *((unsigned long long *) vp), *((unsigned long long *) vp)); - break; - default: - dt_printf(cbdatap->dtp, cbdatap->fp, "CTF_K_INTEGER: format %x offset %u bits %u\n",cte.cte_format,cte.cte_offset,cte.cte_bits); - break; - } - break; - case CTF_K_FLOAT: - dt_printf(cbdatap->dtp, cbdatap->fp, "CTF_K_FLOAT: format %x offset %u bits %u\n",cte.cte_format,cte.cte_offset,cte.cte_bits); - break; - case CTF_K_POINTER: - dt_printf(cbdatap->dtp, cbdatap->fp, "%p;\n", *((void **) addr)); - break; - case CTF_K_ARRAY: - if (ctf_array_info(cbdatap->dtt.dtt_ctfp, type, &arinfo) != 0) - return (-1); - dt_printf(cbdatap->dtp, cbdatap->fp, "{\n%*s",cbdata.indent * 4,""); - dt_print_type_data(&cbdata, arinfo.ctr_contents); - dt_printf(cbdatap->dtp, cbdatap->fp, "%*s};\n",cbdatap->indent * 4,""); - break; - case CTF_K_FUNCTION: - dt_printf(cbdatap->dtp, cbdatap->fp, "CTF_K_FUNCTION:\n"); - break; - case CTF_K_STRUCT: - cbdata.f_type = 1; - if (ctf_member_iter(cbdatap->dtt.dtt_ctfp, type, - dt_print_type_width, &cbdata) != 0) - return (-1); - dt_printf(cbdatap->dtp, cbdatap->fp, "{\n"); - if (ctf_member_iter(cbdatap->dtt.dtt_ctfp, type, - dt_print_type_member, &cbdata) != 0) - return (-1); - dt_printf(cbdatap->dtp, cbdatap->fp, "%*s};\n",cbdatap->indent * 4,""); - break; - case CTF_K_UNION: - cbdata.f_type = 1; - if (ctf_member_iter(cbdatap->dtt.dtt_ctfp, type, - dt_print_type_width, &cbdata) != 0) - return (-1); - dt_printf(cbdatap->dtp, cbdatap->fp, "{\n"); - if (ctf_member_iter(cbdatap->dtt.dtt_ctfp, type, - dt_print_type_member, &cbdata) != 0) - return (-1); - dt_printf(cbdatap->dtp, cbdatap->fp, "%*s};\n",cbdatap->indent * 4,""); - break; - case CTF_K_ENUM: - dt_printf(cbdatap->dtp, cbdatap->fp, "%s;\n", ctf_enum_name(cbdatap->dtt.dtt_ctfp, type, *((int *) vp))); - break; - case CTF_K_TYPEDEF: - dt_print_type_data(&cbdata, ctf_type_reference(cbdatap->dtt.dtt_ctfp,type)); - break; - case CTF_K_VOLATILE: - if (cbdatap->f_type) - dt_printf(cbdatap->dtp, cbdatap->fp, "volatile "); - dt_print_type_data(&cbdata, ctf_type_reference(cbdatap->dtt.dtt_ctfp,type)); - break; - case CTF_K_CONST: - if (cbdatap->f_type) - dt_printf(cbdatap->dtp, cbdatap->fp, "const "); - dt_print_type_data(&cbdata, ctf_type_reference(cbdatap->dtt.dtt_ctfp,type)); - break; - case CTF_K_RESTRICT: - if (cbdatap->f_type) - dt_printf(cbdatap->dtp, cbdatap->fp, "restrict "); - dt_print_type_data(&cbdata, ctf_type_reference(cbdatap->dtt.dtt_ctfp,type)); - break; - default: - break; - } - - addr += ssz; - cnt++; - } - - return (0); -} - -static int -dt_print_type(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr) -{ - caddr_t addrend; - char *p; - dtrace_typeinfo_t dtt; - dt_type_cbdata_t cbdata; - int num = 0; - int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET); - ssize_t ssz; - - if (!quiet) - dt_printf(dtp, fp, "\n"); - - /* Get the total number of bytes of data buffered. */ - size_t nbytes = *((uintptr_t *) addr); - addr += sizeof(uintptr_t); - - /* - * Get the size of the type so that we can check that it matches - * the CTF data we look up and so that we can figure out how many - * type elements are buffered. - */ - size_t typs = *((uintptr_t *) addr); - addr += sizeof(uintptr_t); - - /* - * Point to the type string in the buffer. Get it's string - * length and round it up to become the offset to the start - * of the buffered type data which we would like to be aligned - * for easy access. - */ - char *strp = (char *) addr; - int offset = roundup(strlen(strp) + 1, sizeof(uintptr_t)); - - /* - * The type string might have a format such as 'int [20]'. - * Check if there is an array dimension present. - */ - if ((p = strchr(strp, '[')) != NULL) { - /* Strip off the array dimension. */ - *p++ = '\0'; - - for (; *p != '\0' && *p != ']'; p++) - num = num * 10 + *p - '0'; - } else - /* No array dimension, so default. */ - num = 1; - - /* Lookup the CTF type from the type string. */ - if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_EVERY, strp, &dtt) < 0) - return (-1); - - /* Offset the buffer address to the start of the data... */ - addr += offset; - - ssz = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type); - - if (typs != ssz) { - printf("Expected type size from buffer (%lu) to match type size looked up now (%ld)\n", (u_long) typs, (long) ssz); - return (-1); - } - - cbdata.dtp = dtp; - cbdata.dtt = dtt; - cbdata.name = ""; - cbdata.addr = addr; - cbdata.addrend = addr + nbytes; - cbdata.indent = 1; - cbdata.f_type = 1; - cbdata.type_width = 0; - cbdata.name_width = 0; - cbdata.fp = fp; - - return (dt_print_type_data(&cbdata, dtt.dtt_type)); -} - static int dt_print_sym(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) { @@ -1904,6 +1596,16 @@ dt_print_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) return (0); } +static int +dt_print_memory(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr) +{ + int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET); + size_t nbytes = *((uintptr_t *) addr); + + return (dt_print_bytes(dtp, fp, addr + sizeof(uintptr_t), + nbytes, 50, quiet, 1)); +} + typedef struct dt_normal { dtrace_aggvarid_t dtnd_id; uint64_t dtnd_normal; @@ -2644,12 +2346,6 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, goto nextrec; } - if (act == DTRACEACT_PRINTT) { - if (dt_print_type(dtp, fp, addr) < 0) - return (-1); - goto nextrec; - } - if (DTRACEACT_ISPRINTFLIKE(act)) { void *fmtdata; int (*func)(dtrace_hdl_t *, FILE *, void *, diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h index 6bc392ff65f..d95de2dfa99 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_errtags.h @@ -265,8 +265,6 @@ typedef enum { D_NOREG, /* no available internal registers */ D_PRINTM_ADDR, /* printm() memref bad type */ D_PRINTM_SIZE, /* printm() size bad type */ - D_PRINTT_ADDR, /* printt() typeref bad type */ - D_PRINTT_SIZE /* printt() size bad type */ } dt_errtag_t; extern const char *dt_errtag(dt_errtag_t); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h index e71e9d71aef..f2c60a2b07d 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h @@ -488,7 +488,6 @@ struct dtrace_hdl { #define DT_ACT_SETOPT DT_ACT(28) /* setopt() action */ #define DT_ACT_PRINT DT_ACT(29) /* print() action */ #define DT_ACT_PRINTM DT_ACT(30) /* printm() action */ -#define DT_ACT_PRINTT DT_ACT(31) /* printt() action */ /* * Sentinel to tell freopen() to restore the saved stdout. This must not diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c index a56b98681d3..77d8386bc80 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c @@ -392,8 +392,6 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_func, "void(@, ...)" }, { "printm", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTM, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_func, "void(size_t, uintptr_t *)" }, -{ "printt", DT_IDENT_ACTFUNC, 0, DT_ACT_PRINTT, DT_ATTR_STABCMN, DT_VERS_1_0, - &dt_idops_func, "void(size_t, uintptr_t *)" }, { "probefunc", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEFUNC, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" }, { "probemod", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEMOD, @@ -505,8 +503,6 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_func, "void(@, size_t, ...)" }, { "trunc", DT_IDENT_ACTFUNC, 0, DT_ACT_TRUNC, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_func, "void(...)" }, -{ "typeref", DT_IDENT_FUNC, 0, DIF_SUBR_TYPEREF, DT_ATTR_STABCMN, DT_VERS_1_1, - &dt_idops_func, "uintptr_t *(void *, size_t, string, size_t)" }, { "uaddr", DT_IDENT_ACTFUNC, 0, DT_ACT_UADDR, DT_ATTR_STABCMN, DT_VERS_1_2, &dt_idops_func, "_usymaddr(uintptr_t)" }, { "ucaller", DT_IDENT_SCALAR, 0, DIF_VAR_UCALLER, DT_ATTR_STABCMN, diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile index 83a93cf0cb5..17e1eb9bdf5 100644 --- a/cddl/lib/libdtrace/Makefile +++ b/cddl/lib/libdtrace/Makefile @@ -121,12 +121,10 @@ LIBADD= ctf elf proc pthread rtld_db CLEANFILES= dt_errtags.c dt_names.c -dt_errtags.c: - sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mkerrtags.sh < ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/dt_errtags.h > dt_errtags.c - -dt_names.c: - sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mknames.sh < ${OPENSOLARIS_SYS_DISTDIR}/uts/common/sys/dtrace.h > dt_names.c - -beforedepend: dt_errtags.c dt_names.c - .include + +dt_errtags.c: ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/dt_errtags.h + sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mkerrtags.sh < ${.ALLSRC} > ${.TARGET} + +dt_names.c: ${OPENSOLARIS_SYS_DISTDIR}/uts/common/sys/dtrace.h + sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mknames.sh < ${.ALLSRC} > ${.TARGET} diff --git a/contrib/amd/AUTHORS b/contrib/amd/AUTHORS index 3c241d016bb..1ae6dcd2d72 100644 --- a/contrib/amd/AUTHORS +++ b/contrib/amd/AUTHORS @@ -6,22 +6,22 @@ This file lists the ones who contributed major code changes, in no particular order, and I thank them all. This is of course not to diminish the smaller contributes of the many others. Thank you all. -* Erez Zadok +* Erez Zadok The most significant changes were made by Erez Zadok in terms of bug fixes, ports, and new features added. Erez Zadok is the current maintainer of am-utils, as of January 1997. -* Ion Badulescu +* Ion Badulescu Co-maintainer of am-utils since late 1999: Linux and Solaris autofs support, Linux NFSv3 support, major code reorganization, etc... -* Randall S. Winchester +* Randall S. Winchester May 7, 1997: contributed a special version of upl102 that included NFS V.3 support. Some of the code was contributed by Christos Zoulas -. I (Erez) ported these changes to am-utils. +. I (Erez) ported these changes to am-utils. September 12, 1997: lots of small prototype cleanups and fixes to numerous files. @@ -35,12 +35,12 @@ February 1, 1998: fixes for NetBSD to better detect its features. September 4, 1999: assorted fixes for NetBSD 1.4+. -* Hannes Reinecke +* Hannes Reinecke Back in 1995, contributed code for linux. A new parser for file system specific options that only exist under linux. -* Leif Johansson +* Leif Johansson June 22, 1997: minor patch to ensure that systems without an RE library work. @@ -52,7 +52,7 @@ functions. Contributed scripts/amd2ldif.pl. August 4, 1997: info_ldap.c fixes and adding two new amd.conf ldap variables: ldap_cache_seconds and ldap_cache_maxmem. -* Andreas Stolcke +* Andreas Stolcke June 22, 1997: patches to ensure that proto= and vers= options work properly in mount tables and can be overridden. Later on, more code @@ -68,11 +68,11 @@ message. December 19, 1997: detected an FMR (Free Memory Read) in amd/mntfs.c, uninit_mntfs(). -* Danny Braniss +* Danny Braniss July, 6 1997: contributed patches to hesiod on bsdi3. -* Tom Schmidt +* Tom Schmidt July 10, 1997: Recommdation to include libgdbm if libc has no dbm_open. Patches for netgrp(host) command. Mods to aux/config.guess to recognize @@ -86,7 +86,7 @@ IFF_ROUTE instead of IFF_LOOPBACK. May 30, 2000: correct logging types for addopts/mergeopts messages. -* Daniel S. Riley +* Daniel S. Riley July 11, 1997: fixes to DU-4.0 to support string POSIX.1 signals, and struct sockaddr with sa_len field. @@ -99,15 +99,15 @@ grpid, nosuid, and actimo. August 15, 1998: fix memory leak in processing of /defaults, and avoid accessing uninitialized memory in osf1. -* Roman Hodek +* Roman Hodek July 23, 1997: Got lots of patches from the Debian Linux folks, who fixed several generic bugs, and one serious one for Linux. The latter involved using connected sockets for NFS mounts on kernels 1.3.10 and older. Roman's -work is baed on amd-upl102, and work from Ian Murdock -and Dominik Kubla . +work is baed on amd-upl102, and work from Ian Murdock +and Dominik Kubla . -* Rainer Orth +* Rainer Orth August 6, 1997: assorted fixes to support hesiod-1.3, solaris 2.4 (which I already fixed but did not release yet), and support for $LDFLAGS at @@ -132,34 +132,34 @@ mount tables in Solaris 8. February 9, 2000: new debug options hrtime (hi-res timer) and xdrtrace. bug fixes. -* Jason Thorpe +* Jason Thorpe August 25, 1997: make amd work when talking to NIS+ servers in NIS compatibility mode. Fix originally came from Matthieu Herrb -. +. -* Chris Metcalf +* Chris Metcalf August 29, 1997: patch to make amd use FQHN for NFS/RPC authentication, useful esp. for cross-domain NFS mounts. September 2, 1997: if plock() succeeded, don't display errno string. -* Enami Tsugutomo +* Enami Tsugutomo September 4, 1997: don't ping remote servers with NFS V.3 always, but V.2, regardless of client's NFS version. (conf/transp/transp_sockets.c) -* Dan Riley +* Dan Riley September 19, 1997: make sure that amd works with more secure portmappers that do not allow forwarding of RPC messages to other services. -* Wolfgang Rupprecht +* Wolfgang Rupprecht August 10, 1997: netbsd and other bsd systems have a mask flag for pcfs_args (msdos mount). -* Christos Zoulas +* Christos Zoulas September 25, 1997: fix to initialize uid/gid fields of pcfs_args_t on netbsd. @@ -181,7 +181,7 @@ TLI implementations. Patch to print version string (amd -v) after all options had been initialized, so we can print domain, host, and hostd. Linux patch to use umount2(2) if umount(2) fails. -* Bill Paul +* Bill Paul November 5, 1997: NFS v.3 support for AIX 4.2.1, which does *not* include headers for this. Bill had to guess at the right structures, field names, @@ -189,26 +189,26 @@ sizes, alignment, etc. January 15, 1999: small ldap bug fixes. -* Stefan Vogel +* Stefan Vogel November 14, 1997: typo in the subscription instructions to amd-dev. -* Guntram Wolski +* Guntram Wolski November 15, 1997: pointed out mismatching documentation for the -o option. -* Michael Hucka +* Michael Hucka January 11, 1997: pointed out reversed definition of NFS mount options vers and proto. -* Albert Chin +* Albert Chin January 12, 1998: minor bug in output of amd -H. June 23, 2005: assortment of small compile bugs on aix4, and solaris 5/6/7. -* Thomas Richter +* Thomas Richter January 13, 1998: use case insensitive comparisons for variables that need it (such as all hostname related ones, and more). @@ -216,11 +216,11 @@ it (such as all hostname related ones, and more). July 20, 1998: don't leak memory in the private version of yp_all (when vendor yp_all is bad). -* Fred Korz +* Fred Korz January 30, 1998: minor typo fixed to tftp example in am-utils.texi. -* Donald Buczek +* Donald Buczek March 6, 1998: correctly inherit existing NFS V.3 mounts upon restart. @@ -230,36 +230,36 @@ March 20, 1998: do not close stdout in case it gets reused elsewhere and to allow startup script to redirect it. Set a temporary secure umask(0022) before writing log file and restore it afterwards. -* Matthew Crosby +* Matthew Crosby April 20, 1998: allow arbitrary number of interfaces in wire listing. -* David O'Brien +* David O'Brien September 4, 1998: bug fix to avoid overrunning hostname buffer, and minor amd.conf man page typo correction. September 22, 1999: use more secure vsnprintf in real_plog(). -* Danny Rathjens +* Danny Rathjens October 29, 1998: swap arguments to kill(2) in amd.c. -* Mike Mitchell +* Mike Mitchell November 3, 1998: amd/nfs_subr.c (nfsproc_lookup_2_svc): try to avoid a race condition between unmounting and re-mounting an entry, by increasing the ttl of a looked up entry before unmounting it. -* Douglas K. Rand" +* Douglas K. Rand" December 3, 1998: case insensitive host name match for nfsl. -* David Wolfskill +* David Wolfskill January 28, 1999: don't turn on/off noconn option if it was already in that state. -* Jeffrey C Honig +* Jeffrey C Honig March 14, 1999: clean up more autogenerated files upon "make distclean". March 15, 1999: avoid overly verbose NIS warning even on systems that don't @@ -271,30 +271,30 @@ detection for bsdi4. September 17, 1999: fixes to expn. -* Paul Balyoz +* Paul Balyoz March 26, 1999: ensure lostaltmail displays Y2K compliant dates. -* Jon Peatfield +* Jon Peatfield March 30, 1999: turn off incomplete NFS V.3 support in HPUX 10.20. September 22, 1999: safe reloading of maps without first clearing old copies, and using cached copies if map failed to reload. -* Peter Breitenlohner +* Peter Breitenlohner July 24, 1999: patch for linux 2.2.x to work with older libc5 systems, and nis_isup mis-logic fixes. December 13, 2001: report typos in scripts/amd.conf.5. -* Dale Talcott +* Dale Talcott July 26, 1999: added NFS3 support for AIX mounting. -* Christophe Kalt +* Christophe Kalt July 14, 1999: add netgrpd() syntax function which uses FQHN. -* Andrew J. Korty +* Andrew J. Korty September 5, 1999: pawd works for type:=nfsl. -* Nick Williams +* Nick Williams September 1, 1999: bug fix for incorrect symlinks when two locations are requested simultaneously. @@ -306,38 +306,38 @@ doing rapid mounts and umounts in succession. June 5, 2000: better handling of potential race-conditions during rapid u/mounts. Correctly update d_drops stats for amq -s. -* Johann Pfefferl +* Johann Pfefferl November 16, 1999: fix to ldap code so repeated calls to string2he don't corrupt the string passed. -* Amitha Perera +* Amitha Perera December 9, 1999: detect all wire() interfaces correctly. -* Steven Danz +* Steven Danz January 25, 2000: allow browsable auto maps. -* Wolfram Klaus . +* Wolfram Klaus . November 21, 2000: recognize proplist mnttab flag. -* Thomas Klausner +* Thomas Klausner November 21, 2000: lots of NetBSD fixes (many of which are generic). April 18, 2003: patch to reference am-utils info pages in man page. November 28, 2004: small fixes to typos in amd.conf(5) man page. -* Olaf Kirch +* Olaf Kirch February 1, 2001: important Linux NFS error number mapping fixed -* Ahmon Dancy +* Ahmon Dancy February 9, 2001: Apple Rhapsody/Darwin/OS X port -* Sebastien Bahloul +* Sebastien Bahloul July 3, 2001: LDAP fixes and updates to support new APIs March 27, 2002: LDAP bug and port to HPUX-11. -* Philippe Troin +* Philippe Troin July 12, 2001: Proper handling of GNU getopt, support for optionally disabling LDAP/Hesiod, fixes for the dev/nodev option on Linux. Texi documentation fix. @@ -348,65 +348,65 @@ generic mount option. July 17, 2003: pref:=null core dump fix. libgdbm portability. tcpd/librap support. And a few other things for the 6.0 branch. -* Trond Myklebust +* Trond Myklebust January 10, 2002: Proper initialization of the timeo parameter on Linux, TCP _must_ have a timeout 2 orders of magnitude larger than UDP -* George Ross +* George Ross April 29, 2002: Rework of old code, support for wildcards in LDAP queries, and an FD leak fix. Amd -A support. October 21, 2002: ldap_unbind fix for SIGPIPE, and support for LDAPv3 -protocol version parameter (with Tim Colles ). +protocol version parameter (with Tim Colles ). -* Matthias Scheler +* Matthias Scheler June 14, 2002: patch to use "xlatecookie" NFS mount option. -* Jun-ichiro itojun Hagino . +* Jun-ichiro itojun Hagino . June 11, 2002: minor fixes to support NetBSD 1.6A. -* Sean Fagan +* Sean Fagan March 14, 2003: detect and use the MNT2_GEN_OPT_AUTOMNTFS mount flag on OS X / Darwin. -* Hendrik Scholz +* Hendrik Scholz June 9, 2003: mk-amd-map should open temp db file using O_EXCL. -* Mark Davies +* Mark Davies July 14, 2003: define "xlatecookie" mnttab option if not defined (for NetBSD). Support null hesiod entries if they start with a ".". -* Eric S. Raymond +* Eric S. Raymond December 9, 2003: fix unbalanced [] typo in fsinfo man page. -* Martin Blapp +* Martin Blapp July 6, 2004: recognize fields in pcfs_args_t in FreeBSD 5. -* Dan Nelson +* Dan Nelson August 2, 2004: pawd to recognize "host" type mounts. -* Hauke Fath +* Hauke Fath August 3, 2004: pawd to recognize "linkx" type mounts. -* Michael van Elst +* Michael van Elst September 1, 2004: bug fix to avoid race condition in calls to mntctl on AIX. -* Jonathan Chen +* Jonathan Chen October 22, 2004: patch/fix to move mlock/mlockall/plock code after the fork(). June 29, 2005: core dump going off end of exported_ap[] array. September 29, 2005: patch/fix for pawd not to go into an infinite loop. October 25, 2005: patch/fix for pawd to repeatedly resolve path. -* David Rage +* David Rage January 17, 2005: prevent Amd from logging 'Read-only filesystem' errors when the mount point has an ancestor (i.e. '/') that is mounted read-only. -* Kevin Layer +* Kevin Layer January 28, 2005: basic instructions how to setup Amd on Mac OS-X. -* Dan Ottavio +* Dan Ottavio March 2, 2005: new global amd.conf option debug_mtab_file, to set the debug mtab file when using debug_options=mtab. Default has changed from "./mtab" to "/tmp/mtab" to avoid security problem. Bug fixed to ensure that Amd @@ -415,16 +415,13 @@ terminates properly even mtab file doesn't exist. * Erik Kline January 3, 2005: implementation of executable maps for Amd. -* Jim Zajkowski +* Jim Zajkowski March 14, 2005: small patch to amd2ldif. * Adam Morley January 27, 2005: synchronize what amd2ldif does vs. what the ldap.schema expects. -* Graeme Wilford +* Graeme Wilford July 4, 2005: buffer overflow in pawd. -* Steve Plite -September 22, 2005: repair reversed meaning of D_AMQ, so amq will unregister -on exit. diff --git a/contrib/amd/BUGS b/contrib/amd/BUGS index 3a3ba6b367d..8e87e859cba 100644 --- a/contrib/amd/BUGS +++ b/contrib/amd/BUGS @@ -1,7 +1,7 @@ LIST OF KNOWN BUGS IN AM-UTILS OR OPERATING SYSTEMS Note: report am-utils bugs via Bugzilla to https://bugzilla.am-utils.org/ or -by email to the am-utils@am-utils.org mailing list. +by email to the am-utils mailing list (see www.am-utils.org). (1) mips-sgi-irix* @@ -98,11 +98,11 @@ diff -u -r1.1 utsname.h (4) powerpc-ibm-aix4.2.1.0 -[4A] "Randall S. Winchester" reports that for amd to +[4A] "Randall S. Winchester" reports that for amd to start, you need to kill and restart rpc.mountd and possibly also make sure that nfsd is running. Normally these are not required. -[4B] "Stefan Vogel" reports that if your amq +[4B] "Stefan Vogel" reports that if your amq executable dump core unexpectedly, then it may be a bug in gcc 2.7.x. Upgrade to gcc 2.8.x or use IBM's xlC compiler. @@ -123,7 +123,7 @@ but it is not yet in the glibc-2.0.7-19 RPM. A bug in libc results in an amq binary that doesn't work; amq -v dumps core in xdr_string. There is no known fix (source code or vendor patch) at this -time. (Please let am-utils@am-utils.org know if you know of a fix.) +time. (Please let us know if you have a fix; see www.am-utils.org.) (7) *-aix4.3.2.0 diff --git a/contrib/amd/COPYING b/contrib/amd/COPYING index 035f6239c93..f54191d75fe 100644 --- a/contrib/amd/COPYING +++ b/contrib/amd/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 1997-2006 Erez Zadok +Copyright (c) 1997-2014 Erez Zadok Copyright (c) 1989 Jan-Simon Pendry Copyright (c) 1989 Imperial College of Science, Technology & Medicine Copyright (c) 1989 The Regents of the University of California. @@ -15,12 +15,7 @@ are met: 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 acknowledgment: - This product includes software developed by the University of - California, Berkeley and its contributors, as well as the Trustees of - Columbia University. -4. Neither the name of the University nor the names of its contributors +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. diff --git a/contrib/amd/ChangeLog b/contrib/amd/ChangeLog index 12f2c5fb8e6..d996f8e7508 100644 --- a/contrib/amd/ChangeLog +++ b/contrib/amd/ChangeLog @@ -1,14 +1,564 @@ +2014-10-28 Christos Zoulas + + ******************************************************************* + *** Released am-utils-6.2 *** + ******************************************************************* + + * add ylwrap.amd, sick and tired of patching broken ylwrap. + +2014-09-05 Christos Zoulas + + * factor out the size check for both readdir methods + (raven at themaw.net) + +2014-09-03 Christos Zoulas + + * configure test for 64 bit xdr function (raven at themaw.net) + +2014-09-01 Christos Zoulas + + * bug fix from raven at themaw.net to prevent writing v3 handle + to a v2 structure. + +2014-07-21 Christos Zoulas + + * fix permission problems with access + * auto_nfs_version = 3 now works for me. + +2014-07-20 Christos Zoulas + + * refresh some autoconf files + * force autoconf version since earlier versions don't work + * changes from raven at themaw.net to support NFSv3 for automounted + toplevel filesystems presented to the list in May. A few bug fixes + and integration changes by me. The code now works well enough to + mount the filesystem with NFSv3 and automount children but readdir + does not work yet (so no listing of automounted filesystems). + The new code is not enabled by default. To enable use + auto_nfs_version = 3 + in your configuration file. + +2014-03-26 Christos Zoulas + + From Ian Kent + + * use mktemp in scripts/fixrmtab + * fix documentatio nits + * [linux] Add ext2, ext3, ext4 specific mount options + * fix tcpwrappers (hosts.{allow,deny} problems for specific host + entries + +2014-03-20 Christos Zoulas + + + * don't background autofs umount + * avoid fh NULL dereference on umount + * handle ENOENT umount return for autofs mounts + * fix error message in get_nfs_version + * fix debug log deadlock + * [linux] retry umount on EBUSY + * handle failed umount on exit + +2014-03-09 Christos Zoulas + + * Remove BSD advertising clause. + * Remove expn program which is not used by anything + +2013-12-05 Christos Zoulas + + * Change the way we handle multiple lex scanners and yacc parsers + in a single program. Our old patch to ylwrap does not work anymore + because the bison parsers need shared symbols that start with yy + and we can't easily select which ones work. So now we use -P and + -p to let lex and yacc do the work for us. This requires a patch + to ylwrap, but it is smaller. + + +2013-12-05 Christos Zoulas + + * Change the way we handle multiple lex scanners and yacc parsers + in a single program. Our old patch to ylwrap does not work anymore + because the bison parsers need shared symbols that start with yy + and we can't easily select which ones work. So now we use -P and + -p to let lex and yacc do the work for us. This requires a patch + to ylwrap, but it is smaller. + +2013-05-14 Christos Zoulas + + * update to handle new autoconf and regen files + +2012-11-23 Christos Zoulas + + * recognize mountport=, noacl options + * simplify the bootstrap process, by forcing + all the files to be rebuild with autoreconf -f - i + +2012-10-03 Christos Zoulas + + * add missing ops_nfs4.c to the Makefile.am + +2012-09-14 Christos Zoulas + + * add locking option handling for lustre + * fix noatime, nodiratime, mandlock for linux + +2012-07-25 Christos Zoulas + + * bug fixes for lustre rhost parsing + +2012-06-27 Christos Zoulas + + * Disable 1/2-baked sun map support to avoid SIGSEGV + +2012-06-16 Christos Zoulas + + ******************************************************************* + *** Released am-utils-6.2-rc1 *** + ******************************************************************* + + * Fix libtool.m4 to work with later versions of autoconf. + * In buildall, use eval so that quoted strings work + * Centralize nfs version checking function, and introduce + new configuration variable nfs_vers_ping, which is the + max version we ping for. This is not documented yet, because + there might be a better way separate the max version we can + use vs the max version we ping for. + +2012-06-09 Christos Zoulas + + * fix issue with parsing nfsv4 security option strings + +2012-05-01 Christos Zoulas + + * Handle EPERM return from v4 file handles + in old linux kernels + +2012-03-09 Christos Zoulas + + * fix linux autofs detection + * fix wrong types in new amq mount xdr processing + +2012-01-25 Christos Zoulas + + * FreeBSD portability fixes + +2012-01-23 Christos Zoulas + + * Avoid type punned warnings + +2011-12-29 Christos Zoulas + + * fix bug I introduced in get_nfs_version that caused it to return 0 + * add direct support for ext{2,3,4} + +2011-12-15 Christos Zoulas + + * Include on linux, to grab extra mount flags + * Add support for lustre + +2011-11-28 Christos Zoulas + + * For nfsl mounts, match against either the short local + host name or the fqdn name. + +2011-10-06 Christos Zoulas + + * Add NFSv4 support (loosely based on Ramya's code). + Currently if the NFSv4 mount fails with ENOENT we fail + back to NFSv3, unless -DNO_FALLBACK. + * Replace strdup with xstrdup. It is not nice to replace + system functions with ones that behave differently. + * Add various consistency checks (caller function checks + variable for NULL, but callee does not). + * Fix error handling in various paths. + * Don't check before using XFREE(). free(NULL) works. + +2011-09-15 Christos Zoulas + + * amq -i addition (prints info about the map files) + +2011-09-14 Christos Zoulas + + * Solaris OS and compiler fixes from: + Hofmann, Frank + Sayle, Alex + - (void)&var generates warnings, removed + - __inline is invalid, changed with inline + - and other headers have extra dependendcies + ` +2011-08-11 Christos Zoulas + + * fix potential buffer overflow in expand_error() + (Richard Kettlewell). Does not seem to be exploitable. + + * simplify %option parsing to appease ancient flex. + +2011-06-21 Christos Zoulas + + * add support for linux autofs version 5 (untested) + +2011-06-18 Christos Zoulas + + * roll back to an older version of libtool that works + + * newer versions of config.guess and config.sub + + * minor fixes to buildall + +2011-05-19 Christos Zoulas + + * m4/macros/libtool.m4: for AIX AC_LANG_PROGRAM is incorrectly + used and the latest autoconf gives an error. For now just + quote it. + + * configure.in: Fedora Core 15 and RedHat 6 now don't define + af_family_t in , but in . + Include so that we get + indirectly. This caused the detection + test to fail. + +2010-11-24 Erez Zadok + + * m4/macros/os_cflags.m4: for linux, define _GNU_SOURCE (to get + definitions for O_LARGEFILE and more). + +2010-11-20 Christos Zoulas + + * Update news items, add release readme, mark as rc1 + + * Fix addopts code to work with options that are key=value + when the built-in hasmntopt() code is not used. The problem + was that the code passed "key=" to hasmntopt not "key". + +2009-12-10 Christos Zoulas + + * Copy all fields of the am_opts structure + When we introduced am_loc we also added a function to + create a duplicate of an am_opts structure. As it turns + out, that only made a partial copy of the struct and some + fields (e.g. opt_cache) was left blank in the new structure. + Unfortunately any code that was checking the options + through the mntfs structure was mislead by the partial + copy: caching was disabled completely, for example, and + since browsing relies on caching being enabled it wasn't + working either. + From: Krisztian Kovacs + + * Initialize RPC authentication flavor to AUTH_UNIX instead + of zero. RHEL 5 uses version 6 of the mount_arg structure + that includes the desired RPC authorization flavour. + Unfortunately amd initializes that value to zero, meaning + AUTH_NULL, resulting in all NFS servers denying operations. + From: Krisztian Kovacs + + * Make sure to remove nodes in the proper order when going + down. Depending on what order the nodes got created it's + possible that the parent of a node has a bigger am_mapno + (index in exported_ap[]) so that it gets freed before + its child while the child's am_parent pointer is still + pointing to the already freed block of memory. + This change makes sure that umount_exported() cleans up + all children of a node first before freeing the node. + From: Krisztian Kovacs + + * Fix Linux-specific stuff in ops_tmpfs.c + AUTOFS_TMPFS_FS_FLAGS is defined only in the Linux-specific + conf_linux.c file, so it cannot be built on Solaris. + From: Krisztian Kovacs + + * Add missing parenthesis to fix defined(XXX + From: Krisztian Kovacs + + * In the previous commit we've already made a change that + makes this code unnecessary since the node is returned + even if the backing file server is known to be down. + Since the code path is unused it should be removed. + From: Krisztian Kovacs + + * amfs_generic_lookup_child() tries to find an alternate + file server if it detects that the current one is down. + However, in the comparison used to decide if a possible + mount is the same as the current one it compares the am_loc + pointers instead of the actual mntfs pointers. Since + amfs_lookup_one_location() creates a brand new am_loc + structure for the returned mntfs structure the am_loc + pointer will be different even if the mntfs it's pointing + to is the same. + This tricks amfs_generic_lookup_child() think it has + found an alternate file server while it hasn't and thus + starts multiple racing mounts for the very same node and + mntfs. + From: Krisztian Kovacs + + * In the new am_loc scheme mounted mntfs structures still + have their mf_fo structure left intact. So when restart + creates a fake mntfs for an already mounted filesystem it + should not free mf_fo right away. + From: Krisztian Kovacs + + * Setting the error flag of the mntfs for which the share + is already mounted results in the mount point not being + removed when it times out. (Amd considers it an error + mntfs and thus umount becomse a no-op.) + From: Krisztian Kovacs + + * Right now AMD sets all timeout values to their defaults + even if you explicitly set them to zero. This patch + introduces separate flags that store if the respective + values have been set and the code path setting default + values checks these flags instead of testing the values + for zero. [Linux only] + From: Krisztian Kovacs + + * Fix mntfs related lookup/(un)mount race conditions, by + introducing a new structure linking an mntfs to a node. + From: Krisztian Kovacs + + * We have to free the buffers allocated by the XDR routines when + decoding the mount response after copying them to their final place. + From: Krisztian Kovacs + +2009-12-09 Christos Zoulas + + * Free continuation in amfs_retry() if we don't call amfs_bgmount() + Normally it's amfs_bgmount() which frees the continuation. However, if + the mount is already in progress and we're in amfs_retry() for another + node we don't try mounting the filesystem once again. Still, we have + to free the continuation as we won't get called again and thus would + leak the continuation structure and our am_loc references. + From: Krisztian Kovacs + + * Fix use-after-free and double free of mntfs private data + ops_nfs.c(nfs_init) does not clear private data pointer after free(). + This leads to use-after-free and double free in case mount() fails. + (found by valgrind) + From: Krisztian Kovacs + +2009-11-23 Christos Zoulas + + * The temporary filename buffer was leaked in lock_mtab(). + From: Krisztian Kovacs + +2009-10-27 Christos Zoulas + + * Deal with errno.h->sys/errno.h better + +2009-10-26 Christos Zoulas + + * Fix issue with autoconf 2.63 + + * Fix compile warnings for gcc-4.4.x + +2009-04-15 Christos Zoulas + + * Share the LDAP connection between different maps to save resources + on the LDAP server. (Olaf Flebbe ) + +2009-03-20 Christos Zoulas + + * Fix largefile re-definitions + + * Fix compilation error caused in previous patch + +2009-02-19 Christos Zoulas + + * Add a synchronous unmount amq rpc that will wait for the remote + filesystem to be unmounted, or return an error. Enabled by amq -uu + +2009-01-11 Erez Zadok + + * amd/ops_udf.c: don't define functions/variables which may not be + used. + + * amd/ops_tmpfs.c (mount_tmpfs): force gcc not to complain about + unused variables. + + * config.guess.long: properly support Fedora Core. + +2009-01-09 Christos Zoulas + + * Fix nfs mounts on linux 2.6.26 by explicitly initializing context. + + * Treat an empty sublink as an unset sublink; this allows us to + say sublink:=; in a spec to override the default. (This produces + Bad selector error, but it works. XXX: We need to decide how to + unset a selector. I proposed an unset keyword a while ago). + +2009-01-06 Christos Zoulas + + * re-renerate all generated files with newer versions of the + auto-tools. + + * move INSTALL to INSTALL.am-utils to avoid conflicts + + * fix incompatibilities with new m4 and new autoconf. + + * add UDF filesystem support. + + * fix NetBSD nfs file handle detection. + +2009-01-02 Christos Zoulas + + * add nocasetrans, nojoliet, rrcaseins for cd9660 filesystems + +2008-12-03 Christos Zoulas + + * allow ldap queries try a comma-separated list of servers given as: + + ldap_hostports = host1:port1,host2,host3:port3 + + original patch from Florian Geyer + +2008-09-19 Christos Zoulas + + * the auth_create gid on NetBSD is int + + * deal with lossage from flex -P + + * fix missing/incorrect prototypes + +2008-09-17 Christos Zoulas + + * fix manual page section issues (sorting, non-existant) + + * add missing forward declarations + + * avoid null pointer derefs (coverity) + + * more portable endian detection support + + * implement tmpfs support + + * use sizeof var instead of constant + + * fix yyerror declaration and definition + + * fix yy function renaming, and correct some renaming issues. + + * work around automake < 1.9 issue where ylwrap is not being run + for a single yacc or lex file. + + * NetBSD + - handle headers that need other headers to compile + - add exfs and tmpfs specific glue + - add options log, noatime, nocoredump, nodevmtime, softdep, + symperm, union + - NetBSD's new mount system call needs the size of the opaque + filesystem specific structure, but passing 0 for now works. + We would need to change a lot more code to pass the size from + the fs-specific calls, so for now punt. + - recvfrom takes socklen_t * on NetBSD + - handle newer NetBSD using statvfs + - NetBSD calls its ufs ffs + + * Linux + - Most recent kernels have trouble with trying to parse the pid + hostname and do locking. What before was a silent failure, now + there is a warning printed and the mount is rejected. This is + the simplest fix: + (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=479884) + +2007-04-13 Erez Zadok + + * amd/sun_map.c (sun_append_str): When translating '&' from Sun + automounter maps, replace it with "${key}" in the Amd map, not + with the value of the key at the time. This way '*' maps work + too. + + * config.guess.long: don't use -q option to grep because some + systems don't support it. Bug fix for solaris. + +2007-03-11 Christos Zoulas + + * amd/opts.c (expand_op): Don't call xstrlcpy() to truncate a + string. It causes spurious xstrlcpy() syslog() errors. Use + memcpy() and explicitly terminate the string. + +2007-01-20 Erez Zadok + + * updated copyright year to 2007 on all files. + +2006-12-27 Erez Zadok + + * minor new port: ia64-hp-hpux11.23 + + * m4/macros/check_libwrap_severity.m4 (LIBS): also test if caller + needs to define rfc931_timeout. + + * amd/sun2amd.c: define rfc931_timeout and allow/deny_severity for + libwrap. + + * amd/amq_svc.c: some versions of libwrap require the caller to + define rfc931_timeout in addition to allow/deny_severity. + + * amd/amfs_toplvl.c (amfs_toplvl_init): properly detect when + forced unmount functionality exists for all systems. + + * libamu/mount_fs.c (compute_nfs_args): reset nfs_args_t->pathconf + only if field exists. + + * conf/nfs_prot/nfs_prot_hpux11.h: prevent HPUX 11.23 from + including or (TLI definitions are already + included from elsewhere). + + * configure.in: detect nfs_args_t->pathconf field. + +2006-11-27 Erez Zadok + + * doc/Makefile.am: properly publish html files using newer + text2html. + +2006-11-27 Erez Zadok + + * doc/Makefile.am: obfuscate emails in ChangeLog before it is + published on web site. + + * obfuscate many more emails in the distro, esp. of files which get + posted on the am-utils web site. + +2006-11-26 Erez Zadok + + * minor new port: i386-apple-darwin8.8.1. + + * doc/am-utils.texi: remove obvious URLs used by spammers, and + replace them with links to the am-utils web site, which uses PNG + images to obfuscate the actual email/mailman URLs. + +2006-10-30 Erez Zadok + + * doc/am-utils.texi (Password maps): minor typo reported by + Christoph P. Kukulies. + +2006-10-26 Erez Zadok + + * minor new port: i386-pc-linux-fc6. + + * m4/macros/linux_headers.m4: handle newer Linux kernels which + removed UTS_RELEASE from . + +2006-10-25 Erez Zadok + + * minor new ports: i386-pc-linux-centos4.4 and + powerpc-apple-darwin8.7.0. + + * config.guess.long: recognize CentOS Linux. + +2006-06-20 Erez Zadok + + * minor new port: i386-pc-solaris2.11-nexentaos (GNU/OpenSolaris). + + * config.guess.long: recognize NexentaOS (GNU/OpenSolaris) + + * config.guess, config.sub: updates from latest official GNU + distributions. + 2006-05-11 Erez Zadok - ******************************************************************* - *** Released am-utils-6.1.5 *** - ******************************************************************* + * Minor new ports: i386-unknown-freebsd6.1 (RELEASE), + powerpc-apple-darwin8.6.0, and i386-unknown-openbsd3.9. 2006-05-10 Erez Zadok - * Minor new ports: i386-unknown-freebsd6.1 (RELEASE) - powerpc-apple-darwin8.6.0, and i386-unknown-openbsd3.9. - * libamu/mount_fs.c (compute_nfs_attrcache_flags): fix signedness problems on IRIX-6.5. @@ -188,11 +738,14 @@ same $ac_cv_* variable name). Some systems support one header or another. Patch inspired by work Debian did. -2006-02-10 Erez Zadok +2006-02-16 Daniel P. Ottavio - ******************************************************************* - *** Released am-utils-6.1.4 *** - ******************************************************************* + * amd/sum_map_tok.l: Fixed a bug in a regular expression that + prevented dashes in hostnames. This was posted in BZ by Thomas + A. Fine. + + * README.sun2amd: Fixed a typo. Sentence mentions use of autofs + type when it should be host type. 2006-01-04 Erez Zadok @@ -302,9 +855,31 @@ 2005-10-10 Erez Zadok ******************************************************************* - *** Released am-utils-6.1.3 *** + *** Released am-utils-6.1a1 *** ******************************************************************* + * README.sun2amd: revised. + +2005-10-09 Daniel P. Ottavio + + * amd/info_nis.c (nis_search): Bug fix for bugzilla #428; make + sure that sun_entry2amd() is not called when yp_match() returns an + error, this is done by checking that 'res' is 0. Bug fix (same + BZ#); free the output allocated by yp_match() instead of freeing + the return value of sun_entry2amd(). + + * amd/sun_map.c (sun_entry2amd): Fix a comment. + + * README.sun2amd: Made a first pass at describing the status of + the sun2amd feature. + Moved the date. + +2005-10-09 Erez Zadok + + * README.sun2amd: place holder. + + * Makefile.am (EXTRA_DIST): distribute new README.sun2amd file. + 2005-10-07 Erez Zadok * m4/macros/check_mnttab_type.m4: move the test for MOUNT_* to the @@ -343,6 +918,10 @@ * amd/info_exec.c (exec_map_open): break assignment from inside conditional, to work around an IRIX-6.5 cc bug. + * amd/Makefile.am (amd_LDADD, sun2amd_LDADD): put libaminfo.a + before libamu.la. Some linkers (e.g., IRIX-6.5) incorrectly + complain about undefined symbols. + * fsinfo/fsi_util.c (set_ether_if), amd/map.c (unmount_mp), libamu/xutil.c (expand_error), libamu/strutil.c (xsnprintf): avoid comparison between signed and unsigned integers. @@ -479,15 +1058,10 @@ 2005-10-02 Erez Zadok - * include/am_utils.h: extern for xvsnprintf(). - - * amd/autil.c: move strsplit() to libamu/strutil.c. - * libamu/Makefile.am: use strutil.c, not util.c. * libamu/strutil.c: rename from util.c to explain better purpose - of file. Move xvsnprintf and xsnprintf from xutil.c to this - file. Sync up with 6.2 version of file. + of file. Move xvsnprintf and xsnprintf from xutil.c to this file. * libamu/xutil.c: explain purpose of file. Move mkdirs/rmdirs code from old util.c. @@ -555,22 +1129,13 @@ 2005-09-26 Erez Zadok - * libamu/xutil.c (unregister_amq): repair broken meaning of D_AMQ, - which was reversed in am-utils-6.2. Bug fix from Steve Plite - . - * hlfsd/stubs.c (nfsproc_getattr_2_svc, nfsproc_lookup_2_svc, nfsproc_readlink_2_svc, nfsproc_readdir_2_svc), hlfsd/hlfsd.c (hlfsd_init): use new clocktime() function. 2005-09-18 Erez Zadok - ******************************************************************* - *** Released am-utils-6.1.2.1 *** - ******************************************************************* - - * README.attrcache: Update status of freebsd and openbsd. - Document netbsd's patchs to support noac. + * README.attrcache: document netbsd's patchs to support noac. * libamu/mount_fs.c (compute_nfs_attrcache_flags): cleanup the code that sets the ac{reg,dir}{min,max} fields so it also sets the @@ -578,13 +1143,10 @@ * configure.in: check for nfs_args fields acregmax and acdirmax. - ******************************************************************* - *** Released am-utils-6.1.2 *** - ******************************************************************* - * README.attrcache: new file documenting in detail OS bugs relating to attribute caching, which can affect Amd's reliability under heavy load. + Update status of freebsd and openbsd. * doc/Makefile.am: install README.attrcache file as attrache.txt file on am-utils Web site. @@ -665,6 +1227,54 @@ amfs_bgmount, amfs_generic_mount_child), amd/amd.c (main): pass NULL to clocktime(). +2005-09-15 Erez Zadok + + * amd/nfs_subr.c (nfsproc_getattr_2_svc): initialize 'retry', just + in case. + (fh_to_mp3): increment amd_stats.d_stale counter only if we are + actually returning ESTALE. + + * amd/info_exec.c (exec_parse_qanswer), amd/info_file.c + (file_search_or_reload), amd/info_hesiod.c (hesiod_search), + amd/info_ldap.c (amu_ldap_search), amd/info_ndbm.c (search_ndbm), + amd/info_nis.c (nis_search), amd/info_nisplus.c (nisplus_search, + nisplus_search): don't dereference mnt_map->cfm which may be null + if we're not using an amd.conf file. + +2005-09-14 Erez Zadok + + * libamu/xutil.c (unregister_amq): if failed to de-register Amd + from portmapper, report it under dlog (debugging), not as an + annoying plog that always shows up. + +2005-09-13 Erez Zadok + + * mk-amd-map/mk-amd-map.c (read_file_file), libamu/util.c + (strsplit), libamu/hasmntopt.c (nextmntopt), amd/sun_map.c + (sun_entry2amd), amd/sun2amd.c (sun2amd_convert_convert), + amd/mapc.c (mapc_add_kv), amd/info_file.c (file_search_or_reload), + amd/info_exec.c (exec_parse_qanswer): cast isspace() and isascii() + arg to unsigned char, which is safer as per Christos. + + * amd/sun_map.c (sun_entry2amd): isspace takes an int, not a char. + + * configure.in: keep a dummy unused AM_PROG_LEX, because old + Automake (1.6.3) looks for it if you refer to LEX in your + Makefile.am files. Silly thing, fixed in newer versions of + Automake (1.9.2). + +2005-09-11 Erez Zadok + + * Makefile.am (EXTRA_DIST_M4): add prog_{lex,yacc}.m4 to distro. + + * configure.in: use new macros AMU_PROG_YACC and AMU_PROG_LEX. + + * m4/macros/prog_yacc.m4: new macro to check if bison/yacc/byacc + exist, but exist with an error if none found. + + * m4/macros/prog_lex.m4: new macro to check if f/lex exist, but + exit with an error if not found (am-utils requires f/lex). + 2005-09-07 Erez Zadok * minor new port: powerpc-apple-darwin8.2.0. @@ -683,8 +1293,48 @@ file system on this system (probably because /proc isn't mounted), then provide some default definition for this file to compile. +2005-08-28 Daniel P. Ottavio + + * amd/sun_map.c (sun_entry2amd) : Wipe out any trailing white + spaces or '\n' before passing strings to the parser. + + * amd/amd.h : oops, reverting bad changes + + * amd/info_file.c : oops, reverting bad changes + + * amd/mapc.c : oops, reverting bad changes + + * amd/sun_map_parse.y : oops, reverting bad changes + 2005-08-27 Erez Zadok + * libamu/xutil.c: amd_program_number is a u_long now. + (unregister_amq): if pmap_unset failed to de-register Amd from the + portmapper, print an error message. + (get_amd_program_number): returns a u_long now. + (set_amd_program_number): take a u_long now. + + * include/am_utils.h: get_amd_program_number() returns u_long now. + set_amd_program_number() takes a u_long now. + + * amq/amq.c: amd_program_number is a u_long, not int. + + * amd/nfs_start.c (mount_automounter): when registering Amd with + the portmapper (for Amq service), don't fail if just one of TCP or + UDP failed to register, but only if both transports failed. That + way Amq can still contact Amd using the transport that did + register correctly. However, now, if both transports failed to + register, then set amd_state to "Done" so it would shutdown + cleanly. + + * conf/transp/transp_{sockets,tli{}.c (amu_svc_register): better + comments. + + * libamu/xutil.c: debug_flags should always be initialized to + D_CONTROL (amq,daemon,fork). + (debug_option): allow setting initial immutable debug_flags via + amd.conf; afterward, prevent it (i.e., one tries it via "amq -D"). + * Makefile.am (DISTCLEANFILES): also remove amu_autofs_prot.h, config.cache.old, and dbgcf.h on "make distclean". (CLEANFILES): remove dbgcf on plain "make clean". @@ -692,13 +1342,199 @@ * amd/Makefile.am (DISTCLEANFILES): also remove ops_autofs.c on "make distclean". +2005-08-27 Daniel P. Ottavio + + * amd/info_file.c (file_search_or_reload): Changed the key + variable that is passed to the sun_entry2amd. + + * amd/mapc.c (mapc_add_kv): Add support for multiple entries + packed into one line. This is a workaround for handling Sun style + mounts that contains multiple entries on one line: "multi-mount + entries". The sun2amd conversion tools will convert such entries + into type:=auto and pack each of the auto-entries into one line + separated by '\n'. The mapc_add_kv function will now recognize + such entries and add then. + + * amd/sun2amd.c (sun2amd_convert): Add print statement that + includes the line number during a parser failure. + + * sun_map.c: Fix the AMD_MAP_PREF_KW definition. Fix spelling. + (sun_mountpts2amd): removed this function + (sun_hsfs2amd): added some more comments + (sun_nfs2amd): moved support for multi-mount entries from this + function to sun_multi2amd(). + (sun_multi2amd): New function to handle multi-mount entries. This + function will convert the Sun version to an Amd type:=auto. Each + extra auto entry will be appended to the same line separated by a + '\n'. + (sun_entry2amd): Fixed a bug if-statement. This function now + checks for multi-mount entries. + + * amd/sun_map.h: Add a fstype member to the sun_mountpt struct. + + * amd/sun_map_parse.y: Parser now supports fstype for multi-mount + entries. + + * amd/sun_map_tok.l: No longer print the line and column number + when parsing. This is because the parser is handed strings not + files. Therefore, the line number will always be 1. It is now up + to the higher level tools to echo line information during error + when they feed the parser. + 2005-08-24 Erez Zadok * configure.in: wrap all LDAP and HESIOD tests in test whether --with-OPT was used. +2005-08-20 Daniel P. Ottavio + + * amd/sun_map.c: Clean up #defines + (sun_entry2amd) : Verify that the key and entry values passed are + not NULL. Free the Sun entry struct when done. + + * amd/sun_map.h: Add some "not implemented yet" comments to the + map and mmap structures. + + * amd/sun_map_parse.y: Removed automap include functionality, it + will need to be re-implemented using a pre-processor. + Clean up function calls. + +2005-08-16 Daniel P. Ottavio + + * amd/sun2amd.c (sun2amd_convert): If the input line is too long + don't return an error just null terminate and continue. Fix bug: + the map key was not written. + + * amd/sun_map.c: Add a new Amd device, and cdfs constant. + (sun_locations2amd): Write the NFS type keyword + for each host of the mount entry. Add a space between each mount + location. + (sun_hsfs2amd): New function to support hsfs to + cdfs. + (sun_nfs2amd): Don't write the nfs type here. Fix + comments. + (sun_entry2amd): Change function parameter var for + clarity. Add support for hsfs. + + * amd/sun_map_parse.y (sun_map_parse_read): Reset the entry list + after it has been returned. + 2005-08-16 Erez Zadok + * amd/get_args.c (get_args): initialize debug_flags if they've + never been set. + +2005-08-15 Erez Zadok + + * amd/mapc.c (mapc_create): mapc find takes 4th arg, the mount + point. Now, we can properly initialize the cfm structure of the + mnt_map, so we can have access to the flags (e.g., SUN_MAP_SYNTAX) + inside each info_*.c file. + (mapc_find): takes 4rd arg (mntpt) and passes it to calls to + mapc_create. + (root_newmap): pass NULL as 4th arg (mntpt). + + * amd/amfs_generic.c (amfs_parse_defaults): remove ugly hack to + initialize map cfm structure (including flags) so late. + + * amd/autil.c (amfs_mkcacheref): pass mount point as 4th arg to + mapc_find. + + * amd/amfs_root.c (amfs_root_mount): pass NULL as new 4th arg to + mapc_find. + + * amd/amd.h: extern for mapc_find changed to pass the mount point. + + * libamu/xutil.c: debug_flags should be unsigned. + (dbg_opt): fix comments for updated debug_flags, add "defaults". + (debug_option): Don't allow "immutable" (D_IMMUTABLE) flags to be + changed, because they could mess Amd's state and only make sense + to be set once when Amd starts. Currently these immutable flags + are "daemon," "fork," "amq," and "mtab." If Amd not compiled with + debugging, set default "control" options (daemon,fork,amq). + (unregister_amq): proper use of D_AMQ. + + * include/am_utils.h: define new D_BASIC, D_CONTROL, D_DEFAULT, + D_IMMUTABLE, and D_MASK. Updated definitions of D_ALL and D_TEST. + debug_flags extern should be unsigned. + + * scripts/amd.conf-sample (debug_options): mention new "defaults" + option. + + * scripts/amd.conf.5,doc/am-utils.texi: document new debug option + "defaults" and properly explain the corrected meanings of + "daemon," "fork," "amq," and their "no" inversions. Better + explain "all" and "test" too. Correct default debug_mtab file to + /tmp/mtab. + + * hlfsd/stubs.c (nfsproc_readlink_2_svc): proper use of D_FORK. + + * hlfsd/homedir.c (homedir): proper use of D_FORK. + + * hlfsd/hlfsd.c (main, hlfsd_init, cleanup): proper use of + D_DAEMON. + + * amd/nfs_start.c (mount_automounter): proper use of D_AMQ. + + * amd/amd.h (DEBUG_MNTTAB_FILE): change default to /tmp/mtab, + which is more common on more systems (instead of /tmp/mnttab). + + * amd/amd.c (main): properly use D_DAEMON. + +2005-08-14 Erez Zadok + + * libamu/xutil.c (xlog_opt): define new pseudo log_option named + "defaults", which is an alias for "fatal,error,user,warning,info". + + * scripts/amd.conf.5, doc/am-utils.texi, amd/amd.8: document new + log_option "defaults". + + * amq/amq.8: typo. Arg name for -D is "debug_options" not + "log_options". + + * libamu/xutil.c: make xlog_level static, and initialize it to + XLOG_DEFAULT. + (cmdoption): take unsigned int as flags argument, and print any + errors as XLOG_ERROR (which cannot be turned off). + (switch_option): remove old code which disallowed you from turning + off flags that were set when Amd started up. Now, you can turn + any log option on/off at start time or later on (via amq -x), + other than the two mandatory options (fatal+error). + + * include/am_utils.h (XLOG_*): remove unused XLOG_DEFSTR. Define + XLOG_MASK to mask out unused flag bits. Define XLOG_DEFAULT to be + what it was before (fatal + error + user + warning + info), but + use the new mask. Remove extern's for xlog_level and + xlog_level_init. Change extern for cmdoption() to take an + unsigned flags argument. + + * doc/am-utils.texi, amq/amq.8, scripts/amd.conf.5, amd/amd.8: + document mandatory log options + (fatal+error) which cannot be turned off and are always on by + default. They must be on so that Amd can report crucial errors, + including those related to setting flags on/off. + + * hlfsd/hlfsd.c (main): remove hack to initialize log_options. + + * wire-test/wire-test.c: remove reference to unused xlog_level. + + * amd/mapc.c (mapc_create): 'alloc' flags variable should be + unsigned. + + * amd/get_args.c (get_args): no need for hack using + xlog_level_init. + + * amd/Makefile.am: separate sources common to amd and sun2amd into + a special, locally-built only, static library called libaminfo.a. + + * libamu/xutil.c (real_plog, xsnprintf): call new xvsnprintf() + wrapper function. + (xvsnprintf): new function which already gets a va_list. This was + needed to avoid nesting va_list's (which apparently isn't + allowed). + + * include/am_utils.h: prototype for new xvsnprintf wrapper. + * configure.in: sinclude([vers.m4]) version number file. * vers.m4: new file to separate version number out of @@ -707,24 +1543,248 @@ * Makefile.am (EXTRA_DIST_M4): include vers.m4 in distro. +2005-08-14 Daniel P. Ottavio + + * amd/info_file.c: add key to sun_entry2amd()'s parameters + + * amd/info_hesiod.c: add key to sun_entry2amd()'s parameters + + * amd/info_ldap.c: add key to sun_entry2amd()'s parameters + + * amd/info_ndbm.c: add key to sun_entry2amd()'s parameters + + * amd/info_nis.c: add key to sun_entry2amd()'s parameters + + * amd/info_nisplus.c: add key to sun_entry2amd()'s parameters + + * amd/sun_map.c: New functions to support sun translation to amd. + The function sun_entry2amd's parameters were expanded to include + the key value. sun_entry_2amd() now returns NULL on error. + + * amd/sun_map.h: Expand sun_entry2amd's parameters to include key + value. + + * amd/sun_map_parse.y: Change how file system types are parsed out + of the list of options for each entry. The previous way was not + working properly so now we just look for the 'fstype' keyword in + each option. If it exists we copy its key value. + Added some comments to sun_map_parse_read(). + + * amd/amd.h: Added an extern from info_file.c called + file_read_line(). Previously this function was static but is now + used in sun2amd.c. + + * amd/info_file.c: Changed the static function read_line() to a + public function called file_read_line(). This function is now + used in sun2amd.c + + * amd/sun2amd.8: Filled in the contents of this man page. This is + a conversion utility that converts Sun maps to Amd maps. + + * amd/sun2amd.c: Implemented a working version of this utility. + 2005-08-11 Erez Zadok + * amd/sun_map_parse.y: instead of using a custom FOO_alloc() + function, use Amd's CALLOC(struct FOO) macro. + + * amd/sun_map.h: remove extern definitions to functions no longer + needed. + + * amd/sun_map.c: removed superfluous *_alloc() functions, some of + which caused conflicts with same-named symbols in the parser + (since we rename 'yyalloc' to 'sun_map_alloc'). + * configure.in: keep AC_INIT on same line, for nightly snapshot build script. + * amd/Makefile.am: f/lex libraries are incompatible with multiple + scanners, so don't link Amd with libl.a/libfl.a. + +2005-08-10 Daniel P. Ottavio + + * amd/sun_map_tok.l: Clean up regular expression so HPUX stops + whining. + +2005-08-09 Daniel P. Ottavio + + * amd/sun_map_parse.y: Moved license below special yacc bracket to + be portable with HPUX's yacc. Clean up externs. + + * amd/sun_map_tok.l: Moved license below special lex bracket to be + portable with HPUX's lex. Fixed definitions to allow for a + non-flex lex to parse strings instead of files. Added some casts + to strlcpy usage to silence warnings. Moved the % options because + HPUX was complaining, + +2005-08-08 Daniel P. Ottavio + + * amd/sun_map_tok.l: Applied some definition goop to handle the + ECHO symbol that lex defines. This symbol causes problems on + RedHat-EL-powerPC platforms. Replaced strncpy with strlcpy. + Renamed the function sun_map_yyinput to sun_map_input. This + function is a utility function that is not generated by lex. + Therefore, the 'yy' may cause confusion. + +2005-08-08 Erez Zadok + + * amd/sun_map_tok.l: allocate more output slots so lex scanners + don't run out of memory. + + * amd/sun_map_parse.y: declare extern for sun_map_parse(). + + * libamu/xutil.c (xsnprintf): ensure proper comparisons between + signed and unsigned quantities. + 2005-08-06 Erez Zadok + * libamu/util.c, amd/autil.c (strsplit): moved strsplit() function + from Amd code to to libamu, so sun2amd could use it. + + * amd/Makefile.am (sbin_PROGRAMS): build sun2amd binary and man + page. + (EXTRA_sun2amd_OBJECTS): sun2amd needs to link with all info_*.c files + + * amd/sun2amd.8: placeholder for man page. + + * amd/sun2amd.c: placeholder for C version of translator from Sun + syntax maps to Amd maps. + + * */*.[0-9]: include file name in nroff source comment. + + * ALL: use '0' properly when assigning or passing it to functions. + If in the context pointer, use NULL. If in the context of a + single char (say within a string), the use '\0'. This is just to + make the code clearer. + + * m4/macros/header_templates.m4: template for HAVE_MAP_SUN. + + * amd/mapc.c (maptypes): add placeholder for Sun-syntax map + methods. + + * amd/Makefile.am (EXTRA_amd_SOURCES): compile info_sun.c + + * amd/info_sun.c: placeholder for meta info parser to get info + from Sun automount-style /etc/auto_master, possibly following + into multiple info services (via /etc/nsswitch.conf). + + * libamu/xutil.c (xsnprintf): if vsnprintf truncated the output + string to avoid an overflow, print an error. Include some code to + break out any possible infinite loop between plog() and + xsnprintf(). + (real_plog): now we can use (carefully) xsnprintf() directly. + + * amd/sun_map.[hc]: cleanup and formatting. + + * amd/sun_map_parse.y: to match the literal string "fstype=" use + double quotes, not single quotes. + + * amd/get_args.c (get_args): call conf_parse() using conf_in. + + * amd/amd.h: use renamed parser symbols (yyparse -> conf_parse; + yyin -> conf_in). + + * ylwrap: Enhance wrapper to avoid the #define hacks done by Gdb, + and suggested by the Automake manual. This enhanced parser will + prefix each conflicting yacc/lex symbol with a unique name + produced from INPUT. For example, if INPUT is foo_parse.y, then + yyparse() becomes foo_parse(). This requires that both your .l + and corresponding .y files have the same prefix (e.g., foo_parse.y + and foo_tok.l). + + * amd/Makefile.am (BUILT_SOURCES): define which yacc/lex .h/.c + source files are built automatically, and therefore should not be + in the distro (IMHO), and should be cleaned upon "make clean". + (amd_SOURCES): include new sun_map_parse.y and sun_map_tok.l files. + + * ylwrap: new file needed because we have two parsers now. + + * amd/sun_map_{parse.y,tok.l}: cleanup and formatting. + +2005-08-06 Daniel P. Ottavio + + * amd/Makefile.am: Added new files sun_map.h, sun_map.c, + sun_map_parse.y, and sun_map_tok.l. These files add support for + parsing Sun style maps. The yacc/lex files needed custom rules so + they don't cause symbol conflicts with each other. + + * amd/amd.h: Added "#define INFO_MAX_LINE_LEN" that specifies the + line limit for info services. + + * amd/info_exec.c: Replaced MAX_LINE_LEN with INFO_MAX_LINE_LEN + + * amd/info_file.c: Replaced MAX_LINE_LEN with INFO_MAX_LINE_LEN, + added support for parsing Sun style maps. The support for Sun + maps is done using the sun_entry2amd() function. This function is + called for each entry line that is read only when Sun parsing is + enabled. For each entry line that is passed to the function a + copy of the Amd equivalent is returned. + + * amd/sun_map.h: new header file for Sun style map support + + * amd/sun_map.c: new source file for Sun style map support, clean + up comments, additional sun2amd conversion routines + + * amd/sun_map_parse.y: new yacc file for parsing Sun style maps, + fix copyright notice, put filename below license. + + * amd/sun_map_tok.l: new lex file for parsing Sun style maps, fix + copyright notice, put filename below license. + + * amd/get_args.c: replace usage of strlcat with xstrlcat + + * include/am_utils.h: added 'extern void xstrlcat()' + + * libamu/util.c: Added a xstrlcat() function that wraps the + syscall strlcat() so that string truncations can be logged. + +2005-08-06 Erez Zadok + + * amd/info_file.c (file_search, file_reload): pass mnt_map to + file_search_or_reload. + (file_search_or_reload): ensure that mnt_map is never NULL. + + * amd/info_nis.c (nis_search): call sun_entry2amd() if + sun_map_syntax=yes. + + * amd/info_ldap.c (amu_ldap_search): call sun_entry2amd() if + sun_map_syntax=yes. + + * amd/info_hesiod.c (hesiod_search): call sun_entry2amd() if + sun_map_syntax=yes. + + * amd/info_ndbm.c (ndbm_search): pass mnt_map to search_ndbm. + (search_ndbm): call sun_entry2amd() if sun_map_syntax=yes. + + * amd/info_nisplus.c (nisplus_search): call sun_entry2amd() if + sun_map_syntax=yes. + + * amd/info_exec.c (exec_search): pass mnt_map to + exec_parse_qanswer. + (exec_parse_qanswer): call sun_entry2amd() if sun_map_syntax=yes. + + * doc/am-utils.texi (sun_map_syntax Parameter): document new + common parameter. + * scripts/amd.conf.5: selectors_in_defaults is a common parameter, not just [global]. Use consistent capitalization of Amd/Amq. + Document new sun_map_syntax parameter. * scripts/amd.conf-sample: properly list all of the parameters which are common to both the [global] and the per-map sections. + (sun_map_syntax): example of new parameter. * doc/am-utils.texi (Common Parameters): selectors_in_defaults is a common parameter, not just [global]. * scripts/amd.conf-sample (sun_map_syntax): example of new flag. + * amd/conf.c ({ropt,gopt}_sun_map_syntax): new function to parse + sun_map_syntax flag (global or per map). + + * amd/amd.h (CFM_SUN_MAP_SYNTAX): new flag for users to say if the + map uses Sun automounter syntax. + * cvs-server.txt: update instructions after branching 6.1-stable. 2005-08-02 Erez Zadok diff --git a/contrib/amd/FAQ b/contrib/amd/FAQ index 18e73a3fab2..3fbcb4cdb1d 100644 --- a/contrib/amd/FAQ +++ b/contrib/amd/FAQ @@ -26,7 +26,7 @@ answer your questions, see information in the following sources: listed in bugzilla in https://bugzilla.am-utils.org/ If you have additions to this FAQ, please let us know at -am-utils@am-utils.org. +the am-utils list (see www.am-utils.org). Thank you, The Am-utils development team. diff --git a/contrib/amd/INSTALL b/contrib/amd/INSTALL index 273fe02f454..2099840756e 100644 --- a/contrib/amd/INSTALL +++ b/contrib/amd/INSTALL @@ -1,124 +1,370 @@ - am-utils 6.1 compatibility list +Installation Instructions +************************* -For each system, list if it autoconfigures, compiles, or runs. Fill in -email id of person who confirms the fact. A missing entry means unverified. -A 'no' or 'X' means verified broken or nonexistent (static library). +Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, +Inc. -SYSTEM CONFIG COMPILE RUN SHLIB AUTOFS -========================= ======= ======= ======= ======= ====== -alpha-dec-osf4.0f ro ro ro - - -alpha-dec-osf5.1 ro ro ro - - -alpha-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk - -alphaev56-dec-osf4.0f ezk ezk ezk ezk - -i386-apple-darwin6.0 ezk ezk ezk ezk - -i386-pc-bsdi2.1 ion ion ion ion[X] ion[X] -i386-pc-linux-deb3.0 ezk ezk ezk ezk - -i386-pc-linux-deb3.1 ezk ezk ezk ezk - -i386-pc-linux-fc1 ezk ezk ezk ezk - -i386-pc-linux-fc2 ezk ezk ezk ezk - -i386-pc-linux-fc3 ezk ezk ezk ezk - -i386-pc-linux-fc4 ezk ezk ezk ezk - -i386-pc-linux-gentoo1.4.16 ezk ezk ezk ezk - -i386-pc-linux-rh6.2 ion ion ion ion ion -i386-pc-linux-rh7.1 ion ion ion ion ion -i386-pc-linux-rh7.2 ion ion ion ion ion -i386-pc-linux-rh7.3 ion ion ion ion ion -i386-pc-linux-rh8.0 ezk ezk ezk ezk - -i386-pc-linux-rh9 ion ion ion ion ion -i386-pc-linux-rhel3 ezk ezk ezk ezk - -i386-pc-linux-rhel4 ezk ezk ezk ezk - -i386-pc-linux-suse8.2 ezk ezk ezk ezk - -i386-pc-linux-suse9.1 ezk ezk ezk ezk - -i386-pc-linux-suse9.2 ezk ezk ezk ezk - -i386-pc-linux-suse9.3 ezk ezk ezk ezk - -i386-pc-solaris2.10 ro ro ro - - -i386-pc-solaris2.9 ro ro ro - - -i386-unknown-freebsd4.10 ezk ezk ezk ezk - -i386-unknown-freebsd4.11 ezk ezk ezk ezk - -i386-unknown-freebsd4.8 ezk ezk ezk ezk - -i386-unknown-freebsd4.9 ezk ezk ezk ezk - -i386-unknown-freebsd5.0 ezk ezk - ezk - -i386-unknown-freebsd5.1 ezk ezk ezk ezk - -i386-unknown-freebsd5.2 ezk ezk ezk ezk - -i386-unknown-freebsd5.2.1 ezk ezk ezk ezk - -i386-unknown-freebsd5.3 ezk ezk ezk ezk - -i386-unknown-freebsd5.4 ezk ezk ezk ezk - -i386-unknown-freebsd6 (BETA5) ezk ezk ezk ezk - -i386-unknown-netbsd1.6A ezk ezk ezk ezk - -i386-unknown-netbsdelf1.6.1 ezk ezk ezk ezk - -i386-unknown-netbsdelf1.6.2 ezk ezk ezk ezk - -i386-unknown-netbsdelf2.0 ezk ezk ezk ezk - -i386-unknown-netbsdelf2.0.2 ezk ezk ezk ezk - -i386-unknown-netbsdelf3.0 ezk ezk ezk ezk - -i386-unknown-openbsd3.3 ezk ezk ezk ezk - -i386-unknown-openbsd3.6 ezk ezk ezk ezk - -i386-unknown-openbsd3.7 ezk ezk ezk ezk - -i686-apple-darwin6.6 ezk ezk ezk ezk - -ia64-hp-hpux11.20 ezk ezk ezk ezk - -ia64-unknown-linux-rh2.1AS ezk ezk - ezk - -ia64-unknown-linux-rh2.1AW ezk ezk ezk ezk - -ia64-unknown-linux-rhel4 ezk ezk ezk ezk - -mips-sgi-irix6.2 ro ro ro - -[3] -mips-sgi-irix6.5 ro ro ro - -[3] -mips-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk - -mipsel-unknown-linux-rhPS2 ezk ezk ezk ezk - -powerpc-apple-darwin7.6.0 ezk ezk ezk ezk - -powerpc-apple-darwin7.7.0 ezk ezk ezk ezk - -powerpc-apple-darwin7.8.0 ezk ezk ezk ezk - -powerpc-apple-darwin7.9.0 ezk ezk ezk ezk - -powerpc-apple-darwin8.2.0 ezk ezk ezk ezk - -powerpc-ibm-aix5.1.0.0 ion ion ion ion[X] ion[1,2] -powerpc-ibm-aix5.2.0.0 ezk ezk ezk ezk - -powerpc-ibm-aix5.3.0.0 ezk ezk ezk ezk - -powerpc-unknown-linux-yellowdog2.3 ezk ezk ezk ezk - -sparc-sun-solaris2.10 ro ro ro - - -sparc-sun-solaris2.5.1 ion ion ion ion ion[1] -sparc-sun-solaris2.6 ion ion ion ion ion -sparc-sun-solaris2.7 ion ion ion ion ion -sparc-sun-solaris2.8 ion ion ion ion ion -sparc-sun-solaris2.9 ro ro ro - - -sparc-unknown-linux-rh62 ion ion ion ion ion -sparc64-unknown-linux-aurora10 ion ion ion ion ion -sparc64-unknown-linux-deb3.0 ezk ezk ezk ezk - -sparc64-unknown-linux-gentoo1.4.16 ezk ezk ezk ezk - -sparc64-unknown-linux-rh62 ion ion ion ion ion -sparc64-unknown-linux-suse7.3 ezk ezk - ezk - -x86_64-unknown-linux-rh2.9.5AS ezk ezk ezk ezk - -x86_64-unknown-linux-rh3.0.0AS ion ion ion ion ion + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. +Basic Installation +================== -EMAIL ID LEGEND: + Briefly, the shell command `./configure && make && make install' +should configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. -bking: Bevis R W King -dsr: Dan Riley -ezk: Erez Zadok -finkel: Raphael Finkel -ion: Ion Badulescu -jose: Jose Nazario -nrh: Nick Hall -ro: Rainer Orth -stolke: Andreas Stolcke -wpaul: Bill Paul + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. -FOOTNOTES: + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. -[1] Due to limitations in the Sun autofs v1 implementation, some amd features -cannot be properly supported. More precisely, trying to access a link mount -pointing to another amd entry will result in failure and/or deadlock. -Ordinary nfs and link mounts work well, however. + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. -[2] AIX autofs appears to be a variant of the Sun autofs v1 protocol, but -IBM don't provide any sort of documentation or even header files from it. -It is currently unsupported; we may add some experimental support for it at -some point, though it won't be pretty. Assistance from IBM-ers would be -highly appreciated, hint hint. + The simplest way to compile this package is: -[3] IRIX 6 autofs uses the Sun autofs v1 protocol, too. The header files -are part of the onc3_eoe.sw.autofs (IRIX 6.2) or nfs.sw.autofs (IRIX 6.5) -package, which may not be installed. The autofs code is known to compile, -but hasn't been run yet. SGI's autofsd uses a barely documented system -call, syssgi(SGI_AUTOFS_SYS, ...), which may be required to get working -autofs support. Additional help from SGI would be highly appreciated. + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. -Erez & Ion + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf limitation. Until the limitation is lifted, you can use +this workaround: + + CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/contrib/amd/MIRRORS.html b/contrib/amd/MIRRORS.html index 0deeefe32c7..511df2b905c 100644 --- a/contrib/amd/MIRRORS.html +++ b/contrib/amd/MIRRORS.html @@ -11,8 +11,8 @@ Note: in case of any problems accessing the individual FTP sites, please contact their respective maintainers. If you wish to be added to the -official mirror list, please send mail to am-utils-developers@am-utils.org with the +official mirror list, please send mail to +"am-utils-developers AT am-utils.org" with the full URL, maintainer's email, and geographical location.

@@ -24,8 +24,8 @@ full URL, maintainer's email, and geographical location.

@@ -33,14 +33,14 @@ full URL, maintainer's email, and geographical location.
  • Florida (University of Florida) @@ -52,24 +52,24 @@ full URL, maintainer's email, and geographical location.
  • Germany
  • Sweden
  • UK @@ -81,21 +81,21 @@ full URL, maintainer's email, and geographical location.
  • Japan
    - Last updated: Jan 5, 2004 + Last updated: 2006-11-27 diff --git a/contrib/amd/MIRRORS.txt b/contrib/amd/MIRRORS.txt index b5093e8f4aa..087c6ccd0cc 100644 --- a/contrib/amd/MIRRORS.txt +++ b/contrib/amd/MIRRORS.txt @@ -2,59 +2,59 @@ Note: in case of any problems accessing the individual FTP sites, please contact their respective maintainers. If you wish to be added to the -official mirror list, please send mail to am-utils-developers@am-utils.org +official mirror list, please send mail to am-utils-developers AT am-utils.org with the full URL, maintainer's email, and geographical location. U.S.A: New York (Stony Brook, Primary Site): ftp://ftp.am-utils.org/pub/am-utils - Maintainer: ezk@am-utils.org + Maintainer: ezk AT am-utils.org Minnesota: ftp://ftp.cs.umn.edu/pub/am-utils - Maintainer: dokas@cs.umn.edu + Maintainer: dokas AT cs.umn.edu #Avoid for now: empty directory # Virginia (Newport News): # ftp://ftp.ferginc.com/pub/unix/am-utils -# Maintainer: Branson.Matheson@FergInc.com +# Maintainer: Branson.Matheson AT FergInc.com #server gone? (Jan 5, 2004) # Ohio (Kent State University): # ftp://info.mcs.kent.edu/pub/am-utils -# Maintainer: root@mcs.kent.edu +# Maintainer: root AT mcs.kent.edu Florida (University of Florida) ftp://ftp.cise.ufl.edu/pub/mirrors/am-utils - Maintainer: mirror@cise.ufl.edu + Maintainer: mirror AT cise.ufl.edu Europe: Germany: ftp://ftp.fu-berlin.de/unix/network/am-utils - Maintainer: ftp-adm@ftp.fu-berlin.de + Maintainer: ftp-adm AT ftp.fu-berlin.de Germany: ftp://ftp.tu-darmstadt.de/pub/networking/filesystems/am-utils/ - Maintainer: networking@ftp.tu-darmstadt.de + Maintainer: networking AT ftp.tu-darmstadt.de Sweden: ftp://ftp.sunet.se/pub/unix/admin/am-utils - Maintainer: archive@ftp.sunet.se + Maintainer: archive AT ftp.sunet.se # not responding (Jan 5, 2004) # Sweden (Stockholm University, Math Depat): # ftp://mirror.matematik.su.se/pub/am-utils -# Maintainer: leifj@matematik.su.se +# Maintainer: leifj AT matematik.su.se UK: ftp://sunsite.org.uk/package/am-utils - Maintainer: lmjm@icparc.ic.ac.uk + Maintainer: lmjm AT icparc.ic.ac.uk Asia: Japan: ftp://ftp.u-aizu.ac.jp/pub/net/amd/am-utils - Maintainer: ftp-admin@u-aizu.ac.jp + Maintainer: ftp-admin AT u-aizu.ac.jp Japan: ftp://core.ring.gr.jp/pub/net/am-utils/ - Maintainer: ftpadmin@ring.gr.jp + Maintainer: ftpadmin AT ring.gr.jp Japan: ftp://ftp.ring.gr.jp/pub/net/am-utils/ - Maintainer: ftpadmin@ring.gr.jp + Maintainer: ftpadmin AT ring.gr.jp # gone? (Jan 5, 2004) # Australia: # Melbourne: # ftp://ftp.sage-au.org.au/pub/network/filesystem/am-utils -# Maintainer: mirror@ftp.sage-au.org.au +# Maintainer: mirror AT ftp.sage-au.org.au diff --git a/contrib/amd/NEWS b/contrib/amd/NEWS index 5cde984ed51..b7fbedac6d0 100644 --- a/contrib/amd/NEWS +++ b/contrib/amd/NEWS @@ -1,4 +1,44 @@ -*** Notes specific to am-utils version 6.1.5 +*** Notes specific to am-utils version 6.2 + + - Removed license advertising clause + - Removed expn program + +*** Notes specific to am-utils version 6.2-rc1 + +Filesystem Support: + - Add support for NFSv4 + - Add support for Lustre + - Add support for ext{2,3,4} + - Add support for linux autofs version 5 + - Add support for TMPFS and UDF +New features: + - Add amq -i (prints information about maps) + - Add synchronous unmount code for amq -uu + - Allow a comma-separated list of LDAP servers for failover +Changes in behavior: + - Empty variable assignments, now unset the variable value. + - Share LDAP connections between different maps to save resources +Portability fixes: + - Changes to work with Linux-2.6.x, Linux-3.x and NetBSD-5.x, NetBSD-6.x, + FreeBSD 7.x, Solaris +Bug fixes: + - Many bug fixes, see ChangeLog + +*** Notes specific to am-utils version 6.2a3 + +- minor new ports: + i386-apple-darwin8.8.1 + i386-pc-linux-centos4.4 (RHEL4 clone) + i386-pc-linux-fc6 (Fedora Core 6) + i386-pc-solaris2.11-nexentaos (GNU/OpenSolaris) + ia64-hp-hpux11.23 (gcc and cc) + powerpc-apple-darwin8.7.0 + +- Bugs fixed: + * reduce annoying warnings from xstrlcpy when expanding options. + * translate '*' Sun maps correctly with "${key}" + +*** Notes specific to am-utils version 6.2a2 New amd.conf global parameter: nfs_allow_any_interface. By default it is set to 'no' which means that Amd accepts local NFS packets only from @@ -11,21 +51,6 @@ Add support for specifying the host to match in the mount selectors netgrp and netgrpd. Now one can use either netgrp() or netgrp(,). -- Bugs fixed: - * handle old-style filehandles correctly (for mount points longer - than 28 chars) - * don't turn off attribute cache for regular NFS mounts (improves - performance) - * detect G/DBM support via gdbm_compat library (Debian) - * detect NDBM support in libc (FreeBSD 6) - -- minor new ports: - i386-unknown-freebsd6.1 (RELEASE) - i386-unknown-openbsd3.9 - powerpc-apple-darwin8.6.0 - -*** Notes specific to am-utils version 6.1.4 - Support new mount options for type:=pcfs mounts: longname, nowin95, shortname, user=N, group=N, mask=N, and dirmask=N. @@ -41,44 +66,28 @@ better tune Amd's responsiveness under heavy scheduler loads. i386-pc-linux-fc5 (Fedora Core 5) i386-pc-linux-suse10.1 (beta 8) i386-unknown-freebsd6.0 (RELEASE) + i386-unknown-freebsd6.1 (RELEASE) i386-unknown-netbsdelf2.1 i386-unknown-netbsdelf3.0 (RELEASE) i386-unknown-openbsd3.8 + i386-unknown-openbsd3.9 powerpc-apple-darwin8.5.0 + powerpc-apple-darwin8.6.0 - Bugs fixed: * one serious memory leak in amfs_generic (caught by Coverity) * assorted potential (but rare) NULL pointer dereferences (Coverity) * correctly print nfs_args->addr info (sin_family/port/addr) * pawd should resolve path repeatedly until no more to do + * handle old-style filehandles correctly (for mount points longer + than 28 chars) * use-after-free bug in amfs_lookup_mntfs (Coverity) + * don't turn off attribute cache for regular NFS mounts (improves + performance) + * detect G/DBM support via gdbm_compat library (Debian) + * detect NDBM support in libc (FreeBSD 6) -*** Notes specific to am-utils version 6.1.3 - -- Bugs fixed: - * amq should de-register properly on exit - * convert all sprintf to safer xsnprintf - * convert all strcat to safer xstrlcat - * convert all strcpy to safer xstrlcpy - * fix three buffer overruns in expand_op (amd/opts.c) - * pawd was trying UDP only, now try TCP if UDP failed - -Moved pawd's path-matching functionality into Amd, where it can be done a -lot more efficiently (we no longer need to construct and send the whole -mounted tree, only to match small parts of it). This will lessen the CPU -and network load on systems that use pawd heavily, and also minimize the -chance that we exceed default or hard-coded UDP/TCP RPC packet sizes. - -*** Notes specific to am-utils version 6.1.2.1 - -- Bugs fixed: - * properly turn off the attrcache in freebsd and openbsd - * can turn off attrcache on netbsd, but need kernel patch, see - README.attrcache - * pawd goes into an infinite loop on type:=auto - * consistent search for file system mnttab/mount names - -*** Notes specific to am-utils version 6.1.2 +*** Notes specific to am-utils version 6.2a1 MAJOR BUG FIXES: Synchronize Amd's view of its file systems with the kernel's NFS client-side DNLC/dcache. Amd changes its view when it reloads @@ -114,13 +123,82 @@ Amd. Tell syslog not to log automatically to /dev/console; it's unfriendly. If user really wants to, they can set it in /etc/syslog.conf. +Moved pawd's path-matching functionality into Amd, where it can be done a +lot more efficiently (we no longer need to construct and send the whole +mounted tree, only to match small parts of it). This will lessen the CPU +and network load on systems that use pawd heavily, and also minimize the +chance that we exceed default or hard-coded UDP/TCP RPC packet sizes. + +Changed slightly how Amd behaves when you try to change log_options after +Amd started (options can be turned on/off via "amq -x ARG"). It used to be +that Amd won't let you turn off options which were on when Amd started. +That limited users' ability to reduce Amd's logging levels to a minimum. +Now, Amd will allow you to turn on/off any option, other than the two +options "fatal" and "error." Both are on by default and considered +mandatory. These two don't produce a lot of log messages, so your logs will +remain small, but they are important to keep on, so Amd can report serious +problems (including errors relating to incorrectly setting other log +options). + +Amd now understands a new log_option called "defaults" which is synonymous +with "fatal,error,user,warning,info" (and is also what logging happens by +default). + +Amd now understands a new debug_option called "defaults" which is synonymous +with "all,nohrtime,nomtab,noxdrtrace". + +Changed the misleading inverted logic of certain debug_options: + +1. "xdrtrace" is included in "all" because "all" (as the name implies), + should be *all* options, not just a subset. If you want the old behavior + of "all" then use "defaults" (all only adds "xdrtrace" which can be + chatty on some systems). + +2. Certain debug options are hereby declared immutable: they may not be + changed by "amq -D" after Amd starts, because it doesn't make much sense + to change them after Amd starts, and it could really mess up Amd. These + immutable flags are currently "daemon," "fork," "amq," and "mtab." + +3. the debug option "daemon" *will* cause Amd to daemonize. Before, it was + causing Amd NOT to daemonize. This was greatly confusing, especially + since the code, documentation, and comments often conflicted with each + other. If you don't want Amd to daemonize, which is useful for debugging + it, then use the debug option "nodaemon" -- it makes a lot more sense. + +4. Similarly, the "fork" option *will* cause Hlfsd to fork. Use "nofork" if + you don't want Hlfsd to fork. This option is only applicable to Hlfsd. + +5. Similarly, the "amq" option, which is now on by default, will cause Amd + to register itself with the RPC portmapper (for Amq), as is done + normally. If you don't want Amd to register with the portmapper, use + "noamq" -- this naming convention makes more sense. This was also + confusingly documented and coded in places. + + Note: unfortunately, these changes to the "daemon," "fork," and "amq" + debug options may be incompatible with people's previous use of Amd. + Some of you may have to update your amd.conf slightly or your startup + options (if they're hard-coded in your amd startup script). Sorry, but + we have to fix those old problems sooner or later. However, if you never + set any debug_options, or you used to "all," then you won't be affected + by the change in meaning of these three flags. + - minor new ports: i386-pc-linux-deb3.1 - i386-unknown-netbsdelf3.0 + i386-unknown-netbsdelf3.0 (BETA) powerpc-apple-darwin8.2.0 -- bugs fixed: - * minor documentation corrections +- Bugs fixed: + * abort with an error if yacc/lex programs not found + * properly turn off the attrcache in freebsd and openbsd + * can turn off attrcache on netbsd, but need kernel patch, see + README.attrcache + * pawd goes into an infinite loop on type:=auto + * consistent search for file system mnttab/mount names + * convert all sprintf to safer xsnprintf + * convert all strcat to safer xstrlcat + * convert all strcpy to safer xstrlcpy + * fix three buffer overruns in expand_op (amd/opts.c) + * pawd was trying UDP only, now try TCP if UDP failed *** Notes specific to am-utils version 6.1.1 @@ -328,7 +406,7 @@ version (10.3.x) than uname(3) reports. Useful with firewalls and NAT'ed environments. - new amd.conf option "debug_mtab_file". Allows user to define the mtab - file during debug-mtab mode. The default path is "/tmp/mnttab". + file during debug-mtab mode. The default path is "/tmp/mtab". - new function selector xhost(ARG) which will match ARG against the current host name. This works even if ARG is a CNAME (unlike the host==ARG diff --git a/contrib/amd/README b/contrib/amd/README index 0b3ce46beb6..4b4aec0e8c0 100644 --- a/contrib/amd/README +++ b/contrib/amd/README @@ -81,7 +81,7 @@ or ./buildall -K To be a developer and be able to run "bootstrap", you must have -autoconf-2.50, automake-1.5, and libtool 1.4 installed on your system (or +autoconf-2.68, automake-1.11.1, and libtool 2.2.6b installed on your system (or later versions thereof). You no longer need to get my special version of automake. Contact me if you'd like to be a maintainer and get access to the CVS server. @@ -94,9 +94,9 @@ before. Let me know if you are having any problems with them. I fully expect, at least initially, to have to be the sole developers of the M4 macros and let others concentrate on C sources. -[E] Report all bugs to am-utils@am-utils.org. Avoid reporting to my -personal email address. It is important to involve the whole list in bug -fixes etc. +[E] Report all bugs via Bugzilla or the am-utils list (see +www.am-utils.org). Avoid reporting to my personal email address. It is +important to involve the whole list in bug fixes etc. Good luck. diff --git a/contrib/amd/README.attrcache b/contrib/amd/README.attrcache index e8522d226eb..7bd10874bf8 100644 --- a/contrib/amd/README.attrcache +++ b/contrib/amd/README.attrcache @@ -122,8 +122,8 @@ OS. You can run this script as root as follows: # sh test-attrcache If you run this script on an OS whose status is known (and not listed -above), please report it to am-utils@am-utils.org, so we can record it in -this file. +above), please report it to us via Bugzilla or the am-utils mailing list +(see www.am-utils.org), so we can record it in this file. Sincerely, Erez. diff --git a/contrib/amd/README.ldap b/contrib/amd/README.ldap index 71511344255..24095cafa9c 100644 --- a/contrib/amd/README.ldap +++ b/contrib/amd/README.ldap @@ -1,12 +1,12 @@ LDAP support for am-utils was originally done by Leif Johansson -. He no longer maintains it. +. He no longer maintains it. The current LDAP support for am-utils is for LDAPv2 only. Reportedly, LDAPv3 mostly works. Volunteers and patches are welcome. The IANA has assigned the following Private Enterprise Number to: - 10180 Am-utils Organization Erez Zadok ezk@am-utils.org + 10180 Am-utils Organization Erez Zadok ezk AT am-utils.org There are three files in this directory that relate to LDAP: @@ -33,8 +33,8 @@ Erez. ------- Forwarded Message -From: "IANA Private Enterprise Number" -To: "Erez Zadok" +From: "IANA Private Enterprise Number" +To: "Erez Zadok" Subject: RE: Application for Enterprise-number (10180) Date: Sun, 15 Jul 2001 14:43:45 -0700 @@ -43,7 +43,7 @@ Dear Erez, The IANA has assigned the following Private Enterprise Number to: -10180 Am-utils Organization Erez Zadok ezk@am-utils.org +10180 Am-utils Organization Erez Zadok ezk AT am-utils.org Please notify the IANA if there is a change in your contact or company information. diff --git a/contrib/amd/README.y2k b/contrib/amd/README.y2k index e75bd122590..b0b887c500a 100644 --- a/contrib/amd/README.y2k +++ b/contrib/amd/README.y2k @@ -8,10 +8,10 @@ all, because it does not do anything with dates other than print the date on the log file, in whatever format is provided by your os/libc --- especially the ctime(3) call. -However, on Friday, September 18th 1998, Matthew Crosby +However, on Friday, September 18th 1998, Matthew Crosby reported that they evaluated 6.0a16 and found it to be compliant. -On March 26, 1999, Paul Balyoz submitted a +On March 26, 1999, Paul Balyoz submitted a patch to lostaltmail which makes it print Y2K compliant dates. He used a code scanner and manually "eyeballed" the code and could not find any more problems. Paul's patch is included in am-utils-6.0.1s7 and newer versions. @@ -23,5 +23,4 @@ CERTIFY AM-UTILS AS Y2K COMPLIANT. USE AT YOUR OWN RISK. --- Erez Zadok. Maintainer, am-utils package and am-utils list. -Email: am-utils@am-utils.org WWW: http://www.am-utils.org diff --git a/contrib/amd/amd/am_ops.c b/contrib/amd/amd/am_ops.c index 5a5c33650ec..4d07dc807d9 100644 --- a/contrib/amd/amd/am_ops.c +++ b/contrib/amd/amd/am_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -96,6 +92,11 @@ static am_ops *vops[] = #ifdef HAVE_FS_XFS &xfs_ops, /* Unix (irix) F/S */ #endif /* HAVE_FS_XFS */ +#ifdef HAVE_FS_EXT + &ext2_ops, /* Unix (linux) F/S */ + &ext3_ops, /* Unix (linux) F/S */ + &ext4_ops, /* Unix (linux) F/S */ +#endif /* HAVE_FS_EXT */ #ifdef HAVE_FS_EFS &efs_ops, /* Unix (irix) F/S */ #endif /* HAVE_FS_EFS */ @@ -111,6 +112,9 @@ static am_ops *vops[] = #ifdef HAVE_FS_CACHEFS &cachefs_ops, /* caching F/S */ #endif /* HAVE_FS_CACHEFS */ +#ifdef HAVE_FS_TMPFS + &tmpfs_ops, /* /tmp (in memory) F/S */ +#endif /* HAVE_FS_TMPFS */ #ifdef HAVE_FS_NULLFS /* FILL IN */ /* null (loopback) F/S */ #endif /* HAVE_FS_NULLFS */ @@ -120,6 +124,12 @@ static am_ops *vops[] = #ifdef HAVE_FS_UMAPFS /* FILL IN */ /* uid/gid mapping F/S */ #endif /* HAVE_FS_UMAPFS */ +#ifdef HAVE_FS_UDF + &udf_ops, /* UDF F/S */ +#endif /* HAVE_FS_UDF */ +#ifdef HAVE_FS_LUSTRE + &lustre_ops, /* Lustre */ +#endif /* HAVE_FS_LUSTRE */ /* * These 4 should be last, in the order: @@ -316,7 +326,7 @@ merge_opts(const char *opts1, const char *opts2) char oneopt[80]; /* one option w/o value if any */ char *revoneopt; /* reverse of oneopt */ size_t len = strlen(opts1) + strlen(opts2) + 2; /* space for "," and NULL */ - char *s1 = strdup(opts1); /* copy of opts1 to munge */ + char *s1 = xstrdup(opts1); /* copy of opts1 to munge */ /* initialization */ mnt2.mnt_opts = (char *) opts2; @@ -327,13 +337,13 @@ merge_opts(const char *opts1, const char *opts2) tmpstr; tmpstr = strtok(NULL, ",")) { /* copy option to temp buffer */ - xstrlcpy(oneopt, tmpstr, 80); + xstrlcpy(oneopt, tmpstr, sizeof(oneopt)); /* if option has a value such as rsize=1024, chop the value part */ - if ((eq = haseq(oneopt))) + if ((eq = strchr(oneopt, '='))) *eq = '\0'; /* find reverse option of oneopt */ revoneopt = reverse_option(oneopt); - /* if option orits reverse exist in opts2, ignore it */ + /* if option or its reverse exist in opts2, ignore it */ if (amu_hasmntopt(&mnt2, oneopt) || amu_hasmntopt(&mnt2, revoneopt)) continue; /* add option to returned string */ @@ -362,7 +372,7 @@ am_ops * ops_search(char *type) { am_ops **vp; - am_ops *rop = 0; + am_ops *rop = NULL; for (vp = vops; (rop = *vp); vp++) if (STREQ(rop->fs_type, type)) break; @@ -373,7 +383,7 @@ ops_search(char *type) am_ops * ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map) { - am_ops *rop = 0; + am_ops *rop = NULL; char *link_dir; /* @@ -400,7 +410,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map * Otherwise skip past any leading '-'. */ if (fo->opt_opts == 0) - fo->opt_opts = strdup("rw,defaults"); + fo->opt_opts = xstrdup("rw,defaults"); else if (*fo->opt_opts == '-') { /* * We cannot simply do fo->opt_opts++ here since the opts @@ -408,7 +418,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map * So just reallocate the thing -- stolcke 11/11/94 */ char *old = fo->opt_opts; - fo->opt_opts = strdup(old + 1); + fo->opt_opts = xstrdup(old + 1); XFREE(old); } @@ -426,7 +436,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map XFREE(fo->opt_opts); XFREE(fo->opt_remopts); fo->opt_opts = mergedstr; - fo->opt_remopts = strdup(mergedstr); + fo->opt_remopts = xstrdup(mergedstr); } else { char *mergedstr, *remmergedstr; mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts); @@ -451,7 +461,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map /* Normalize the sublink and make it absolute */ link_dir = fo->opt_sublink; if (link_dir && link_dir[0] && link_dir[0] != '/') { - link_dir = str3cat((char *) 0, fo->opt_fs, "/", link_dir); + link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir); normalize_slash(link_dir); XFREE(fo->opt_sublink); fo->opt_sublink = link_dir; @@ -460,8 +470,7 @@ ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map /* * Check the filesystem is happy */ - if (fo->fs_mtab) - XFREE(fo->fs_mtab); + XFREE(fo->fs_mtab); fo->fs_mtab = rop->fs_match(fo); if (fo->fs_mtab) diff --git a/contrib/amd/amd/amd.8 b/contrib/amd/amd/amd.8 index ca6b6de39f5..35eba4c5baa 100644 --- a/contrib/amd/amd/amd.8 +++ b/contrib/amd/amd/amd.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1989 Jan-Simon Pendry .\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,9 +32,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" %W% (Berkeley) %G% .\" -.\" $Id: amd.8,v 1.14.2.1 2006/01/02 18:48:23 ezk Exp $ +.\" File: am-utils/amd/amd.8 .\" $FreeBSD$ .\" .Dd February 26, 2016 @@ -232,20 +227,20 @@ Specify an in seconds, between attempts to dismount file systems that have exceeded their cached times. The default is 2 minutes. +.TP .It Fl x Ar options -Specify run-time logging options. -The options are a comma separated +Specify run-time logging options. The options are a comma separated list chosen from: -.Li fatal , error , user , warn , info , map , stats , all . +.Li fatal, error, user, warn, info, map, stats, defaults, all . +Note that "fatal" and "error" are mandatory and cannot be turned off. +.TP .It Fl y Ar domain Specify an alternative .Tn NIS domain from which to fetch the .Tn NIS maps. -The default is the system domain name. -This option is ignored if -.Tn NIS +The default is the system domain name. This option is ignored if NIS support is not available. .It Fl A Ar arch Specifies the OS architecture. @@ -367,14 +362,15 @@ number of process context switches. A weird imagination is most useful to gain full advantage of all the features. .Sh SEE ALSO -.Xr domainname 1 , -.Xr hostname 1 , -.Xr syslog 3 , -.Xr amd.conf 5 , -.Xr mtab 5 , -.Xr amq 8 , -.Xr mount 8 , -.Xr umount 8 +.Xr domainname 1, +.Xr hostname 1, +.Xr syslog 3. +.Xr amd.conf 5, +.Xr mtab 5, +.Xr amq 8, +.Xr automount 8, +.Xr mount 8, +.Xr umount 8, .Pp .Dq am-utils .Xr info 1 diff --git a/contrib/amd/amd/amd.c b/contrib/amd/amd/amd.c index 3fc25f833db..7ec49ce1cec 100644 --- a/contrib/amd/amd/amd.c +++ b/contrib/amd/amd/amd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -379,7 +375,7 @@ do_memory_locking(void) #endif /* HAVE_PLOCK || HAVE_MLOCKALL */ #if defined(HAVE_MADVISE) && defined(MADV_PROTECT) - madvise(0, 0, MADV_PROTECT); /* may be redundant of the above worked out */ + madvise(NULL, 0, MADV_PROTECT); /* may be redundant of the above worked out */ #endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */ } @@ -431,6 +427,7 @@ main(int argc, char *argv[]) if (gethostname(hostname, sizeof(hostname)) < 0) { plog(XLOG_FATAL, "gethostname: %m"); going_down(1); + return 1; } hostname[sizeof(hostname) - 1] = '\0'; @@ -440,6 +437,7 @@ main(int argc, char *argv[]) if (!*hostname) { plog(XLOG_FATAL, "host name is not set"); going_down(1); + return 1; } /* @@ -498,7 +496,8 @@ main(int argc, char *argv[]) getwire(&PrimNetName, &PrimNetNum); /* - * Determine command-line arguments + * Determine command-line arguments. + * (Also initialize amd.conf parameters, maps, and more.) */ get_args(argc, argv); @@ -532,6 +531,7 @@ main(int argc, char *argv[]) if (geteuid() != 0) { plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid()); going_down(1); + return 1; } #ifdef HAVE_MAP_NIS @@ -543,10 +543,11 @@ main(int argc, char *argv[]) if (gopt.nis_domain && yp_bind(gopt.nis_domain)) { plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain); going_down(1); + return 1; } #endif /* HAVE_MAP_NIS */ - if (!amuDebug(D_DAEMON)) + if (amuDebug(D_DAEMON)) ppid = daemon_mode(); /* diff --git a/contrib/amd/amd/amd.h b/contrib/amd/amd/amd.h index 0e371b72a5b..f66f5b75169 100644 --- a/contrib/amd/amd/amd.h +++ b/contrib/amd/amd/amd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -54,9 +50,12 @@ * that support mtab on file. */ #ifdef MOUNT_TABLE_ON_FILE -# define DEBUG_MNTTAB_FILE "/tmp/mnttab" +# define DEBUG_MNTTAB_FILE "/tmp/mtab" #endif /* MOUNT_TABLE_ON_FILE */ +/* Max line length that info services can handle */ +#define INFO_MAX_LINE_LEN 1500 + /* options for amd.conf */ #define CFM_BROWSABLE_DIRS 0x00000001 #define CFM_MOUNT_TYPE_AUTOFS 0x00000002 /* use kernel autofs support */ @@ -76,10 +75,7 @@ #define CFM_NORMALIZE_SLASHES 0x00008000 /* normalize slashes? */ #define CFM_FORCED_UNMOUNTS 0x00010000 /* forced unmounts? */ #define CFM_TRUNCATE_LOG 0x00020000 /* truncate log file? */ -#if 0 -/* XXX: reserved to sync up with am-utils-6.2 */ #define CFM_SUN_MAP_SYNTAX 0x00040000 /* Sun map syntax? */ -#endif #define CFM_NFS_ANY_INTERFACE 0x00080000 /* all interfaces are acceptable */ /* defaults global flags: plock, tcpwrappers, and autofs/lofs */ @@ -212,6 +208,7 @@ typedef struct cf_map cf_map_t; typedef struct kv kv; typedef struct am_node am_node; typedef struct mntfs mntfs; +typedef struct am_loc am_loc; typedef struct am_opts am_opts; typedef struct am_ops am_ops; typedef struct am_stats am_stats; @@ -245,13 +242,17 @@ typedef int (*vmount_fs) (am_node *, mntfs *); typedef int (*vumount_fs) (am_node *, mntfs *); typedef am_node *(*vlookup_child) (am_node *, char *, int *, int); typedef am_node *(*vmount_child) (am_node *, int *); -typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, u_int); +typedef int (*vreaddir) (am_node *, voidp, voidp, voidp, u_int); typedef am_node *(*vreadlink) (am_node *, int *); typedef void (*vmounted) (mntfs *); typedef void (*vumounted) (mntfs *); typedef fserver *(*vffserver) (mntfs *); typedef wchan_t (*vget_wchan) (mntfs *); +/* + * NFS progran dispatcher + */ +typedef void (*dispatcher_t)(struct svc_req *rqstp, SVCXPRT *transp); /* @@ -314,6 +315,7 @@ struct amu_global_options { #endif /* HAVE_MAP_NIS */ char *nfs_proto; /* NFS protocol (NULL, udp, tcp) */ int nfs_vers; /* NFS version (0, 2, 3, 4) */ + int nfs_vers_ping; /* NFS rpc ping version (0, 2, 3, 4) */ u_int exec_map_timeout; /* timeout (seconds) for executable maps */ }; @@ -349,6 +351,7 @@ struct mnt_map { short alloc; /* Allocation mode */ time_t modify; /* Modify time of map */ u_int reloads; /* Number of times map was reloaded */ + u_int nentries; /* Number of entries in the map */ char *map_name; /* Name of this map */ char *wildcard; /* Wildcard value */ reload_fn *reload; /* Function to be used for reloads */ @@ -420,7 +423,7 @@ struct mntfs { am_opts *mf_fo; /* File opts */ char *mf_mount; /* "/a/kiska/home/kiska" */ char *mf_info; /* Mount info */ - char *mf_auto; /* Automount opts */ + char *mf_auto; /* Mount info */ char *mf_mopts; /* FS mount opts */ char *mf_remopts; /* Remote FS mount opts */ char *mf_loopdev; /* loop device name for /dev/loop mounts */ @@ -434,6 +437,16 @@ struct mntfs { opaque_t mf_private; /* Private - per-fs data */ }; +/* + * Locations: bindings between keys and mntfs + */ +struct am_loc { + am_opts *al_fo; + mntfs *al_mnt; + int al_refc; +}; + + /* * List of fileservers */ @@ -463,6 +476,8 @@ struct am_stats { int s_readdir; /* Count of readdirs */ int s_readlink; /* Count of readlinks */ int s_statfs; /* Count of statfs */ + int s_fsinfo; /* Count of fsinfo */ + int s_pathconf; /* Count of pathconf */ }; /* @@ -482,8 +497,8 @@ extern struct amd_stats amd_stats; */ struct am_node { int am_mapno; /* Map number */ - mntfs *am_mnt; /* Mounted filesystem */ - mntfs **am_mfarray; /* Filesystem sources to try to mount */ + am_loc *am_al; /* Mounted filesystem */ + am_loc **am_alarray; /* Filesystem sources to try to mount */ char *am_name; /* "kiska": name of this node */ char *am_path; /* "/home/kiska": path of this node's mount point */ char *am_link; /* "/a/kiska/home/kiska/this/that": link to sub-dir */ @@ -508,6 +523,7 @@ struct am_node { autofs_fh_t *am_autofs_fh; time_t am_autofs_ttl; /* Time to expire autofs nodes */ #endif /* HAVE_FS_AUTOFS */ + int am_fd[2]; /* parent child pipe fd's for sync umount */ }; /* @@ -527,13 +543,18 @@ extern int *amqproc_getpid_1_svc(voidp argp, struct svc_req *rqstp); extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp); extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp); extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp); -extern voidp amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp); +extern int *amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp); +extern int *amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp); +extern amq_sync_umnt *amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp); +extern amq_sync_umnt *amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp); +extern amq_map_info_list *amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp); /* other external definitions */ -extern am_nfs_fh *get_root_nfs_fh(char *dir); +extern am_nfs_handle_t *get_root_nfs_fh(char *dir, am_nfs_handle_t *nfh); extern am_node *find_ap(char *); extern am_node *get_ap_child(am_node *, char *); extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead); +extern bool_t xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead); extern fserver *find_nfs_srvr(mntfs *mf); extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf); extern int process_all_regular_maps(void); @@ -541,7 +562,8 @@ extern cf_map_t *find_cf_map(const char *name); extern int set_conf_kv(const char *section, const char *k, const char *v); extern int mount_node(opaque_t arg); extern int unmount_mp(am_node *mp); -extern int yyparse (void); +extern int conf_parse(void); /* "yyparse" renamed */ +extern FILE *conf_in; /* "yyin" renamed */ extern void amfs_mkcacheref(mntfs *mf); extern int amfs_mount(am_node *mp, mntfs *mf, char *opts); @@ -566,12 +588,15 @@ extern int get_mountd_port(fserver *, u_short *, wchan_t); extern void flush_nfs_fhandle_cache(fserver *); extern mntfs *dup_mntfs(mntfs *); +extern am_loc *dup_loc(am_loc *); extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *); extern mntfs *locate_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *); +extern am_loc *new_loc(void); extern mntfs *new_mntfs(void); extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *); extern void flush_mntfs(void); extern void free_mntfs(voidp); +extern void free_loc(voidp); extern void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp); @@ -579,9 +604,11 @@ extern int background(void); extern void deslashify(char *); extern void do_task_notify(void); extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *); +extern int file_read_line(char *, int, FILE *); extern void forcibly_timeout_mp(am_node *); extern void free_map(am_node *); extern void free_opts(am_opts *); +extern am_opts *copy_opts(am_opts *); extern void free_srvr(fserver *); extern int fwd_init(void); extern int fwd_packet(int, char *, int, struct sockaddr_in *, struct sockaddr_in *, opaque_t, fwd_fun *); @@ -596,7 +623,7 @@ extern int make_nfs_auth(void); extern void make_root_node(void); extern void map_flush_srvr(fserver *); extern void mapc_add_kv(mnt_map *, char *, char *); -extern mnt_map *mapc_find(char *, char *, const char *); +extern mnt_map *mapc_find(char *, char *, const char *, const char *); extern void mapc_free(opaque_t); extern int mapc_keyiter(mnt_map *, key_fun, opaque_t); extern void mapc_reload(void); @@ -608,9 +635,11 @@ extern int mount_auto_node(char *, opaque_t); extern int mount_automounter(int); extern int mount_exported(void); extern void mp_to_fh(am_node *, am_nfs_fh *); +extern void mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp); extern void new_ttl(am_node *); extern void nfs_quick_reply(am_node *mp, int error); extern void normalize_slash(char *); +extern void notify_child(am_node *, au_etype, int, int); extern void ops_showamfstypes(char *buf, size_t l); extern void ops_showfstypes(char *outbuf, size_t l); extern void rem_que(qelem *); @@ -639,8 +668,8 @@ extern char hostd[SIZEOF_HOSTD]; /* Host+domain */ /* * Global variables. */ -extern FILE *yyin; extern SVCXPRT *current_transp; /* For nfs_quick_reply() */ +extern dispatcher_t nfs_dispatcher; extern char *conf_tag; #define SIZEOF_UID_STR 12 #define SIZEOF_GID_STR 12 @@ -723,6 +752,19 @@ extern am_ops cdfs_ops; extern am_ops pcfs_ops; #endif /* HAVE_FS_PCFS */ +/* + * UDF File System + * Many systems can't support this, and in any case most of the + * functionality is available with program FS. + */ +#ifdef HAVE_FS_UDF +extern am_ops udf_ops; +#endif /* HAVE_FS_UDF */ + +#ifdef HAVE_FS_LUSTRE +extern am_ops lustre_ops; +#endif /* HAVE_FS_LUSTRE */ + /* * Caching File System (Solaris) */ @@ -730,6 +772,12 @@ extern am_ops pcfs_ops; extern am_ops cachefs_ops; #endif /* HAVE_FS_CACHEFS */ +/* + * In memory /tmp filesystem (Linux, NetBSD) + */ +#ifdef HAVE_FS_TMPFS +extern am_ops tmpfs_ops; +#endif /* HAVE_FS_TMPFS */ /* * Network File System * Good, slow, NFS V.2. @@ -753,6 +801,13 @@ extern am_ops ufs_ops; /* Un*x file system */ extern am_ops xfs_ops; /* Un*x file system */ #endif /* HAVE_FS_XFS */ +/* Unix file system (ext*) */ +#ifdef HAVE_FS_EXT +extern am_ops ext2_ops; /* Un*x file system */ +extern am_ops ext3_ops; /* Un*x file system */ +extern am_ops ext4_ops; /* Un*x file system */ +#endif /* HAVE_FS_EXT */ + /* Unix file system (irix) */ #ifdef HAVE_FS_EFS extern am_ops efs_ops; /* Un*x file system */ @@ -772,7 +827,7 @@ extern am_ops amfs_root_ops; /* Root file system */ */ extern am_node *amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op); extern am_node *amfs_generic_mount_child(am_node *ap, int *error_return); -extern int amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count); +extern int amfs_generic_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count); extern int amfs_generic_umount(am_node *mp, mntfs *mf); extern void amfs_generic_mounted(mntfs *mf); extern char *amfs_generic_match(am_opts *fo); @@ -808,7 +863,8 @@ extern am_ops amfs_direct_ops; /* Direct Automount file system (this too) */ extern am_ops amfs_error_ops; /* Error file system */ extern am_node *amfs_error_lookup_child(am_node *mp, char *fname, int *error_return, int op); extern am_node *amfs_error_mount_child(am_node *ap, int *error_return); -extern int amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count); +extern int amfs_error_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count); + #endif /* HAVE_AMU_FS_ERROR */ /* diff --git a/contrib/amd/amd/amfs_auto.c b/contrib/amd/amd/amfs_auto.c index 75a451fd111..34fdb00f501 100644 --- a/contrib/amd/amd/amfs_auto.c +++ b/contrib/amd/amd/amfs_auto.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -101,6 +97,8 @@ am_ops amfs_auto_ops = static int amfs_auto_mount(am_node *mp, mntfs *mf) { + if (mp->am_parent == NULL) + return EINVAL; /* * Pseudo-directories are used to provide some structure * to the automounted directories instead @@ -115,7 +113,7 @@ amfs_auto_mount(am_node *mp, mntfs *mf) * Historical - not documented. */ if (mf->mf_info[0] == '.' && mf->mf_info[1] == '\0') - mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_mnt->mf_info); + mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_al->al_mnt->mf_info); /* * Compute prefix: @@ -131,12 +129,12 @@ amfs_auto_mount(am_node *mp, mntfs *mf) if (mf->mf_fo->opt_pref) { /* allow pref:=null to set a real null prefix */ if (STREQ(mf->mf_fo->opt_pref, "null")) { - mp->am_pref = strdup(""); + mp->am_pref = xstrdup(""); } else { /* * the prefix specified as an option */ - mp->am_pref = strdup(mf->mf_fo->opt_pref); + mp->am_pref = xstrdup(mf->mf_fo->opt_pref); } } else { /* @@ -147,7 +145,7 @@ amfs_auto_mount(am_node *mp, mntfs *mf) char *ppref = mp->am_parent->am_pref; if (ppref == 0) ppref = ""; - mp->am_pref = str3cat((char *) 0, ppref, mp->am_name, "/"); + mp->am_pref = str3cat((char *) NULL, ppref, mp->am_name, "/"); } #ifdef HAVE_FS_AUTOFS diff --git a/contrib/amd/amd/amfs_direct.c b/contrib/amd/amd/amfs_direct.c index dbef743d0d7..b911c2a1e2c 100644 --- a/contrib/amd/amd/amfs_direct.c +++ b/contrib/amd/amd/amfs_direct.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -93,8 +89,8 @@ amfs_direct_readlink(am_node *mp, int *error_return) xp = next_nonerror_node(mp->am_child); if (!xp) { - if (!mp->am_mnt->mf_private) - amfs_mkcacheref(mp->am_mnt); /* XXX */ + if (!mp->am_al->al_mnt->mf_private) + amfs_mkcacheref(mp->am_al->al_mnt); xp = amfs_generic_lookup_child(mp, mp->am_path + 1, &rc, VLOOK_CREATE); if (xp && rc < 0) xp = amfs_generic_mount_child(xp, &rc); diff --git a/contrib/amd/amd/amfs_error.c b/contrib/amd/amd/amfs_error.c index 51bdaa6db14..58a623102c1 100644 --- a/contrib/amd/amd/amfs_error.c +++ b/contrib/amd/amd/amfs_error.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -92,7 +88,7 @@ am_ops amfs_error_ops = static char * amfs_error_match(am_opts *fo) { - return strdup("(error-hook)"); + return xstrdup("(error-hook)"); } @@ -145,7 +141,7 @@ amfs_error_mount_child(am_node *ap, int *error_return) * If we do then just give an error. */ int -amfs_error_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) +amfs_error_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count) { return ESTALE; } diff --git a/contrib/amd/amd/amfs_generic.c b/contrib/amd/amd/amfs_generic.c index 0d5996969cf..25d734bbde0 100644 --- a/contrib/amd/amd/amfs_generic.c +++ b/contrib/amd/amd/amfs_generic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -55,7 +51,7 @@ /**************************************************************************** *** MACROS *** ****************************************************************************/ -#define IN_PROGRESS(cp) ((cp)->mp->am_mnt->mf_flags & MFF_MOUNTING) +#define IN_PROGRESS(cp) ((cp)->mp->am_al->al_mnt->mf_flags & MFF_MOUNTING) /**************************************************************************** @@ -80,7 +76,7 @@ struct continuation { int retry; /* Try again? */ time_t start; /* Time we started this mount */ int callout; /* Callout identifier */ - mntfs **mf; /* Current mntfs */ + am_loc **al; /* Current location */ }; @@ -88,9 +84,9 @@ struct continuation { *** FORWARD DEFINITIONS *** ****************************************************************************/ static am_node *amfs_lookup_node(am_node *mp, char *fname, int *error_return); -static mntfs *amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, +static am_loc *amfs_lookup_one_location(am_node *new_mp, mntfs *mf, char *ivec, char *def_opts, char *pfname); -static mntfs **amfs_lookup_mntfs(am_node *new_mp, int *error_return); +static am_loc **amfs_lookup_loc(am_node *new_mp, int *error_return); static void amfs_cont(int rc, int term, opaque_t arg); static void amfs_retry(int rc, int term, opaque_t arg); static void free_continuation(struct continuation *cp); @@ -108,7 +104,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return) int error = 0; /* Error so far */ int in_progress = 0; /* # of (un)mount in progress */ mntfs *mf; - char *expanded_fname = 0; + char *expanded_fname = NULL; dlog("in amfs_lookup_node"); @@ -118,7 +114,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return) * about the mount point. */ if (amd_state == Finishing) { - if (mp->am_mnt == 0 || mp->am_mnt->mf_fsflags & FS_DIRECT) { + if (mp->am_al == NULL || mp->am_al->al_mnt == NULL || mp->am_al->al_mnt->mf_fsflags & FS_DIRECT) { dlog("%s mount ignored - going down", fname); } else { dlog("%s/%s mount ignored - going down", mp->am_path, fname); @@ -170,7 +166,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return) * If the error code is undefined then it must be * in progress. */ - mf = new_mp->am_mnt; + mf = new_mp->am_al->al_mnt; if (mf->mf_error < 0) goto in_progrss; @@ -240,7 +236,7 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return) */ new_mp = get_ap_child(mp, expanded_fname); XFREE(expanded_fname); - if (new_mp == 0) + if (new_mp == NULL) ereturn(ENOSPC); *error_return = -1; @@ -249,19 +245,25 @@ amfs_lookup_node(am_node *mp, char *fname, int *error_return) -static mntfs * -amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, - char *def_opts, char *pfname) +static am_loc * +amfs_lookup_one_location(am_node *new_mp, mntfs *mf, char *ivec, + char *def_opts, char *pfname) { am_ops *p; am_opts *fs_opts; + am_loc *new_al; mntfs *new_mf; - char *mp_dir = 0; + char *mp_dir = NULL; #ifdef HAVE_FS_AUTOFS int on_autofs = 1; #endif /* HAVE_FS_AUTOFS */ /* match the operators */ + /* + * although we alloc the fs_opts here, the pointer is 'owned' by the am_loc and will + * be free'd on destruction of the am_loc. If we don't allocate a loc, then we need + * to free this. + */ fs_opts = CALLOC(am_opts); p = ops_match(fs_opts, ivec, def_opts, new_mp->am_path, pfname, mf->mf_info); @@ -269,7 +271,7 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, /* XXX: this should be factored out into an autofs-specific function */ if (new_mp->am_flags & AMF_AUTOFS) { /* ignore user-provided fs if we're using autofs */ - if (fs_opts->opt_sublink) { + if (fs_opts->opt_sublink && fs_opts->opt_sublink[0]) { /* * For sublinks we need to use a hack with autofs: * mount the filesystem on the original opt_fs (which is NOT an @@ -292,6 +294,9 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, /* * Find or allocate a filesystem for this node. + * we search for a matching backend share, since + * we will construct our own al_loc to handle + * any customisations for this usage. */ new_mf = find_mntfs(p, fs_opts, mp_dir, @@ -300,6 +305,7 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, fs_opts->opt_opts, fs_opts->opt_remopts); + /* * See whether this is a real filesystem */ @@ -307,10 +313,16 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, if (p == &amfs_error_ops) { plog(XLOG_MAP, "Map entry %s for %s did not match", ivec, new_mp->am_path); free_mntfs(new_mf); + free_opts(fs_opts); + XFREE(fs_opts); return NULL; } dlog("Got a hit with %s", p->fs_type); + new_al = new_loc(); + free_mntfs(new_al->al_mnt); + new_al->al_mnt = new_mf; + new_al->al_fo = fs_opts; /* now the loc is in charge of free'ing this mem */ #ifdef HAVE_FS_AUTOFS if (new_mp->am_flags & AMF_AUTOFS && on_autofs) { @@ -332,12 +344,12 @@ amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec, new_mf->mf_flags |= MFF_IS_AUTOFS; #endif /* HAVE_FS_AUTOFS */ - return new_mf; + return new_al; } -static mntfs ** -amfs_lookup_mntfs(am_node *new_mp, int *error_return) +static am_loc ** +amfs_lookup_loc(am_node *new_mp, int *error_return) { am_node *mp; char *info; /* Mount info - where to get the file system */ @@ -348,10 +360,11 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return) int error = 0; /* Error so far */ char path_name[MAXPATHLEN]; /* General path name buffer */ char *pfname; /* Path for database lookup */ - mntfs *mf, **mf_array; + mntfs* mf; /* The mntfs for the map of our parent */ + am_loc **al_array; /* the generated list of locations */ int count; - dlog("in amfs_lookup_mntfs"); + dlog("in amfs_lookup_loc"); mp = new_mp->am_parent; @@ -369,7 +382,7 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return) pfname = new_mp->am_name; } - mf = mp->am_mnt; + mf = mp->am_al->al_mnt; dlog("will search map info in %s to find %s", mf->mf_info, pfname); /* @@ -404,8 +417,8 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return) else def_opts = ""; - orig_def_opts = amfs_parse_defaults(mp, mf, strdup(def_opts)); - def_opts = strdup(orig_def_opts); + orig_def_opts = amfs_parse_defaults(mp, mf, xstrdup(def_opts)); + def_opts = xstrdup(orig_def_opts); /* first build our defaults */ num_ivecs = 0; @@ -423,11 +436,11 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return) num_ivecs++; } - mf_array = calloc(num_ivecs + 1, sizeof(mntfs *)); + al_array = calloc(num_ivecs + 1, sizeof(am_loc *)); - /* construct the array of struct mntfs for this mount point */ + /* construct the array of struct locations for this key */ for (count = 0, cur_ivec = ivecs; *cur_ivec; cur_ivec++) { - mntfs *new_mf; + am_loc *new_al; if (**cur_ivec == '-') { XFREE(def_opts); @@ -436,18 +449,18 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return) * If we have a single dash '-' than we need to reset the * default options. */ - def_opts = strdup(orig_def_opts); + def_opts = xstrdup(orig_def_opts); dlog("Resetting the default options, a single dash '-' was found."); } else { /* append options to /default options */ - def_opts = str3cat((char *) 0, orig_def_opts, ";", *cur_ivec + 1); + def_opts = str3cat((char *) NULL, orig_def_opts, ";", *cur_ivec + 1); dlog("Resetting def_opts to \"%s\"", def_opts); } continue; } /* - * If a mntfs has already been found, and we find + * If a loc has already been found, and we find * a cut then don't try any more locations. * * XXX: we do not know when the "/" was added as an equivalent for "||". @@ -455,16 +468,16 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return) */ if (STREQ(*cur_ivec, "/") || STREQ(*cur_ivec, "||")) { if (count > 0) { - dlog("Cut: not trying any more locations for %s", mp->am_path); + dlog("Cut: not trying any more locations for %s", pfname); break; } continue; } - new_mf = amfs_lookup_one_mntfs(new_mp, mf, *cur_ivec, def_opts, pfname); - if (new_mf == NULL) + new_al = amfs_lookup_one_location(new_mp, mf, *cur_ivec, def_opts, pfname); + if (new_al == NULL) continue; - mf_array[count++] = new_mf; + al_array[count++] = new_al; } /* We're done with ivecs */ @@ -473,11 +486,11 @@ amfs_lookup_mntfs(am_node *new_mp, int *error_return) XFREE(orig_def_opts); XFREE(def_opts); if (count == 0) { /* no match */ - XFREE(mf_array); + XFREE(al_array); ereturn(ENOENT); } - return mf_array; + return al_array; } @@ -491,7 +504,7 @@ amfs_cont(int rc, int term, opaque_t arg) { struct continuation *cp = (struct continuation *) arg; am_node *mp = cp->mp; - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; dlog("amfs_cont: '%s'", mp->am_path); @@ -556,7 +569,7 @@ amfs_cont(int rc, int term, opaque_t arg) mf->mf_error = rc; mf->mf_flags |= MFF_ERROR; errno = rc; /* XXX */ - if (!STREQ(mp->am_mnt->mf_ops->fs_type, "linkx")) + if (!STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "linkx")) plog(XLOG_ERROR, "%s: mount (amfs_cont): %m", mp->am_path); } } @@ -568,7 +581,7 @@ amfs_cont(int rc, int term, opaque_t arg) * call the background mount routine again */ amd_stats.d_merr++; - cp->mf++; + cp->al++; } amfs_bgmount(cp); if (mp->am_error > 0) @@ -608,13 +621,21 @@ amfs_retry(int rc, int term, opaque_t arg) */ plog(XLOG_INFO, "mount of \"%s\" has timed out", mp->am_path); error = ETIMEDOUT; - while (*cp->mf) - cp->mf++; + while (*cp->al) + cp->al++; /* explicitly forbid further retries after timeout */ cp->retry = FALSE; } if (error || !IN_PROGRESS(cp)) error = amfs_bgmount(cp); + else + /* Normally it's amfs_bgmount() which frees the continuation. However, if + * the mount is already in progress and we're in amfs_retry() for another + * node we don't try mounting the filesystem once again. Still, we have + * to free the continuation as we won't get called again and thus would + * leak the continuation structure and our am_loc references. + */ + free_continuation(cp); reschedule_timeout_mp(); } @@ -626,7 +647,7 @@ amfs_retry(int rc, int term, opaque_t arg) static void free_continuation(struct continuation *cp) { - mntfs **mfp; + am_loc **alp; dlog("free_continuation"); if (cp->callout) @@ -634,13 +655,12 @@ free_continuation(struct continuation *cp) /* * we must free the mntfs's in the list. * so free all of them if there was an error, - * or free all but the used one, if the mount succeeded. */ - for (mfp = cp->mp->am_mfarray; *mfp; mfp++) { - free_mntfs(*mfp); + for (alp = cp->mp->am_alarray; *alp; alp++) { + free_loc(*alp); } - XFREE(cp->mp->am_mfarray); - cp->mp->am_mfarray = 0; + XFREE(cp->mp->am_alarray); + cp->mp->am_alarray = 0; XFREE(cp); } @@ -690,12 +710,13 @@ static int amfs_bgmount(struct continuation *cp) { am_node *mp = cp->mp; - mntfs *mf; /* Current mntfs */ + am_loc *loc; + mntfs *mf; int this_error = -1; /* Per-mount error */ int hard_error = -1; /* Cumulative per-node error */ - if (mp->am_mnt) - free_mntfs(mp->am_mnt); + if (mp->am_al) + free_loc(mp->am_al); /* * Try to mount each location. @@ -704,10 +725,11 @@ amfs_bgmount(struct continuation *cp) * hard_error > 0 indicates everything failed with a hard error * hard_error < 0 indicates nothing could be mounted now */ - for (mp->am_mnt = *cp->mf; *cp->mf; cp->mf++, mp->am_mnt = *cp->mf) { + for (mp->am_al = *cp->al; *cp->al; cp->al++, mp->am_al = *cp->al) { am_ops *p; - mf = dup_mntfs(mp->am_mnt); + loc = dup_loc(mp->am_al); + mf = loc->al_mnt; p = mf->mf_ops; if (hard_error < 0) @@ -737,12 +759,11 @@ amfs_bgmount(struct continuation *cp) goto failed; } - if (mp->am_link) { - XFREE(mp->am_link); - mp->am_link = NULL; - } - if (mf->mf_fo && mf->mf_fo->opt_sublink) - mp->am_link = strdup(mf->mf_fo->opt_sublink); + XFREE(mp->am_link); + mp->am_link = NULL; + + if (loc->al_fo && loc->al_fo->opt_sublink && loc->al_fo->opt_sublink[0]) + mp->am_link = xstrdup(loc->al_fo->opt_sublink); /* * Will usually need to play around with the mount nodes @@ -784,13 +805,13 @@ amfs_bgmount(struct continuation *cp) if (this_error < 0) goto retry; - if (mf->mf_fo && mf->mf_fo->opt_delay) { + if (loc->al_fo && loc->al_fo->opt_delay) { /* - * If there is a delay timer on the mount + * If there is a delay timer on the location * then don't try to mount if the timer * has not expired. */ - int i = atoi(mf->mf_fo->opt_delay); + int i = atoi(loc->al_fo->opt_delay); time_t now = clocktime(NULL); if (i > 0 && now < (cp->start + i)) { dlog("Mount of %s delayed by %lds", mf->mf_mount, (long) (i - now + cp->start)); @@ -866,22 +887,25 @@ amfs_bgmount(struct continuation *cp) return -1; failed: - amd_stats.d_merr++; - mf->mf_error = this_error; - mf->mf_flags |= MFF_ERROR; + if (!FSRV_ISDOWN(mf->mf_server)) { + /* mark the mount as failed unless the server is down */ + amd_stats.d_merr++; + mf->mf_error = this_error; + mf->mf_flags |= MFF_ERROR; #ifdef HAVE_FS_AUTOFS - if (mp->am_autofs_fh) - autofs_release_fh(mp); + if (mp->am_autofs_fh) + autofs_release_fh(mp); #endif /* HAVE_FS_AUTOFS */ - if (mf->mf_flags & MFF_MKMNT) { - rmdirs(mf->mf_mount); - mf->mf_flags &= ~MFF_MKMNT; + if (mf->mf_flags & MFF_MKMNT) { + rmdirs(mf->mf_mount); + mf->mf_flags &= ~MFF_MKMNT; + } } /* * Wakeup anything waiting for this mount */ wakeup(get_mntfs_wchan(mf)); - free_mntfs(mf); + free_loc(loc); /* continue */ } @@ -890,7 +914,10 @@ amfs_bgmount(struct continuation *cp) * there is no more mount information available. */ if (this_error) { - mp->am_mnt = mf = new_mntfs(); + if (mp->am_al) + free_loc(mp->am_al); + mp->am_al = loc = new_loc(); + mf = loc->al_mnt; #ifdef HAVE_FS_AUTOFS if (mp->am_flags & AMF_AUTOFS) @@ -920,7 +947,7 @@ amfs_bgmount(struct continuation *cp) } new_ttl(mp); } else { - mf = mp->am_mnt; + mf = loc->al_mnt; /* * Wakeup anything waiting for this mount */ @@ -959,19 +986,10 @@ amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts) /* * Find out if amd.conf overrode any map-specific /defaults. - * - * HACK ALERT: there's no easy way to find out what the map mount point is - * at this point, so I am forced to initialize the mnt_map->cfm field here - * for the first time, upon the very first search for a /defaults entry in - * this map. This initialization is much better done in mapc_create(), - * but it's impossible to do that there with the current code structure. */ - if (mm->cfm == NULL) { /* then initialize it for first time */ - mm->cfm = find_cf_map(mf->mf_mount); - } if (mm->cfm && mm->cfm->cfm_defaults) { dlog("map %s map_defaults override: %s", mf->mf_mount, mm->cfm->cfm_defaults); - dflts = strdup(mm->cfm->cfm_defaults); + dflts = xstrdup(mm->cfm->cfm_defaults); } else if (mapc_search(mm, "/defaults", &dflts) == 0) { dlog("/defaults gave %s", dflts); } else { @@ -1009,7 +1027,7 @@ amfs_parse_defaults(am_node *mp, mntfs *mf, char *def_opts) * get expanded to "/defaults" */ pt = ops_match(&ap, *sp, "", mp->am_path, "/defaults", - mp->am_parent->am_mnt->mf_info); + mp->am_parent->am_al->al_mnt->mf_info); free_opts(&ap); /* don't leak */ if (pt == &amfs_error_ops) { plog(XLOG_MAP, "did not match defaults for \"%s\"", *sp); @@ -1076,8 +1094,9 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return) *error_return = error = 0; /* Error so far */ /* we have an errorfs attached to the am_node, free it */ - free_mntfs(new_mp->am_mnt); - new_mp->am_mnt = 0; + if (new_mp->am_al) + free_loc(new_mp->am_al); + new_mp->am_al = NULL; /* * Construct a continuation @@ -1087,7 +1106,7 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return) cp->mp = new_mp; cp->retry = TRUE; cp->start = clocktime(NULL); - cp->mf = new_mp->am_mfarray; + cp->al = new_mp->am_alarray; /* * Try and mount the file system. If this succeeds immediately (possible @@ -1101,7 +1120,7 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return) /* * Code for quick reply. If current_transp is set, then it's the - * transp that's been passed down from nfs_program_2() or from + * transp that's been passed down from nfs_dispatcher() or from * autofs_program_[123](). * If new_mp->am_transp is not already set, set it by copying in * current_transp. Once am_transp is set, nfs_quick_reply() and @@ -1113,7 +1132,8 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return) new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT)); *(new_mp->am_transp) = *current_transp; } - if (error && new_mp->am_mnt && (new_mp->am_mnt->mf_ops == &amfs_error_ops)) + if (error && new_mp->am_al && new_mp->am_al->al_mnt && + (new_mp->am_al->al_mnt->mf_ops == &amfs_error_ops)) new_mp->am_error = error; if (new_mp->am_error > 0) @@ -1132,7 +1152,7 @@ am_node * amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op) { am_node *new_mp; - mntfs **mf_array; + am_loc **al_array; int mp_error; dlog("in amfs_generic_lookup_child"); @@ -1145,7 +1165,7 @@ amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op) return new_mp; /* also return if it's already mounted and known to be up */ - if (*error_return == 0 && FSRV_ISUP(new_mp->am_mnt->mf_server)) + if (*error_return == 0 && FSRV_ISUP(new_mp->am_al->al_mnt->mf_server)) return new_mp; switch (op) { @@ -1161,42 +1181,15 @@ amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op) /* save error_return */ mp_error = *error_return; - mf_array = amfs_lookup_mntfs(new_mp, error_return); - if (!mf_array) { - new_mp->am_error = new_mp->am_mnt->mf_error = *error_return; + al_array = amfs_lookup_loc(new_mp, error_return); + if (!al_array) { + new_mp->am_error = new_mp->am_al->al_mnt->mf_error = *error_return; free_map(new_mp); return NULL; } - /* - * Already mounted but known to be down: - * check if we have any alternatives to mount - */ - if (mp_error == 0) { - mntfs **mfp; - for (mfp = mf_array; *mfp; mfp++) - if (*mfp != new_mp->am_mnt) - break; - if (*mfp != NULL) { - /* - * we found an alternative, so try mounting again. - */ - *error_return = -1; - } else { - for (mfp = mf_array; *mfp; mfp++) - free_mntfs(*mfp); - XFREE(mf_array); - if (new_mp->am_flags & AMF_SOFTLOOKUP) { - ereturn(EIO); - } else { - *error_return = 0; - return new_mp; - } - } - } - /* store the array inside the am_node */ - new_mp->am_mfarray = mf_array; + new_mp->am_alarray = al_array; /* * Note: while it might seem like a good idea to prioritize @@ -1258,5 +1251,5 @@ amfs_generic_match(am_opts *fo) /* * mtab entry turns out to be the name of the mount map */ - return strdup(fo->opt_rfs ? fo->opt_rfs : "."); + return xstrdup(fo->opt_rfs ? fo->opt_rfs : "."); } diff --git a/contrib/amd/amd/amfs_host.c b/contrib/amd/amd/amfs_host.c index 55423c46ea3..a3468ecd4b6 100644 --- a/contrib/amd/amd/amfs_host.c +++ b/contrib/amd/amd/amfs_host.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -227,7 +223,14 @@ fetch_fhandle(CLIENT *client, char *dir, am_nfs_handle_t *fhp, u_long nfs_versio plog(XLOG_INFO, "fetch_fhandle: NFS version %d", (int) nfs_version); #ifdef HAVE_FS_NFS3 - if (nfs_version == NFS_VERSION3) { + if (nfs_version == NFS_VERSION3 +#ifdef HAVE_FS_NFS4 +#ifndef NO_FALLBACK + || nfs_version == NFS_VERSION4 +#endif /* NO_FALLBACK */ +#endif /* HAVE_FS_NFS4 */ + ) { + memset((char *) &res3, 0, sizeof(res3)); clnt_stat = clnt_call(client, MOUNTPROC_MNT, @@ -303,8 +306,8 @@ amfs_host_mount(am_node *am, mntfs *mf) int n_export; int j, k; exports exlist = 0, ex; - exports *ep = 0; - am_nfs_handle_t *fp = 0; + exports *ep = NULL; + am_nfs_handle_t *fp = NULL; char *host; int error = 0; struct sockaddr_in sin; @@ -449,13 +452,13 @@ amfs_host_mount(am_node *am, mntfs *mf) /* Check and avoid a duplicated export entry */ if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) { dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir); - ep[j] = 0; + ep[j] = NULL; } else { k = j; error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j], mf->mf_server->fs_version); if (error) - ep[j] = 0; + ep[j] = NULL; } } @@ -465,8 +468,8 @@ amfs_host_mount(am_node *am, mntfs *mf) * error code 0 at the end. If they all fail then return * the last error code. */ - xstrlcpy(fs_name, mf->mf_info, MAXPATHLEN); - if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) { + xstrlcpy(fs_name, mf->mf_info, sizeof(fs_name)); + if ((rfs_dir = strchr(fs_name, ':')) == (char *) NULL) { plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon"); error = EINVAL; goto out; @@ -493,10 +496,8 @@ amfs_host_mount(am_node *am, mntfs *mf) */ out: discard_mntlist(mlist); - if (ep) - XFREE(ep); - if (fp) - XFREE(fp); + XFREE(ep); + XFREE(fp); if (sock != RPC_ANYSOCK) (void) amu_close(sock); if (client) @@ -554,7 +555,7 @@ amfs_host_umount(am_node *am, mntfs *mf) * Reverse list... */ ml = mlist; - mprev = 0; + mprev = NULL; while (ml) { mntlist *ml2 = ml->mnext; ml->mnext = mprev; diff --git a/contrib/amd/amd/amfs_link.c b/contrib/amd/amd/amfs_link.c index e75ab862f8b..0751dd7047a 100644 --- a/contrib/amd/amd/amfs_link.c +++ b/contrib/amd/amd/amfs_link.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -109,13 +105,13 @@ amfs_link_match(am_opts *fo) */ if (fo->opt_fs[0] == '/') { char *link_hack = str3cat(NULL, ".", fo->opt_fs, ""); - if (!fo->opt_sublink) - fo->opt_sublink = strdup(fo->opt_fs); + if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\0') + fo->opt_sublink = xstrdup(fo->opt_fs); XFREE(fo->opt_fs); fo->opt_fs = link_hack; } - return strdup(fo->opt_fs); + return xstrdup(fo->opt_fs); } diff --git a/contrib/amd/amd/amfs_linkx.c b/contrib/amd/amd/amfs_linkx.c index e306eda91d3..be95fe5e1a2 100644 --- a/contrib/amd/amd/amfs_linkx.c +++ b/contrib/amd/amd/amfs_linkx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/amfs_nfsl.c b/contrib/amd/amd/amfs_nfsl.c index bb48f0efd25..c70a3eeb97c 100644 --- a/contrib/amd/amd/amfs_nfsl.c +++ b/contrib/amd/amd/amfs_nfsl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -101,7 +97,7 @@ amfs_nfsl_match(am_opts *fo) char *retval; struct stat stb; - if (fo->opt_sublink) + if (fo->opt_sublink && fo->opt_sublink[0]) cp = fo->opt_sublink; else cp = fo->opt_fs; @@ -116,8 +112,9 @@ amfs_nfsl_match(am_opts *fo) * call nfs_ops.fs_match(). * If link value exists (or same host), call amfs_link_ops.fs_match(). */ - if (!STRCEQ(ho, am_get_hostname())) { - plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not local host, using type:=nfs", ho); + if (!STRCEQ(ho, am_get_hostname()) && !STRCEQ(ho, hostd)) { + plog(XLOG_INFO, "amfs_nfsl: \"%s\" is not the local host \"%s\", " + "or \"%s\" using type:=nfs", ho, am_get_hostname(), hostd); retval = nfs_ops.fs_match(fo); } else if (lstat(cp, &stb) < 0) { plog(XLOG_INFO, "amfs_nfsl: \"%s\" does not exist, using type:=nfs", cp); @@ -213,11 +210,16 @@ amfs_nfsl_umounted(mntfs *mf) static fserver * amfs_nfsl_ffserver(mntfs *mf) { - char *cp; - char *ho = mf->mf_fo->opt_rhost; + char *cp, *ho; struct stat stb; - if (mf->mf_fo->opt_sublink) + if (mf->mf_fo == NULL) { + plog(XLOG_ERROR, "%s: NULL mf_fo", __func__); + return NULL; + } + ho = mf->mf_fo->opt_rhost; + + if (mf->mf_fo->opt_sublink && mf->mf_fo->opt_sublink[0]) cp = mf->mf_fo->opt_sublink; else cp = mf->mf_fo->opt_fs; @@ -227,7 +229,8 @@ amfs_nfsl_ffserver(mntfs *mf) * call amfs_link_ops.ffserver(). * If link value exists (or same host), then call ops_nfs.ffserver(). */ - if (!STRCEQ(ho, am_get_hostname()) || lstat(cp, &stb) < 0) { + if ((!STRCEQ(ho, am_get_hostname()) && + !STRCEQ(ho, hostd)) || lstat(cp, &stb) < 0) { return nfs_ops.ffserver(mf); } else { mf->mf_flags |= MFF_NFSLINK; diff --git a/contrib/amd/amd/amfs_nfsx.c b/contrib/amd/amd/amfs_nfsx.c index 91be8af47e1..db1b9fafd11 100644 --- a/contrib/amd/amd/amfs_nfsx.c +++ b/contrib/amd/amd/amfs_nfsx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -118,7 +114,7 @@ amfs_nfsx_match(am_opts *fo) } /* set default sublink */ - if (fo->opt_sublink == 0) { + if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\0') { ptr = strchr(fo->opt_rfs, ','); if (ptr && ptr > (fo->opt_rfs + 1)) fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1); @@ -149,7 +145,7 @@ amfs_nfsx_match(am_opts *fo) /* * Determine magic cookie to put in mtab */ - xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs); + xmtab = str3cat((char *) NULL, fo->opt_rhost, ":", fo->opt_rfs); dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"", fo->opt_rhost, fo->opt_rfs, fo->opt_fs); @@ -190,12 +186,15 @@ amfs_nfsx_init(mntfs *mf) if (nx == 0) { char **ivec; - char *info = 0; + char *info = NULL; char *host; char *pref; int error = 0; - info = strdup(mf->mf_info); + info = xstrdup(mf->mf_info); + if (info == NULL) + return errno; + host = strchr(info, ':'); if (!host) { error = EINVAL; @@ -221,12 +220,12 @@ amfs_nfsx_init(mntfs *mf) nx->nx_c = i - 1; /* i-1 because we don't want the prefix */ nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt)); - nx->nx_mp = 0; + nx->nx_mp = NULL; { - char *mp = 0; - char *xinfo = 0; + char *mp = NULL; + char *xinfo = NULL; char *fs = mf->mf_fo->opt_fs; - char *rfs = 0; + char *rfs = NULL; for (i = 0; i < nx->nx_c; i++) { char *path = ivec[i + 1]; rfs = str3cat(rfs, pref, "/", path); @@ -251,18 +250,14 @@ amfs_nfsx_init(mntfs *mf) /* propagate the on_autofs flag */ nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS; } - if (rfs) - XFREE(rfs); - if (mp) - XFREE(mp); - if (xinfo) - XFREE(xinfo); + XFREE(rfs); + XFREE(mp); + XFREE(xinfo); } XFREE(ivec); errexit: - if (info) - XFREE(info); + XFREE(info); if (error) return error; } @@ -503,7 +498,7 @@ amfs_nfsx_umount(am_node *am, mntfs *mf) } } free_mntfs(m); - n->n_mnt = 0; + n->n_mnt = NULL; n->n_error = -1; } } diff --git a/contrib/amd/amd/amfs_program.c b/contrib/amd/amd/amfs_program.c index b0aed3752d7..6bf003fb2cf 100644 --- a/contrib/amd/amd/amfs_program.c +++ b/contrib/amd/amd/amfs_program.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -105,7 +101,7 @@ amfs_program_match(am_opts *fo) } prog = strchr(fo->opt_mount, ' '); - return strdup(prog ? prog + 1 : fo->opt_mount); + return xstrdup(prog ? prog + 1 : fo->opt_mount); } @@ -116,11 +112,14 @@ amfs_program_init(mntfs *mf) if (mf->mf_private != NULL) return 0; + if (mf->mf_fo == NULL) + return 0; + /* save unmount (or umount) command */ if (mf->mf_fo->opt_unmount != NULL) - mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_unmount); + mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_unmount); else - mf->mf_private = (opaque_t) strdup(mf->mf_fo->opt_umount); + mf->mf_private = (opaque_t) xstrdup(mf->mf_fo->opt_umount); mf->mf_prfree = (void (*)(opaque_t)) free; return 0; @@ -136,9 +135,7 @@ amfs_program_exec(char *info) /* * Split copy of command info string */ - info = strdup(info); - if (info == 0) - return ENOBUFS; + info = xstrdup(info); xivec = strsplit(info, ' ', '\''); /* @@ -148,11 +145,11 @@ amfs_program_exec(char *info) if (!logfp) logfp = stderr; /* initialize before possible first use */ if (dup(fileno(logfp)) == -1) - return errno; + goto out; if (fileno(logfp) != fileno(stderr)) { (void) fclose(stderr); if (dup(fileno(logfp)) == -1) - return errno; + goto out; } /* @@ -172,13 +169,16 @@ amfs_program_exec(char *info) plog(XLOG_USER, "1st/2nd args missing to (un)mount program"); } else { (void) execv(xivec[0], xivec + 1); + error = errno; + plog(XLOG_ERROR, "exec failed: %m"); + errno = error; } +out: /* * Save error number */ error = errno; - plog(XLOG_ERROR, "exec failed: %m"); /* * Free allocate memory diff --git a/contrib/amd/amd/amfs_root.c b/contrib/amd/amd/amfs_root.c index 243267e71e8..f06c43ce0ba 100644 --- a/contrib/amd/amd/amfs_root.c +++ b/contrib/amd/amd/amfs_root.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -92,7 +88,7 @@ static int amfs_root_mount(am_node *mp, mntfs *mf) { mf->mf_mount = strealloc(mf->mf_mount, pid_fsname); - mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL); + mf->mf_private = (opaque_t) mapc_find(mf->mf_info, "", NULL, NULL); mf->mf_prfree = mapc_free; return 0; diff --git a/contrib/amd/amd/amfs_toplvl.c b/contrib/amd/amd/amfs_toplvl.c index 1b968f197f5..1b143157b4c 100644 --- a/contrib/amd/amd/amfs_toplvl.c +++ b/contrib/amd/amd/amfs_toplvl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -148,7 +144,7 @@ amfs_toplvl_init(mntfs *mf) { int error = 0; -#if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH) +#if (defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)) && (defined(HAVE_UVMOUNT) || defined(HAVE_UMOUNT2)) if (gopt.flags & CFM_FORCED_UNMOUNTS) { plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s", mf->mf_mount); @@ -158,7 +154,7 @@ amfs_toplvl_init(mntfs *mf) else dlog("amfs_toplvl_init: forced/lazy unmount succeeded"); } -#endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */ +#endif /* (MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH) && (HAVE_UVMOUNT || HAVE_UMOUNT2) */ return error; } @@ -227,6 +223,11 @@ amfs_toplvl_mount(am_node *mp, mntfs *mf) xstrlcat(opts, toplvl_opts, sizeof(opts)); } +#ifdef MNTTAB_OPT_NOLOCK + xstrlcat(opts, ",", sizeof(opts)); + xstrlcat(opts, MNTTAB_OPT_NOLOCK, sizeof(opts)); +#endif /* MNTTAB_OPT_NOLOCK */ + #ifdef MNTTAB_OPT_NOAC if (gopt.auto_attrcache == 0) { xstrlcat(opts, ",", sizeof(opts)); diff --git a/contrib/amd/amd/amfs_union.c b/contrib/amd/amd/amfs_union.c index 6adb5b0bd9c..9f37a1b04dd 100644 --- a/contrib/amd/amd/amfs_union.c +++ b/contrib/amd/amd/amfs_union.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -95,7 +91,7 @@ create_amfs_union_node(char *dir, opaque_t arg) am_node *am; am = amfs_generic_lookup_child(arg, dir, &error, VLOOK_CREATE); if (am && error < 0) - am = amfs_generic_mount_child(am, &error); + (void)amfs_generic_mount_child(am, &error); if (error > 0) { errno = error; /* XXX */ plog(XLOG_ERROR, "unionfs: could not mount %s: %m", dir); @@ -121,9 +117,9 @@ amfs_union_mounted(mntfs *mf) for (mp = get_first_exported_ap(&index); mp; mp = get_next_exported_ap(&index)) { - if (mp->am_mnt == mf) { + if (mp->am_al->al_mnt == mf) { /* return value from create_amfs_union_node is ignored by mapc_keyiter */ - (void) mapc_keyiter((mnt_map *) mp->am_mnt->mf_private, + (void) mapc_keyiter((mnt_map *) mp->am_al->al_mnt->mf_private, create_amfs_union_node, mp); break; diff --git a/contrib/amd/amd/amq_subr.c b/contrib/amd/amd/amq_subr.c index 79ecafc3d9b..ba85c68b742 100644 --- a/contrib/amd/amd/amq_subr.c +++ b/contrib/amd/amd/amq_subr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -80,16 +76,68 @@ amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp) /* * Unmount a single node */ -voidp +int * amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp) { - static char res; + static int res = AMQ_UMNT_OK; am_node *mp = find_ap(*(char **) argp); if (mp) forcibly_timeout_mp(mp); - return (voidp) &res; + return &res; +} + + +/* + * Synchronously unmount a single node - parent side. + */ +int * +amqproc_sync_umnt_1_svc_parent(voidp argp, struct svc_req *rqstp) +{ + amqproc_umnt_1_svc(argp, rqstp); + return NULL; +} + + +/* + * Synchronously unmount a single node - child side. + */ +amq_sync_umnt * +amqproc_sync_umnt_1_svc_child(voidp argp, struct svc_req *rqstp) +{ + static amq_sync_umnt rv; + amq_sync_umnt buf; + ssize_t n; + + am_node *mp = find_ap(*(char **) argp); + + memset(&rv, 0, sizeof(rv)); + rv.au_etype = AMQ_UMNT_READ; + if (mp && mp->am_fd[0] >= 0) { + n = read(mp->am_fd[0], &buf, sizeof(buf)); + if (n == sizeof(buf)) + rv = buf; + } + return &rv; +} + + +/* + * Synchronously unmount a single node - use if we can't fork (asynchronous). + */ +amq_sync_umnt * +amqproc_sync_umnt_1_svc_async(voidp argp, struct svc_req *rqstp) +{ + static amq_sync_umnt rv; + + memset(&rv, 0, sizeof(rv)); + rv.au_etype = AMQ_UMNT_FORK; + rv.au_errno = errno; + + amqproc_umnt_1_svc(argp, rqstp); + + return &rv; } @@ -170,6 +218,12 @@ amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp) return (amq_mount_info_list *) ((void *)&mfhead); /* XXX */ } +extern qelem map_list_head; +amq_map_info_list * +amqproc_getmapinfo_1_svc(voidp argp, struct svc_req *rqstp) +{ + return (amq_map_info_list *) ((void *)&map_list_head); /* XXX */ +} amq_string * amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp) @@ -218,11 +272,11 @@ amqproc_pawd_1_svc(voidp argp, struct svc_req *rqstp) for (mp = get_first_exported_ap(&index); mp; mp = get_next_exported_ap(&index)) { - if (STREQ(mp->am_mnt->mf_ops->fs_type, "toplvl")) + if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "toplvl")) continue; - if (STREQ(mp->am_mnt->mf_ops->fs_type, "auto")) + if (STREQ(mp->am_al->al_mnt->mf_ops->fs_type, "auto")) continue; - mountpoint = (mp->am_link ? mp->am_link : mp->am_mnt->mf_mount); + mountpoint = (mp->am_link ? mp->am_link : mp->am_al->al_mnt->mf_mount); len = strlen(mountpoint); if (len == 0) continue; @@ -277,16 +331,16 @@ xdr_amq_mount_tree_node(XDR *xdrs, amq_mount_tree *objp) am_node *mp = (am_node *) objp; long mtime; - if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_info)) { + if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_info)) { return (FALSE); } if (!xdr_amq_string(xdrs, &mp->am_path)) { return (FALSE); } - if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_mnt->mf_mount)) { + if (!xdr_amq_string(xdrs, mp->am_link ? &mp->am_link : &mp->am_al->al_mnt->mf_mount)) { return (FALSE); } - if (!xdr_amq_string(xdrs, &mp->am_mnt->mf_ops->fs_type)) { + if (!xdr_amq_string(xdrs, &mp->am_al->al_mnt->mf_ops->fs_type)) { return (FALSE); } mtime = mp->am_stats.s_mtime; @@ -412,16 +466,15 @@ xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp) } - -/* - * Compute length of list - */ bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead) { mntfs *mf; u_int len = 0; + /* + * Compute length of list + */ for (mf = AM_LAST(mntfs, qhead); mf != HEAD(mntfs, qhead); mf = PREV(mntfs, mf)) { if (!(mf->mf_fsflags & FS_AMQINFO)) continue; @@ -468,6 +521,70 @@ xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead) return (TRUE); } +bool_t +xdr_amq_map_info_qelem(XDR *xdrs, qelem *qhead) +{ + mnt_map *m; + u_int len = 0; + int x; + char *n; + + /* + * Compute length of list + */ + ITER(m, mnt_map, qhead) { + len++; + } + + if (!xdr_u_int(xdrs, &len)) + return (FALSE); + + /* + * Send individual data items + */ + ITER(m, mnt_map, qhead) { + if (!xdr_amq_string(xdrs, &m->map_name)) { + return (FALSE); + } + + n = m->wildcard ? m->wildcard : ""; + if (!xdr_amq_string(xdrs, &n)) { + return (FALSE); + } + + if (!xdr_long(xdrs, (long *) &m->modify)) { + return (FALSE); + } + + x = m->flags; + if (!xdr_int(xdrs, &x)) { + return (FALSE); + } + + x = m->nentries; + if (!xdr_int(xdrs, &x)) { + return (FALSE); + } + + x = m->reloads; + if (!xdr_int(xdrs, &x)) { + return (FALSE); + } + + if (!xdr_int(xdrs, &m->refc)) { + return (FALSE); + } + + if (m->isup) + x = (*m->isup)(m, m->map_name); + else + x = -1; + if (!xdr_int(xdrs, &x)) { + return (FALSE); + } + } + return (TRUE); +} bool_t xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr) diff --git a/contrib/amd/amd/amq_svc.c b/contrib/amd/amd/amq_svc.c index 6fadb160c12..1f2b3d6ff8d 100644 --- a/contrib/amd/amd/amq_svc.c +++ b/contrib/amd/amd/amq_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -57,7 +53,7 @@ typedef char *(*amqsvcproc_t)(voidp, struct svc_req *); * in libwrap, while others don't: so I need to know precisely iff * to define these two severity variables. */ -int allow_severity=0, deny_severity=0; +int allow_severity=0, deny_severity=0, rfc931_timeout=0; # endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */ /* @@ -65,51 +61,90 @@ int allow_severity=0, deny_severity=0; * Returns: 1=allowed, 0=denied. */ static int -amqsvc_is_client_allowed(const struct sockaddr_in *addr, char *remote) +amqsvc_is_client_allowed(const struct sockaddr_in *addr) { - struct hostent *h; - char *name = NULL, **ad; - int ret = 0; /* default is 0==denied */ + struct request_info req; - /* Check IP address */ - if (hosts_ctl(AMD_SERVICE_NAME, "", remote, "")) { - ret = 1; - goto out; - } - /* Get address */ - if (!(h = gethostbyaddr((const char *)&(addr->sin_addr), - sizeof(addr->sin_addr), - AF_INET))) - goto out; - if (!(name = strdup(h->h_name))) - goto out; - /* Paranoia check */ - if (!(h = gethostbyname(name))) - goto out; - for (ad = h->h_addr_list; *ad; ad++) - if (!memcmp(*ad, &(addr->sin_addr), h->h_length)) - break; - if (!*ad) - goto out; - if (hosts_ctl(AMD_SERVICE_NAME, "", h->h_name, "")) { - return 1; - goto out; - } - /* Check aliases */ - for (ad = h->h_aliases; *ad; ad++) - if (hosts_ctl(AMD_SERVICE_NAME, "", *ad, "")) { - return 1; - goto out; - } + request_init(&req, RQ_DAEMON, AMD_SERVICE_NAME, RQ_CLIENT_SIN, addr, 0); + sock_methods(&req); - out: - if (name) - XFREE(name); - return ret; + if (hosts_access(&req)) + return 1; + + return 0; } #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ +/* + * Prepare the parent and child: + * 1) Setup IPC pipe. + * 2) Set signal masks. + * 3) Fork by calling background() so that NumChildren is updated. + */ +static int +amq_fork(opaque_t argp) +{ +#ifdef HAVE_SIGACTION + sigset_t new, mask; +#else /* not HAVE_SIGACTION */ + int mask; +#endif /* not HAVE_SIGACTION */ + am_node *mp; + pid_t pid; + + mp = find_ap(*(char **) argp); + if (mp == NULL) { + errno = 0; + return -1; + } + + if (pipe(mp->am_fd) == -1) { + mp->am_fd[0] = -1; + mp->am_fd[1] = -1; + return -1; + } + +#ifdef HAVE_SIGACTION + sigemptyset(&new); /* initialize signal set we wish to block */ + sigaddset(&new, SIGHUP); + sigaddset(&new, SIGINT); + sigaddset(&new, SIGQUIT); + sigaddset(&new, SIGCHLD); + sigprocmask(SIG_BLOCK, &new, &mask); +#else /* not HAVE_SIGACTION */ + mask = + sigmask(SIGHUP) | + sigmask(SIGINT) | + sigmask(SIGQUIT) | + sigmask(SIGCHLD); + mask = sigblock(mask); +#endif /* not HAVE_SIGACTION */ + + switch ((pid = background())) { + case -1: /* error */ + dlog("amq_fork failed"); + return -1; + + case 0: /* child */ + close(mp->am_fd[1]); /* close output end of pipe */ + mp->am_fd[1] = -1; + return 0; + + default: /* parent */ + close(mp->am_fd[0]); /* close input end of pipe */ + mp->am_fd[0] = -1; + +#ifdef HAVE_SIGACTION + sigprocmask(SIG_SETMASK, &mask, NULL); +#else /* not HAVE_SIGACTION */ + sigsetmask(mask); +#endif /* not HAVE_SIGACTION */ + return pid; + } +} + + void amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) { @@ -121,13 +156,16 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) char *result; xdrproc_t xdr_argument, xdr_result; amqsvcproc_t local; + amqsvcproc_t child; + amqsvcproc_t parent; + pid_t pid; #if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) if (gopt.flags & CFM_USE_TCPWRAPPERS) { struct sockaddr_in *remote_addr = svc_getcaller(rqstp->rq_xprt); char *remote_hostname = inet_ntoa(remote_addr->sin_addr); - if (!amqsvc_is_client_allowed(remote_addr, remote_hostname)) { + if (!amqsvc_is_client_allowed(remote_addr)) { plog(XLOG_WARNING, "Amd denied remote amq service to %s", remote_hostname); svcerr_auth(transp, AUTH_FAILED); return; @@ -137,6 +175,10 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) } #endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ + local = NULL; + child = NULL; + parent = NULL; + switch (rqstp->rq_proc) { case AMQPROC_NULL: @@ -199,6 +241,21 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) local = (amqsvcproc_t) amqproc_pawd_1_svc; break; + case AMQPROC_SYNC_UMNT: + xdr_argument = (xdrproc_t) xdr_amq_string; + xdr_result = (xdrproc_t) xdr_amq_sync_umnt; + parent = (amqsvcproc_t) amqproc_sync_umnt_1_svc_parent; + child = (amqsvcproc_t) amqproc_sync_umnt_1_svc_child; + /* used if fork fails */ + local = (amqsvcproc_t) amqproc_sync_umnt_1_svc_async; + break; + + case AMQPROC_GETMAPINFO: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_amq_map_info_qelem; + local = (amqsvcproc_t) amqproc_getmapinfo_1_svc; + break; + default: svcerr_noproc(transp); return; @@ -212,7 +269,28 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) return; } - result = (*local) (&argument, rqstp); + pid = -1; + result = NULL; + + if (child) { + switch ((pid = amq_fork(&argument))) { + case -1: /* error */ + break; + + case 0: /* child */ + result = (*child) (&argument, rqstp); + local = NULL; + break; + + default: /* parent */ + result = (*parent) (&argument, rqstp); + local = NULL; + break; + } + } + + if (local) + result = (*local) (&argument, rqstp); if (result != NULL && !svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, @@ -226,4 +304,7 @@ amq_program_1(struct svc_req *rqstp, SVCXPRT *transp) plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1"); going_down(1); } + + if (pid == 0) + exit(0); /* the child is done! */ } diff --git a/contrib/amd/amd/autil.c b/contrib/amd/amd/autil.c index a5ecd6d0d1f..cd9514d44ef 100644 --- a/contrib/amd/amd/autil.c +++ b/contrib/amd/amd/autil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -160,16 +156,23 @@ valid_key(char *key) void forcibly_timeout_mp(am_node *mp) { - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; /* * Arrange to timeout this node */ if (mf && ((mp->am_flags & AMF_ROOT) || (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) { + /* + * We aren't going to schedule a timeout, so we need to notify the + * child here unless we are already unmounting, in which case that + * process is responsible for notifying the child. + */ if (mf->mf_flags & MFF_UNMOUNTING) plog(XLOG_WARNING, "node %s is currently being unmounted, ignoring timeout request", mp->am_path); - else + else { plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path); + notify_child(mp, AMQ_UMNT_FAILED, EBUSY, 0); + } } else { plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path); mp->am_flags &= ~AMF_NOTIMEOUT; @@ -207,24 +210,11 @@ mf_mounted(mntfs *mf, bool_t call_free_opts) mf->mf_ops->mounted(mf); /* - * Be careful when calling free_ops and XFREE here. Some pseudo file - * systems like nfsx call this function (mf_mounted), even though it - * would be called by the lower-level amd file system functions. nfsx - * needs to call this function because of the other actions it takes. - * So we pass a boolean from the caller (yes, not so clean workaround) - * to determine if we should free or not. If we're not freeing (often - * because we're called from a callback function), then just to be sure, - * we'll zero out the am_opts structure and set the pointer to NULL. - * The parent mntfs node owns this memory and is going to free it with a - * call to mf_mounted(mntfs,TRUE) (see comment in the am_mounted code). + * We used to free the mf_mo (options) here, however they're now stored + * and managed with the mntfs and do not need to be free'd here (this ensures + * that we use the same options to monitor/unmount the system as we used + * to mount it). */ - if (call_free_opts) { - free_opts(mf->mf_fo); /* this free is needed to prevent leaks */ - XFREE(mf->mf_fo); /* (also this one) */ - } else { - memset(mf->mf_fo, 0, sizeof(am_opts)); - mf->mf_fo = NULL; - } } if (mf->mf_flags & MFF_RESTART) { @@ -249,7 +239,7 @@ void am_mounted(am_node *mp) { int notimeout = 0; /* assume normal timeouts initially */ - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; /* * This is the parent mntfs which does the mf->mf_fo (am_opts type), and @@ -266,7 +256,7 @@ am_mounted(am_node *mp) /* * Patch up path for direct mounts */ - if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT) + if (mp->am_parent && mp->am_parent->am_al->al_mnt->mf_fsflags & FS_DIRECT) mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", "."); /* @@ -277,6 +267,7 @@ am_mounted(am_node *mp) if (mf->mf_fsflags & FS_NOTIMEOUT) notimeout = 1; /* next, alter that decision by map flags */ + if (mf->mf_mopts) { mntent_t mnt; mnt.mnt_opts = mf->mf_mopts; @@ -321,7 +312,7 @@ am_mounted(am_node *mp) /* * Update mtime of parent node (copying "struct nfstime" in '=' below) */ - if (mp->am_parent && mp->am_parent->am_mnt) + if (mp->am_parent && mp->am_parent->am_al->al_mnt) mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime; /* @@ -360,21 +351,27 @@ assign_error_mntfs(am_node *mp) { int error; dlog("assign_error_mntfs"); + + if (mp->am_al == NULL) { + plog(XLOG_ERROR, "%s: Can't assign error", __func__); + return; + } /* * Save the old error code */ error = mp->am_error; if (error <= 0) - error = mp->am_mnt->mf_error; + error = mp->am_al->al_mnt->mf_error; /* * Allocate a new error reference */ - mp->am_mnt = new_mntfs(); + free_loc(mp->am_al); + mp->am_al = new_loc(); /* * Put back the error code */ - mp->am_mnt->mf_error = error; - mp->am_mnt->mf_flags |= MFF_ERROR; + mp->am_al->al_mnt->mf_error = error; + mp->am_al->al_mnt->mf_flags |= MFF_ERROR; /* * Zero the error in the mount point */ @@ -397,7 +394,8 @@ amfs_mkcacheref(mntfs *mf) cache = "none"; mf->mf_private = (opaque_t) mapc_find(mf->mf_info, cache, - (mf->mf_fo ? mf->mf_fo->opt_maptype : NULL)); + (mf->mf_fo ? mf->mf_fo->opt_maptype : NULL), + mf->mf_mount); mf->mf_prfree = mapc_free; } @@ -418,7 +416,7 @@ next_nonerror_node(am_node *xp) * containing hung automounts. */ while (xp && - (!(mf = xp->am_mnt) || /* No mounted filesystem */ + (!(mf = xp->am_al->al_mnt) || /* No mounted filesystem */ mf->mf_error != 0 || /* There was a mntfs error */ xp->am_error != 0 || /* There was a mount error */ !(mf->mf_flags & MFF_MOUNTED) || /* The fs is not mounted */ @@ -453,8 +451,9 @@ amfs_mount(am_node *mp, mntfs *mf, char *opts) mntent_t mnt; MTYPE_TYPE type; int forced_unmount = 0; /* are we using forced unmounts? */ + u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher); - memset((voidp) &mnt, 0, sizeof(mnt)); + memset(&mnt, 0, sizeof(mnt)); mnt.mnt_dir = dir; mnt.mnt_fsname = pid_fsname; mnt.mnt_opts = opts; @@ -525,8 +524,7 @@ amfs_mount(am_node *mp, mntfs *mf, char *opts) again: if (!(mf->mf_flags & MFF_IS_AUTOFS)) { nfs_args_t nfs_args; - am_nfs_fh *fhp; - am_nfs_handle_t anh; + am_nfs_handle_t *fhp, anh; #ifndef HAVE_TRANSPORT_TYPE_TLI u_short port; struct sockaddr_in sin; @@ -535,7 +533,7 @@ again: /* * get fhandle of remote path for automount point */ - fhp = get_root_nfs_fh(dir); + fhp = get_root_nfs_fh(dir, &anh); if (!fhp) { plog(XLOG_FATAL, "Can't find root file handle for %s", dir); return EINVAL; @@ -545,7 +543,7 @@ again: /* * Create sockaddr to point to the local machine. */ - memset((voidp) &sin, 0, sizeof(sin)); + memset(&sin, 0, sizeof(sin)); /* as per POSIX, sin_len need not be set (used internally by kernel) */ sin.sin_family = AF_INET; sin.sin_addr = myipaddr; @@ -559,16 +557,15 @@ again: #endif /* not HAVE_TRANSPORT_TYPE_TLI */ /* setup the many fields and flags within nfs_args */ - memmove(&anh.v2, fhp, sizeof(*fhp)); #ifdef HAVE_TRANSPORT_TYPE_TLI compute_nfs_args(&nfs_args, &mnt, genflags, nfsncp, NULL, /* remote host IP addr is set below */ - NFS_VERSION, /* version 2 */ + nfs_version, "udp", - &anh, + fhp, fs_hostname, pid_fsname); /* @@ -587,9 +584,9 @@ again: genflags, NULL, &sin, - NFS_VERSION, /* version 2 */ + nfs_version, "udp", - &anh, + fhp, fs_hostname, pid_fsname); #endif /* not HAVE_TRANSPORT_TYPE_TLI */ @@ -656,10 +653,17 @@ again: void am_unmounted(am_node *mp) { - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; - if (!foreground) /* firewall - should never happen */ + if (!foreground) { /* firewall - should never happen */ + /* + * This is a coding error. Make sure we hear about it! + */ + plog(XLOG_FATAL, "am_unmounted: illegal use in background (%s)", + mp->am_name); + notify_child(mp, AMQ_UMNT_OK, 0, 0); /* XXX - be safe? */ return; + } /* * Do unmounted callback @@ -707,26 +711,37 @@ am_unmounted(am_node *mp) /* * Update mtime of parent node */ - if (mp->am_parent && mp->am_parent->am_mnt) + if (mp->am_parent && mp->am_parent->am_al->al_mnt) clocktime(&mp->am_parent->am_fattr.na_mtime); if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) { - char *fname = strdup(mp->am_name); + char *fname = xstrdup(mp->am_name); am_node *mp_parent = mp->am_parent; - mntfs *mf_parent = mp_parent->am_mnt; + mntfs *mf_parent = mp_parent->am_al->al_mnt; + am_node fake_mp; int error = 0; + /* + * We need to use notify_child() after free_map(), so save enough + * to do that in fake_mp. + */ + fake_mp.am_fd[1] = mp->am_fd[1]; + mp->am_fd[1] = -1; + free_map(mp); plog(XLOG_INFO, "am_unmounted: remounting %s", fname); mp = mf_parent->mf_ops->lookup_child(mp_parent, fname, &error, VLOOK_CREATE); if (mp && error < 0) - mp = mf_parent->mf_ops->mount_child(mp, &error); + (void)mf_parent->mf_ops->mount_child(mp, &error); if (error > 0) { errno = error; plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname); + notify_child(&fake_mp, AMQ_UMNT_OK, 0, 0); + } else { + notify_child(&fake_mp, AMQ_UMNT_FAILED, EBUSY, 0); } XFREE(fname); - } else + } else { /* * We have a race here. * If this node has a pending mount and amd is going down (unmounting @@ -734,10 +749,12 @@ am_unmounted(am_node *mp) * while a struct continuation still has a reference to it. So when * amfs_cont is called, it blows up. * We avoid the race by refusing to free any nodes that have - * pending mounts (defined as having a non-NULL am_mfarray). + * pending mounts (defined as having a non-NULL am_alarray). */ - if (!mp->am_mfarray) + notify_child(mp, AMQ_UMNT_OK, 0, 0); /* do this regardless */ + if (!mp->am_alarray) free_map(mp); + } } diff --git a/contrib/amd/amd/clock.c b/contrib/amd/amd/clock.c index 0caa7dff2c7..4c6aa541376 100644 --- a/contrib/amd/amd/clock.c +++ b/contrib/amd/amd/clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/conf.c b/contrib/amd/amd/conf.c index 2fc587b0cad..57e1b9ddbd0 100644 --- a/contrib/amd/amd/conf.c +++ b/contrib/amd/amd/conf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -77,6 +73,7 @@ struct _func_map { static int gopt_arch(const char *val); static int gopt_auto_attrcache(const char *val); static int gopt_auto_dir(const char *val); +static int gopt_auto_nfs_version(const char *val); static int gopt_autofs_use_lofs(const char *val); static int gopt_browsable_dirs(const char *val); static int gopt_cache_duration(const char *val); @@ -120,6 +117,7 @@ static int gopt_nfs_retry_interval_udp(const char *val); static int gopt_nfs_retry_interval_tcp(const char *val); static int gopt_nfs_retry_interval_toplvl(const char *val); static int gopt_nfs_vers(const char *val); +static int gopt_nfs_vers_ping(const char *val); static int gopt_nis_domain(const char *val); static int gopt_normalize_hostnames(const char *val); static int gopt_normalize_slashes(const char *val); @@ -132,6 +130,7 @@ static int gopt_restart_mounts(const char *val); static int gopt_search_path(const char *val); static int gopt_selectors_in_defaults(const char *val); static int gopt_show_statfs_entries(const char *val); +static int gopt_sun_map_syntax(const char *val); static int gopt_truncate_log(const char *val); static int gopt_unmount_on_exit(const char *val); static int gopt_use_tcpwrappers(const char *val); @@ -146,6 +145,7 @@ static int ropt_map_options(const char *val, cf_map_t *cfm); static int ropt_map_type(const char *val, cf_map_t *cfm); static int ropt_mount_type(const char *val, cf_map_t *cfm); static int ropt_search_path(const char *val, cf_map_t *cfm); +static int ropt_sun_map_syntax(const char *val, cf_map_t *cfm); static int ropt_tag(const char *val, cf_map_t *cfm); static void init_cf_map(cf_map_t *cfm); @@ -159,6 +159,7 @@ static struct _func_map glob_functable[] = { {"arch", gopt_arch}, {"auto_attrcache", gopt_auto_attrcache}, {"auto_dir", gopt_auto_dir}, + {"auto_nfs_version", gopt_auto_nfs_version}, {"autofs_use_lofs", gopt_autofs_use_lofs}, {"browsable_dirs", gopt_browsable_dirs}, {"cache_duration", gopt_cache_duration}, @@ -202,6 +203,7 @@ static struct _func_map glob_functable[] = { {"nfs_retry_interval_tcp", gopt_nfs_retry_interval_tcp}, {"nfs_retry_interval_toplvl", gopt_nfs_retry_interval_toplvl}, {"nfs_vers", gopt_nfs_vers}, + {"nfs_vers_ping", gopt_nfs_vers_ping}, {"nis_domain", gopt_nis_domain}, {"normalize_hostnames", gopt_normalize_hostnames}, {"normalize_slashes", gopt_normalize_slashes}, @@ -215,6 +217,7 @@ static struct _func_map glob_functable[] = { {"selectors_on_default", gopt_selectors_in_defaults}, {"selectors_in_defaults", gopt_selectors_in_defaults}, {"show_statfs_entries", gopt_show_statfs_entries}, + {"sun_map_syntax", gopt_sun_map_syntax}, {"truncate_log", gopt_truncate_log}, {"unmount_on_exit", gopt_unmount_on_exit}, {"use_tcpwrappers", gopt_use_tcpwrappers}, @@ -255,12 +258,14 @@ init_cf_map(cf_map_t *cfm) cfm->cfm_search_path = gopt.search_path; /* - * Initialize flags that are common both to [global] and a local map. + * Initialize flags that are common both to [global] and a local map + * (that is, they could be inherited from the global section). */ cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS | CFM_BROWSABLE_DIRS_FULL | CFM_MOUNT_TYPE_AUTOFS | - CFM_SELECTORS_IN_DEFAULTS); + CFM_SELECTORS_IN_DEFAULTS | + CFM_SUN_MAP_SYNTAX ); } @@ -366,7 +371,7 @@ process_global_option(const char *key, const char *val) static int gopt_arch(const char *val) { - gopt.arch = strdup((char *)val); + gopt.arch = xstrdup(val); return 0; } @@ -386,10 +391,23 @@ gopt_auto_attrcache(const char *val) static int gopt_auto_dir(const char *val) { - gopt.auto_dir = strdup((char *)val); + gopt.auto_dir = xstrdup(val); return 0; } +static int +gopt_auto_nfs_version(const char *val) +{ + if (strcmp(val, "2") == 0) + nfs_dispatcher = nfs_program_2; + else if (strcmp(val, "3") == 0) + nfs_dispatcher = nfs_program_3; + else { + fprintf(stderr, "conf: bad auto nfs version : \"%s\"\n", val); + return 1; + } + return 0; +} static int gopt_autofs_use_lofs(const char *val) @@ -439,7 +457,7 @@ gopt_cache_duration(const char *val) static int gopt_cluster(const char *val) { - gopt.cluster = strdup((char *)val); + gopt.cluster = xstrdup(val); return 0; } @@ -447,7 +465,7 @@ gopt_cluster(const char *val) static int gopt_debug_mtab_file(const char *val) { - gopt.debug_mtab_file = strdup((char*)val); + gopt.debug_mtab_file = xstrdup(val); return 0; } @@ -547,7 +565,7 @@ gopt_forced_unmounts(const char *val) static int gopt_full_os(const char *val) { - gopt.op_sys_full = strdup((char *)val); + gopt.op_sys_full = xstrdup(val); return 0; } @@ -572,7 +590,7 @@ static int gopt_hesiod_base(const char *val) { #ifdef HAVE_MAP_HESIOD - gopt.hesiod_base = strdup((char *)val); + gopt.hesiod_base = xstrdup(val); return 0; #else /* not HAVE_MAP_HESIOD */ fprintf(stderr, "conf: hesiod_base option ignored. No Hesiod support available.\n"); @@ -584,7 +602,7 @@ gopt_hesiod_base(const char *val) static int gopt_karch(const char *val) { - gopt.karch = strdup((char *)val); + gopt.karch = xstrdup(val); return 0; } @@ -592,7 +610,7 @@ gopt_karch(const char *val) static int gopt_pid_file(const char *val) { - gopt.pid_file = strdup((char *)val); + gopt.pid_file = xstrdup(val); return 0; } @@ -600,7 +618,7 @@ gopt_pid_file(const char *val) static int gopt_local_domain(const char *val) { - gopt.sub_domain = strdup((char *)val); + gopt.sub_domain = xstrdup(val); return 0; } @@ -608,7 +626,7 @@ gopt_local_domain(const char *val) static int gopt_localhost_address(const char *val) { - gopt.localhost_address = strdup((char *)val); + gopt.localhost_address = xstrdup(val); return 0; } @@ -617,7 +635,7 @@ static int gopt_ldap_base(const char *val) { #ifdef HAVE_MAP_LDAP - gopt.ldap_base = strdup((char *)val); + gopt.ldap_base = xstrdup(val); return 0; #else /* not HAVE_MAP_LDAP */ fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n"); @@ -668,7 +686,7 @@ static int gopt_ldap_hostports(const char *val) { #ifdef HAVE_MAP_LDAP - gopt.ldap_hostports = strdup((char *)val); + gopt.ldap_hostports = xstrdup(val); return 0; #else /* not HAVE_MAP_LDAP */ fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n"); @@ -719,7 +737,7 @@ gopt_ldap_proto_version(const char *val) static int gopt_log_file(const char *val) { - gopt.logfile = strdup((char *)val); + gopt.logfile = xstrdup(val); return 0; } @@ -735,7 +753,7 @@ gopt_log_options(const char *val) static int gopt_map_defaults(const char *val) { - gopt.map_defaults = strdup((char *)val); + gopt.map_defaults = xstrdup(val); return 0; } @@ -743,7 +761,7 @@ gopt_map_defaults(const char *val) static int gopt_map_options(const char *val) { - gopt.map_options = strdup((char *)val); + gopt.map_options = xstrdup(val); return 0; } @@ -766,7 +784,7 @@ gopt_map_type(const char *val) fprintf(stderr, "conf: no such map type \"%s\"\n", val); return 1; } - gopt.map_type = strdup((char *)val); + gopt.map_type = xstrdup(val); return 0; } @@ -863,7 +881,7 @@ static int gopt_nfs_proto(const char *val) { if (STREQ(val, "udp") || STREQ(val, "tcp")) { - gopt.nfs_proto = strdup((char *)val); + gopt.nfs_proto = xstrdup(val); return 0; } fprintf(stderr, "conf: illegal nfs_proto \"%s\"\n", val); @@ -946,7 +964,7 @@ gopt_nfs_vers(const char *val) { int i = atoi(val); - if (i == 2 || i == 3) { + if (i == 2 || i == 3 || i == 4) { gopt.nfs_vers = i; return 0; } @@ -955,11 +973,24 @@ gopt_nfs_vers(const char *val) } +static int +gopt_nfs_vers_ping(const char *val) +{ + int i = atoi(val); + + if (i == 2 || i == 3 || i == 4) { + gopt.nfs_vers_ping = i; + return 0; + } + fprintf(stderr, "conf: illegal nfs_vers_ping \"%s\"\n", val); + return 1; +} + static int gopt_nis_domain(const char *val) { #ifdef HAVE_MAP_NIS - gopt.nis_domain = strdup((char *)val); + gopt.nis_domain = xstrdup(val); return 0; #else /* not HAVE_MAP_NIS */ fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n"); @@ -1003,7 +1034,7 @@ gopt_normalize_slashes(const char *val) static int gopt_os(const char *val) { - gopt.op_sys = strdup((char *)val); + gopt.op_sys = xstrdup(val); return 0; } @@ -1011,7 +1042,7 @@ gopt_os(const char *val) static int gopt_osver(const char *val) { - gopt.op_sys_ver = strdup((char *)val); + gopt.op_sys_ver = xstrdup(val); return 0; } @@ -1084,7 +1115,7 @@ gopt_restart_mounts(const char *val) static int gopt_search_path(const char *val) { - gopt.search_path = strdup((char *)val); + gopt.search_path = xstrdup(val); return 0; } @@ -1121,6 +1152,22 @@ gopt_show_statfs_entries(const char *val) } +static int +gopt_sun_map_syntax(const char *val) +{ + if (STREQ(val, "yes")) { + gopt.flags |= CFM_SUN_MAP_SYNTAX; + return 0; + } else if (STREQ(val, "no")) { + gopt.flags &= ~CFM_SUN_MAP_SYNTAX; + return 0; + } + + fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val); + return 1; /* unknown value */ +} + + static int gopt_truncate_log(const char *val) { @@ -1177,7 +1224,7 @@ gopt_use_tcpwrappers(const char *val) static int gopt_vendor(const char *val) { - gopt.op_sys_vendor = strdup((char *)val); + gopt.op_sys_vendor = xstrdup(val); return 0; } @@ -1199,7 +1246,7 @@ process_regular_option(const char *section, const char *key, const char *val, cf /* check if initializing a new map */ if (!cfm->cfm_dir) - cfm->cfm_dir = strdup((char *)section); + cfm->cfm_dir = xstrdup(section); /* check for each possible field */ if (STREQ(key, "browsable_dirs")) @@ -1223,6 +1270,9 @@ process_regular_option(const char *section, const char *key, const char *val, cf if (STREQ(key, "search_path")) return ropt_search_path(val, cfm); + if (STREQ(key, "sun_map_syntax")) + return ropt_sun_map_syntax(val, cfm); + if (STREQ(key, "tag")) return ropt_tag(val, cfm); @@ -1254,7 +1304,7 @@ ropt_browsable_dirs(const char *val, cf_map_t *cfm) static int ropt_map_name(const char *val, cf_map_t *cfm) { - cfm->cfm_name = strdup((char *)val); + cfm->cfm_name = xstrdup(val); return 0; } @@ -1262,7 +1312,7 @@ ropt_map_name(const char *val, cf_map_t *cfm) static int ropt_map_defaults(const char *val, cf_map_t *cfm) { - cfm->cfm_defaults = strdup((char *)val); + cfm->cfm_defaults = xstrdup(val); return 0; } @@ -1270,7 +1320,7 @@ ropt_map_defaults(const char *val, cf_map_t *cfm) static int ropt_map_options(const char *val, cf_map_t *cfm) { - cfm->cfm_opts = strdup((char *)val); + cfm->cfm_opts = xstrdup(val); return 0; } @@ -1283,7 +1333,7 @@ ropt_map_type(const char *val, cf_map_t *cfm) fprintf(stderr, "conf: no such map type \"%s\"\n", val); return 1; } - cfm->cfm_type = strdup((char *)val); + cfm->cfm_type = xstrdup(val); return 0; } @@ -1313,15 +1363,32 @@ ropt_mount_type(const char *val, cf_map_t *cfm) static int ropt_search_path(const char *val, cf_map_t *cfm) { - cfm->cfm_search_path = strdup((char *)val); + cfm->cfm_search_path = xstrdup(val); return 0; } +static int +ropt_sun_map_syntax(const char *val, cf_map_t *cfm) +{ + if (STREQ(val, "yes")) { + cfm->cfm_flags |= CFM_SUN_MAP_SYNTAX; + return 0; + + } else if (STREQ(val, "no")) { + cfm->cfm_flags &= ~CFM_SUN_MAP_SYNTAX; + return 0; + } + + fprintf(stderr, "conf: unknown value to sun_map_syntax \"%s\"\n", val); + return 1; /* unknown value */ +} + + static int ropt_tag(const char *val, cf_map_t *cfm) { - cfm->cfm_tag = strdup((char *)val); + cfm->cfm_tag = xstrdup(val); return 0; } @@ -1397,7 +1464,7 @@ find_cf_map(const char *name) return NULL; while (tmp_map) { - if (STREQ(tmp_map->cfm_dir,name)) { + if (STREQ(tmp_map->cfm_dir, name)) { return tmp_map; } tmp_map = tmp_map->cfm_next; diff --git a/contrib/amd/amd/conf_parse.y b/contrib/amd/amd/conf_parse.y index b397b057324..26c1b7ac790 100644 --- a/contrib/amd/amd/conf_parse.y +++ b/contrib/amd/amd/conf_parse.y @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/conf_tok.l b/contrib/amd/amd/conf_tok.l index b572e4d7d5a..fea2d8bf43f 100644 --- a/contrib/amd/amd/conf_tok.l +++ b/contrib/amd/amd/conf_tok.l @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -17,11 +17,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -74,7 +70,7 @@ */ #ifdef FLEX_SCANNER # ifndef ECHO -# define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +# define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout )) # endif /* not ECHO */ #endif /* FLEX_SCANNER */ @@ -86,9 +82,9 @@ int yylex(void); * which automatically generates yywrap macros and symbols. So I must * distinguish between them and when yywrap is actually needed. */ -#ifndef yywrap +#if !defined(yywrap) || defined(yylex) int yywrap(void); -#endif /* not yywrap */ +#endif /* not yywrap or yylex */ #define TOK_DEBUG 0 @@ -108,6 +104,7 @@ int yywrap(void); /* This option causes Solaris lex to fail. Use flex. See BUGS file */ /* no need to use yyunput() */ %option nounput +%option noinput /* allocate more output slots so lex scanners don't run out of mem */ %o 1024 @@ -131,19 +128,19 @@ NONQUOTE [^\"] \[ { dprintf("%8d: Left bracket \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); + conf_lval.strtype = xstrdup(yytext); amu_return(LEFT_BRACKET); } \] { dprintf("%8d: Right bracket \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); + conf_lval.strtype = xstrdup(yytext); amu_return(RIGHT_BRACKET); } = { dprintf("%8d: Equal \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); + conf_lval.strtype = xstrdup(yytext); amu_return(EQUAL); } @@ -159,7 +156,7 @@ NONQUOTE [^\"] {NONWSCHAR}{NONWSCHAR}* { dprintf("%8d: Non-WS string \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); + conf_lval.strtype = xstrdup(yytext); amu_return(NONWS_STRING); } @@ -167,13 +164,13 @@ NONQUOTE [^\"] dprintf("%8d: QUOTED-Non-WS-EQ string \"%s\"\n", yytext); /* must strip quotes */ yytext[strlen((char *)yytext)-1] = '\0'; - yylval.strtype = strdup((char *)&yytext[1]); + conf_lval.strtype = xstrdup(&yytext[1]); amu_return(QUOTED_NONWSEQ_STRING); } {NONWSEQCHAR}{NONWSEQCHAR}* { dprintf("%8d: Non-WS-EQ string \"%s\"\n", yytext); - yylval.strtype = strdup((char *)yytext); + conf_lval.strtype = xstrdup(yytext); amu_return(NONWSEQ_STRING); } @@ -184,9 +181,9 @@ NONQUOTE [^\"] * which automatically generates yywrap macros and symbols. So I must * distinguish between them and when yywrap is actually needed. */ -#ifndef yywrap +#if !defined(yywrap) || defined(yylex) int yywrap(void) { return 1; } -#endif /* not yywrap */ +#endif /* not yywrap or yylex */ diff --git a/contrib/amd/amd/get_args.c b/contrib/amd/amd/get_args.c index 8f743e6b2f3..724eff7cdbb 100644 --- a/contrib/amd/amd/get_args.c +++ b/contrib/amd/amd/get_args.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -84,38 +80,52 @@ get_version_string(void) len = 2048 + wire_buf_len; vers = xmalloc(len); xsnprintf(vers, len, "%s\n%s\n%s\n%s\n", - "Copyright (c) 1997-2006 Erez Zadok", + "Copyright (c) 1997-2014 Erez Zadok", "Copyright (c) 1990 Jan-Simon Pendry", "Copyright (c) 1990 Imperial College of Science, Technology & Medicine", "Copyright (c) 1990 The Regents of the University of California."); xsnprintf(tmpbuf, sizeof(tmpbuf), "%s version %s (build %d).\n", PACKAGE_NAME, PACKAGE_VERSION, AMU_BUILD_VERSION); - strlcat(vers, tmpbuf, len); + xstrlcat(vers, tmpbuf, len); xsnprintf(tmpbuf, sizeof(tmpbuf), "Report bugs to %s.\n", PACKAGE_BUGREPORT); - strlcat(vers, tmpbuf, len); + xstrlcat(vers, tmpbuf, len); +#if 0 + /* + * XXX This block (between from the #if 0 to #endif was in the + * XXX original was in the original merge however in the interest + * XXX of reproduceable builds and the fact that this is redundant + * XXX information, it is effectively removed. + */ + xsnprintf(tmpbuf, sizeof(tmpbuf), "Configured by %s@%s on date %s.\n", + USER_NAME, HOST_NAME, CONFIG_DATE); + xstrlcat(vers, tmpbuf, len); + xsnprintf(tmpbuf, sizeof(tmpbuf), "Built by %s@%s on date %s.\n", + BUILD_USER, BUILD_HOST, BUILD_DATE); + xstrlcat(vers, tmpbuf, len); +#endif xsnprintf(tmpbuf, sizeof(tmpbuf), "cpu=%s (%s-endian), arch=%s, karch=%s.\n", cpu, endian, gopt.arch, gopt.karch); - strlcat(vers, tmpbuf, len); + xstrlcat(vers, tmpbuf, len); xsnprintf(tmpbuf, sizeof(tmpbuf), "full_os=%s, os=%s, osver=%s, vendor=%s, distro=%s.\n", gopt.op_sys_full, gopt.op_sys, gopt.op_sys_ver, gopt.op_sys_vendor, DISTRO_NAME); - strlcat(vers, tmpbuf, len); + xstrlcat(vers, tmpbuf, len); xsnprintf(tmpbuf, sizeof(tmpbuf), "domain=%s, host=%s, hostd=%s.\n", hostdomain, am_get_hostname(), hostd); - strlcat(vers, tmpbuf, len); + xstrlcat(vers, tmpbuf, len); - strlcat(vers, "Map support for: ", len); + xstrlcat(vers, "Map support for: ", len); mapc_showtypes(tmpbuf, sizeof(tmpbuf)); - strlcat(vers, tmpbuf, len); - strlcat(vers, ".\nAMFS: ", len); + xstrlcat(vers, tmpbuf, len); + xstrlcat(vers, ".\nAMFS: ", len); ops_showamfstypes(tmpbuf, sizeof(tmpbuf)); - strlcat(vers, tmpbuf, len); - strlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */ + xstrlcat(vers, tmpbuf, len); + xstrlcat(vers, ", inherit.\nFS: ", len); /* hack: "show" that we support type:=inherit */ ops_showfstypes(tmpbuf, sizeof(tmpbuf)); - strlcat(vers, tmpbuf, len); + xstrlcat(vers, tmpbuf, len); /* append list of networks if available */ if (wire_buf) { - strlcat(vers, wire_buf, len); + xstrlcat(vers, wire_buf, len); XFREE(wire_buf); } @@ -325,19 +335,18 @@ get_args(int argc, char *argv[]) perror(buf); exit(1); } - yyin = fp; - yyparse(); + conf_in = fp; + conf_parse(); fclose(fp); if (process_all_regular_maps() != 0) exit(1); } - /* make sure there are some default options defined */ - if (xlog_level_init == ~0) { - switch_option(""); - } #ifdef DEBUG usage += switch_option("debug"); + /* initialize debug options */ + if (!debug_flags) + debug_flags = D_CONTROL; /* CONTROL = "daemon,amq,fork" */ #endif /* DEBUG */ /* log information regarding amd.conf file */ diff --git a/contrib/amd/amd/info_exec.c b/contrib/amd/amd/info_exec.c index 8ccab9aee57..95216c90e2e 100644 --- a/contrib/amd/amd/info_exec.c +++ b/contrib/amd/amd/info_exec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -52,8 +48,8 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include -#define MAX_LINE_LEN 1500 /* forward declarations */ int exec_init(mnt_map *m, char *map, time_t *tp); @@ -74,13 +70,13 @@ fgets_timed(char *s, int size, int rdfd, int secs) if (!s || size < 0 || rdfd < 0) return 0; - s[0] = 0; + s[0] = '\0'; if (size == 0) return s; start = clocktime(NULL); while (s[i] != '\n' && i < size-1) { - s[i+1] = 0; /* places the requisite trailing '\0' */ + s[i+1] = '\0'; /* places the requisite trailing '\0' */ /* ready for reading */ rval = read(rdfd, (void *)(s+i), 1); @@ -114,7 +110,7 @@ fgets_timed(char *s, int size, int rdfd, int secs) FD_ZERO(&fds); FD_SET(rdfd, &fds); - rval = select(rdfd+1, &fds, 0, 0, &timeo); + rval = select(rdfd+1, &fds, NULL, NULL, &timeo); if (rval < 0) { /* error selecting */ plog(XLOG_WARNING, "fgets_timed select error: %m"); @@ -165,9 +161,9 @@ read_line(char *buf, int size, int fd) * Try to locate a value in a query answer */ static int -exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp) +exec_parse_qanswer(mnt_map *m, int fd, char *map, char *key, char **pval, time_t *tp) { - char qanswer[MAX_LINE_LEN], *dc = 0; + char qanswer[INFO_MAX_LINE_LEN], *dc = NULL; int chuck = 0; int line_no = 0; @@ -197,7 +193,7 @@ exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp) /* * Find beginning of value (query answer) */ - for (cp = qanswer; *cp && !isascii((int)*cp) && !isspace((int)*cp); cp++) + for (cp = qanswer; *cp && !isascii((unsigned char)*cp) && !isspace((unsigned char)*cp); cp++) ;; /* Ignore blank lines */ @@ -207,7 +203,10 @@ exec_parse_qanswer(int fd, char *map, char *key, char **pval, time_t *tp) /* * Return a copy of the data */ - dc = strdup(cp); + if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) + dc = sun_entry2amd(key, cp); + else + dc = xstrdup(cp); *pval = dc; dlog("%s returns %s", key, dc); @@ -324,7 +323,7 @@ exec_map_open(char *emap, char *key) close(pdes[1]); /* anti-zombie insurance */ - while (waitpid(p1,0,0) < 0) + while (waitpid(p1, 0, 0) < 0) if (errno != EINTR) exit(errno); @@ -416,7 +415,7 @@ exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) if (tp) *tp = clocktime(NULL); - return exec_parse_qanswer(mapfd, map, key, pval, tp); + return exec_parse_qanswer(m, mapfd, map, key, pval, tp); } return errno; diff --git a/contrib/amd/amd/info_file.c b/contrib/amd/amd/info_file.c index 3777a2aebe9..738c7bfa577 100644 --- a/contrib/amd/amd/info_file.c +++ b/contrib/amd/amd/info_file.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -50,8 +46,8 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include -#define MAX_LINE_LEN 1500 /* forward declarations */ int file_init_or_mtime(mnt_map *m, char *map, time_t *tp); @@ -59,8 +55,8 @@ int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)); int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); -static int -read_line(char *buf, int size, FILE *fp) +int +file_read_line(char *buf, int size, FILE *fp) { int done = 0; @@ -79,7 +75,7 @@ read_line(char *buf, int size, FILE *fp) * Skip leading white space on next line */ while ((ch = getc(fp)) != EOF && - isascii(ch) && isspace(ch)) ; + isascii((unsigned char)ch) && isspace((unsigned char)ch)) ; (void) ungetc(ch, fp); } else { return done; @@ -95,18 +91,18 @@ read_line(char *buf, int size, FILE *fp) * Try to locate a key in a file */ static int -file_search_or_reload(FILE *fp, +file_search_or_reload(mnt_map *m, + FILE *fp, char *map, char *key, char **val, - mnt_map *m, void (*fn) (mnt_map *m, char *, char *)) { - char key_val[MAX_LINE_LEN]; + char key_val[INFO_MAX_LINE_LEN]; int chuck = 0; int line_no = 0; - while (read_line(key_val, sizeof(key_val), fp)) { + while (file_read_line(key_val, sizeof(key_val), fp)) { char *kp; char *cp; char *hash; @@ -133,7 +129,7 @@ file_search_or_reload(FILE *fp, /* * Find start of key */ - for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ; + for (kp = key_val; *kp && isascii((unsigned char)*kp) && isspace((unsigned char)*kp); kp++) ; /* * Ignore blank lines @@ -144,7 +140,7 @@ file_search_or_reload(FILE *fp, /* * Find end of key */ - for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ; + for (cp = kp; *cp && (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)); cp++) ; /* * Check whether key matches @@ -153,15 +149,20 @@ file_search_or_reload(FILE *fp, *cp++ = '\0'; if (fn || (*key == *kp && STREQ(key, kp))) { - while (*cp && isascii(*cp) && isspace((int)*cp)) + while (*cp && isascii((unsigned char)*cp) && isspace((unsigned char)*cp)) cp++; if (*cp) { /* * Return a copy of the data */ - char *dc = strdup(cp); + char *dc; + /* if m->cfm == NULL, not using amd.conf file */ + if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) + dc = sun_entry2amd(kp, cp); + else + dc = xstrdup(cp); if (fn) { - (*fn) (m, strdup(kp), dc); + (*fn) (m, xstrdup(kp), dc); } else { *val = dc; dlog("%s returns %s", key, dc); @@ -221,10 +222,10 @@ file_init_or_mtime(mnt_map *m, char *map, time_t *tp) int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) { - FILE *mapf = file_open(map, (time_t *) 0); + FILE *mapf = file_open(map, (time_t *) NULL); if (mapf) { - int error = file_search_or_reload(mapf, map, 0, 0, m, fn); + int error = file_search_or_reload(m, mapf, map, NULL, NULL, fn); (void) fclose(mapf); return error; } @@ -244,7 +245,7 @@ file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) *tp = t; error = -1; } else { - error = file_search_or_reload(mapf, map, key, pval, 0, 0); + error = file_search_or_reload(m, mapf, map, key, pval, NULL); } (void) fclose(mapf); return error; diff --git a/contrib/amd/amd/info_hesiod.c b/contrib/amd/amd/info_hesiod.c index e345c996150..0293f435a26 100644 --- a/contrib/amd/amd/info_hesiod.c +++ b/contrib/amd/amd/info_hesiod.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -50,6 +46,7 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include #define HES_PREFIX "hesiod." #define HES_PREFLEN 7 @@ -127,7 +124,11 @@ hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) * it (and free subsequent replies) */ if (rvec && *rvec) { - *pval = *rvec; + if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) { + *pval = sun_entry2amd(key, *rvec); + XFREE(*rvec); + } else + *pval = *rvec; while (*++rvec) XFREE(*rvec); return 0; diff --git a/contrib/amd/amd/info_ldap.c b/contrib/amd/amd/info_ldap.c index 36ce1c8693d..cfed6fd773d 100644 --- a/contrib/amd/amd/info_ldap.c +++ b/contrib/amd/amd/info_ldap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -66,6 +62,7 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include /* @@ -118,12 +115,17 @@ struct he_ent { struct he_ent *next; }; +static ALD *ldap_connection; + /* * FORWARD DECLARATIONS: */ static int amu_ldap_rebind(ALD *a); static int get_ldap_timestamp(ALD *a, char *map, time_t *ts); +int amu_ldap_init(mnt_map *m, char *map, time_t *tsu); +int amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts); +int amu_ldap_mtime(mnt_map *m, char *map, time_t *ts); /* * FUNCTIONS: @@ -144,30 +146,33 @@ string2he(char *s_orig) { char *c, *p; char *s; - HE_ENT *new, *old = NULL; + HE_ENT *first = NULL, *cur = NULL; - if (NULL == s_orig || NULL == (s = strdup(s_orig))) + if (NULL == s_orig) return NULL; - for (p = s; p; p = strchr(p, ',')) { - if (old != NULL) { - new = ALLOC(HE_ENT); - old->next = new; - old = new; - } else { - old = ALLOC(HE_ENT); - old->next = NULL; - } + s = xstrdup(s_orig); + for (p = strtok(s, ","); p; p = strtok(NULL, ",")) { + if (cur != NULL) { + cur->next = ALLOC(HE_ENT); + cur = cur->next; + } else + first = cur = ALLOC(HE_ENT); + + cur->next = NULL; c = strchr(p, ':'); if (c) { /* Host and port */ *c++ = '\0'; - old->host = strdup(p); - old->port = atoi(c); - } else - old->host = strdup(p); - + cur->host = xstrdup(p); + cur->port = atoi(c); + } else { + cur->host = xstrdup(p); + cur->port = LDAP_PORT; + } + plog(XLOG_USER, "Adding ldap server %s:%d", + cur->host, cur->port); } XFREE(s); - return (old); + return first; } @@ -248,10 +253,18 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts) if (!gopt.map_type || !STREQ(gopt.map_type, AMD_LDAP_TYPE)) { dlog("amu_ldap_init called with map_type <%s>\n", (gopt.map_type ? gopt.map_type : "null")); + return ENOENT; } else { dlog("Map %s is ldap\n", map); } +#ifndef LDAP_CONNECTION_PER_MAP + if (ldap_connection != NULL) { + m->map_data = (void *) ldap_connection; + return 0; + } +#endif + aldh = ALLOC(ALD); creds = ALLOC(CR); aldh->ldap = NULL; @@ -274,11 +287,14 @@ amu_ldap_init(mnt_map *m, char *map, time_t *ts) ald_free(aldh); return (ENOENT); } - m->map_data = (void *) aldh; dlog("Bound to %s:%d\n", aldh->hostent->host, aldh->hostent->port); - if (get_ldap_timestamp(aldh, map, ts)) + if (get_ldap_timestamp(aldh, map, ts)) { + ald_free(aldh); return (ENOENT); + } dlog("Got timestamp for map %s: %ld\n", map, (u_long) *ts); + ldap_connection = aldh; + m->map_data = (void *) ldap_connection; return (0); } @@ -312,7 +328,7 @@ amu_ldap_rebind(ALD *a) for (h = a->hostent; h != NULL; h = h->next) { if ((ld = ldap_open(h->host, h->port)) == NULL) { plog(XLOG_WARNING, "Unable to ldap_open to %s:%d\n", h->host, h->port); - break; + continue; } #if LDAP_VERSION_MAX > LDAP_VERSION2 /* handle LDAPv3 and heigher, if available and amd.conf-igured */ @@ -321,16 +337,16 @@ amu_ldap_rebind(ALD *a) dlog("amu_ldap_rebind: LDAP protocol version set to %ld\n", gopt.ldap_proto_version); } else { - plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld\n", - gopt.ldap_proto_version); - break; + plog(XLOG_WARNING, "Unable to set ldap protocol version to %ld for " + "%s:%d\n", gopt.ldap_proto_version, h->host, h->port); + continue; } } #endif /* LDAP_VERSION_MAX > LDAP_VERSION2 */ if (ldap_bind_s(ld, c->who, c->pw, c->method) != LDAP_SUCCESS) { plog(XLOG_WARNING, "Unable to ldap_bind to %s:%d as %s\n", h->host, h->port, c->who); - break; + continue; } if (gopt.ldap_cache_seconds > 0) { #if defined(HAVE_LDAP_ENABLE_CACHE) && defined(HAVE_EXTERN_LDAP_ENABLE_CACHE) @@ -541,7 +557,10 @@ amu_ldap_search(mnt_map *m, char *map, char *key, char **pval, time_t *ts) } dlog("Map %s, %s => %s\n", map, key, vals[0]); if (vals[0]) { - *pval = strdup(vals[0]); + if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) + *pval = sun_entry2amd(key, vals[0]); + else + *pval = xstrdup(vals[0]); err = 0; } else { plog(XLOG_USER, "Empty value for %s in map %s\n", key, map); diff --git a/contrib/amd/amd/info_ndbm.c b/contrib/amd/amd/info_ndbm.c index 8a52ba9e201..5f2f52b5330 100644 --- a/contrib/amd/amd/info_ndbm.c +++ b/contrib/amd/amd/info_ndbm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -50,6 +46,7 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include /* forward declarations */ int ndbm_init(mnt_map *m, char *map, time_t *tp); @@ -58,7 +55,7 @@ int ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); static int -search_ndbm(DBM *db, char *key, char **val) +search_ndbm(mnt_map *m, DBM *db, char *key, char **val) { datum k, v; @@ -66,7 +63,10 @@ search_ndbm(DBM *db, char *key, char **val) k.dsize = strlen(key) + 1; v = dbm_fetch(db, k); if (v.dptr) { - *val = strdup(v.dptr); + if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) + *val = sun_entry2amd(key, v.dptr); + else + *val = xstrdup(v.dptr); return 0; } return ENOENT; @@ -95,7 +95,7 @@ ndbm_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) *tp = stb.st_mtime; error = -1; } else { - error = search_ndbm(db, key, pval); + error = search_ndbm(m, db, key, pval); } (void) dbm_close(db); return error; diff --git a/contrib/amd/amd/info_nis.c b/contrib/amd/amd/info_nis.c index bcb87d5d02a..83dc4b7a84f 100644 --- a/contrib/amd/amd/info_nis.c +++ b/contrib/amd/amd/info_nis.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -50,6 +46,7 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include /* @@ -109,7 +106,7 @@ determine_nis_domain(void) plog(XLOG_WARNING, "NIS domain name is not set. NIS ignored."); return ENOENT; } - gopt.nis_domain = strdup(default_domain); + gopt.nis_domain = xstrdup(default_domain); return 0; } @@ -167,6 +164,7 @@ nis_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) cbinfo.data = (voidp) &data; cbinfo.foreach = (ypall_callback_fxn_t) callback; + plog(XLOG_INFO, "NIS map %s reloading using yp_all", map); /* * If you are using NIS and your yp_all function is "broken", you have to * get it fixed. The bug in yp_all() is that it does not close a TCP @@ -247,7 +245,7 @@ nis_isup(mnt_map *m, char *map) * Try to locate a key using NIS. */ int -nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp) +nis_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) { int outlen; int res; @@ -301,7 +299,15 @@ nis_search(mnt_map *m, char *map, char *key, char **val, time_t *tp) /* * Lookup key */ - res = yp_match(gopt.nis_domain, map, key, strlen(key), val, &outlen); + res = yp_match(gopt.nis_domain, map, key, strlen(key), pval, &outlen); + if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX) && res == 0) { + char *oldval = *pval; + *pval = sun_entry2amd(key, oldval); + /* We always need to free the output of the yp_match call. */ + XFREE(oldval); + if (*pval == NULL) + return -1; /* sun2amd parser error */ + } /* * Do something interesting with the return code diff --git a/contrib/amd/amd/info_nisplus.c b/contrib/amd/amd/info_nisplus.c index d392b48fed6..79df8361470 100644 --- a/contrib/amd/amd/info_nisplus.c +++ b/contrib/amd/amd/info_nisplus.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -50,6 +46,7 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include #define NISPLUS_KEY "key=" #define NISPLUS_ORGDIR ".org_dir" @@ -221,7 +218,12 @@ nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp) if (value != NULL) data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1)); } - *val = data.value; + + if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) { + *val = sun_entry2amd(key, data.value); + XFREE(data.value); /* strnsave malloc'ed it above */ + } else + *val = data.value; if (*val) { error = 0; diff --git a/contrib/amd/amd/info_passwd.c b/contrib/amd/amd/info_passwd.c index c8bf388b1d6..3c4486693c6 100644 --- a/contrib/amd/amd/info_passwd.c +++ b/contrib/amd/amd/info_passwd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -94,11 +90,11 @@ passwd_init(mnt_map *m, char *map, time_t *tp) int passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) { - char *dir = 0; + char *dir = NULL; struct passwd *pw; if (STREQ(key, "/defaults")) { - *pval = strdup("type:=nfs"); + *pval = xstrdup("type:=nfs"); return 0; } pw = getpwnam(key); @@ -123,7 +119,7 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) char *p, *q; char val[MAXPATHLEN]; char rhost[MAXHOSTNAMELEN]; - dir = strdup(pw->pw_dir); + dir = xstrdup(pw->pw_dir); /* * Find user name. If no / then Invalid... @@ -180,13 +176,12 @@ passwd_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) dlog("passwd_search: map=%s key=%s -> %s", map, key, val); if (q) *q = '.'; - *pval = strdup(val); + *pval = xstrdup(val); return 0; } enoent: - if (dir) - XFREE(dir); + XFREE(dir); return ENOENT; } diff --git a/contrib/amd/amd/info_sun.c b/contrib/amd/amd/info_sun.c new file mode 100644 index 00000000000..3f56965ff74 --- /dev/null +++ b/contrib/amd/amd/info_sun.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/info_sun.c + * + */ + +/* + * Get info from Sun automount-style /etc/auto_master, possibly following + * into multiple info services (via /etc/nsswitch.conf). + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#include +#include +#include + + +/* XXX: just a placeholder. fill in */ diff --git a/contrib/amd/amd/info_union.c b/contrib/amd/amd/info_union.c index 8f0631c64ac..df480317bdd 100644 --- a/contrib/amd/amd/info_union.c +++ b/contrib/amd/amd/info_union.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -77,7 +73,7 @@ union_init(mnt_map *m, char *map, time_t *tp) int union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) { - char *mapd = strdup(map + UNION_PREFLEN); + char *mapd = xstrdup(map + UNION_PREFLEN); char **v = strsplit(mapd, ':', '\"'); char **p; size_t l; @@ -95,14 +91,15 @@ union_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) int union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) { - char *mapd = strdup(map + UNION_PREFLEN); + static const char fseq[] = "fs:="; + char *mapd = xstrdup(map + UNION_PREFLEN); char **v = strsplit(mapd, ':', '\"'); char **dir; /* * Add fake /defaults entry */ - (*fn) (m, strdup("/defaults"), strdup("type:=link;opts:=nounmount;sublink:=${key}")); + (*fn) (m, xstrdup("/defaults"), xstrdup("type:=link;opts:=nounmount;sublink:=${key}")); for (dir = v; *dir; dir++) { size_t l; @@ -113,7 +110,7 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) plog(XLOG_USER, "Cannot read directory %s: %m", *dir); continue; } - l = strlen(*dir) + 5; + l = strlen(*dir) + sizeof(fseq); dlog("Reading directory %s...", *dir); while ((dp = readdir(dirp))) { @@ -125,8 +122,8 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) dlog("... gives %s", dp->d_name); val = xmalloc(l); - xsnprintf(val, l + 5, "fs:=%s", *dir); - (*fn) (m, strdup(dp->d_name), val); + xsnprintf(val, l, "%s%s", fseq, *dir); + (*fn) (m, xstrdup(dp->d_name), val); } closedir(dirp); } @@ -135,11 +132,11 @@ union_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) * Add wildcard entry */ { - size_t l = strlen(*(dir-1)) + 5; + size_t l = strlen(*(dir-1)) + sizeof(fseq); char *val = xmalloc(l); - xsnprintf(val, l, "fs:=%s", *(dir-1)); - (*fn) (m, strdup("*"), val); + xsnprintf(val, l, "%s%s", fseq, *(dir-1)); + (*fn) (m, xstrdup("*"), val); } XFREE(mapd); XFREE(v); diff --git a/contrib/amd/amd/map.c b/contrib/amd/amd/map.c index 8696dfd6984..0d404cfdbd6 100644 --- a/contrib/amd/amd/map.c +++ b/contrib/amd/amd/map.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -69,7 +65,7 @@ static u_int am_gen = 2; /* Initial generation number */ static int timeout_mp_id; /* Id from last call to timeout */ static am_node *root_node; /* The root of the mount tree */ -static am_node **exported_ap = (am_node **) 0; +static am_node **exported_ap = (am_node **) NULL; static int exported_ap_size = 0; static int first_free_map = 0; /* First available free slot */ static int last_used_map = -1; /* Last unavailable used slot */ @@ -190,7 +186,7 @@ am_node * get_ap_child(am_node *mp, char *fname) { am_node *new_mp; - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; /* * Allocate a new map @@ -280,7 +276,7 @@ exported_ap_free(am_node *mp) /* * Zero the slot pointer to avoid double free's */ - exported_ap[mp->am_mapno] = 0; + exported_ap[mp->am_mapno] = NULL; /* * Update the free and last_used indices @@ -325,7 +321,7 @@ insert_am(am_node *mp, am_node *p_mp) mp->am_osib->am_ysib = mp; p_mp->am_child = mp; #ifdef HAVE_FS_AUTOFS - if (p_mp->am_mnt->mf_flags & MFF_IS_AUTOFS) + if (p_mp->am_al->al_mnt->mf_flags & MFF_IS_AUTOFS) mp->am_flags |= AMF_AUTOFS; #endif /* HAVE_FS_AUTOFS */ } @@ -408,13 +404,14 @@ init_map(am_node *mp, char *dir) * mp->am_mapno is initialized by exported_ap_alloc * other fields don't need to be set to zero. */ - mp->am_mnt = new_mntfs(); - mp->am_mfarray = 0; - mp->am_name = strdup(dir); - mp->am_path = strdup(dir); + + mp->am_al = new_loc(); + mp->am_alarray = NULL; + mp->am_name = xstrdup(dir); + mp->am_path = xstrdup(dir); mp->am_gen = new_gen(); #ifdef HAVE_FS_AUTOFS - mp->am_autofs_fh = 0; + mp->am_autofs_fh = NULL; #endif /* HAVE_FS_AUTOFS */ mp->am_timeo = gopt.am_timeo; @@ -430,6 +427,30 @@ init_map(am_node *mp, char *dir) mp->am_stats.s_mtime = mp->am_fattr.na_atime.nt_seconds; mp->am_dev = -1; mp->am_rdev = -1; + mp->am_fd[0] = -1; + mp->am_fd[1] = -1; +} + + +void +notify_child(am_node *mp, au_etype au_etype, int au_errno, int au_signal) +{ + amq_sync_umnt rv; + int err; + + if (mp->am_fd[1] >= 0) { /* we have a child process */ + rv.au_etype = au_etype; + rv.au_signal = au_signal; + rv.au_errno = au_errno; + + err = write(mp->am_fd[1], &rv, sizeof(rv)); + /* XXX: do something else on err? */ + if (err < sizeof(rv)) + plog(XLOG_INFO, "notify_child: write returned %d instead of %d.", + err, (int) sizeof(rv)); + close(mp->am_fd[1]); + mp->am_fd[1] = -1; + } } @@ -442,25 +463,24 @@ free_map(am_node *mp) { remove_am(mp); - if (mp->am_link) - XFREE(mp->am_link); - if (mp->am_name) - XFREE(mp->am_name); - if (mp->am_path) - XFREE(mp->am_path); - if (mp->am_pref) - XFREE(mp->am_pref); - if (mp->am_transp) - XFREE(mp->am_transp); + if (mp->am_fd[1] != -1) + plog(XLOG_FATAL, "free_map: called prior to notifying the child for %s.", + mp->am_path); - if (mp->am_mnt) - free_mntfs(mp->am_mnt); + XFREE(mp->am_link); + XFREE(mp->am_name); + XFREE(mp->am_path); + XFREE(mp->am_pref); + XFREE(mp->am_transp); - if (mp->am_mfarray) { - mntfs **temp_mf; - for (temp_mf = mp->am_mfarray; *temp_mf; temp_mf++) - free_mntfs(*temp_mf); - XFREE(mp->am_mfarray); + if (mp->am_al) + free_loc(mp->am_al); + + if (mp->am_alarray) { + am_loc **temp_al; + for (temp_al = mp->am_alarray; *temp_al; temp_al++) + free_loc(*temp_al); + XFREE(mp->am_alarray); } #ifdef HAVE_FS_AUTOFS @@ -480,8 +500,8 @@ find_ap_recursive(char *dir, am_node *mp) if (STREQ(mp->am_path, dir)) return mp; - if ((mp->am_mnt->mf_flags & MFF_MOUNTED) && - STREQ(mp->am_mnt->mf_mount, dir)) + if ((mp->am_al->al_mnt->mf_flags & MFF_MOUNTED) && + STREQ(mp->am_al->al_mnt->mf_mount, dir)) return mp; mp2 = find_ap_recursive(dir, mp->am_osib); @@ -517,38 +537,21 @@ find_ap(char *dir) } -/* - * Find the mount node corresponding - * to the mntfs structure. - */ -am_node * -find_mf(mntfs *mf) -{ - int i; - - for (i = last_used_map; i >= 0; --i) { - am_node *mp = exported_ap[i]; - if (mp && mp->am_mnt == mf) - return mp; - } - - return 0; -} - - /* * Get the filehandle for a particular named directory. * This is used during the bootstrap to tell the kernel * the filehandles of the initial automount points. */ -am_nfs_fh * -get_root_nfs_fh(char *dir) +am_nfs_handle_t * +get_root_nfs_fh(char *dir, am_nfs_handle_t *nfh) { - static am_nfs_fh nfh; am_node *mp = get_root_ap(dir); if (mp) { - mp_to_fh(mp, &nfh); - return &nfh; + if (nfs_dispatcher == nfs_program_2) + mp_to_fh(mp, &nfh->v2); + else + mp_to_fh3(mp, &nfh->v3); + return nfh; } /* @@ -584,7 +587,8 @@ map_flush_srvr(fserver *fs) for (i = last_used_map; i >= 0; --i) { am_node *mp = exported_ap[i]; - if (mp && mp->am_mnt && mp->am_mnt->mf_server == fs) { + + if (mp && mp->am_al->al_mnt && mp->am_al->al_mnt->mf_server == fs) { plog(XLOG_INFO, "Flushed %s; dependent on %s", mp->am_path, fs->fs_host); mp->am_ttl = clocktime(NULL); done = 1; @@ -608,7 +612,7 @@ mount_auto_node(char *dir, opaque_t arg) am_node *mp = (am_node *) arg; am_node *new_mp; - new_mp = mp->am_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE); + new_mp = mp->am_al->al_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE); if (new_mp && error < 0) { /* * We can't allow the fileid of the root node to change. @@ -616,7 +620,7 @@ mount_auto_node(char *dir, opaque_t arg) */ new_mp->am_gen = new_mp->am_fattr.na_fileid = 1; - new_mp = mp->am_mnt->mf_ops->mount_child(new_mp, &error); + (void) mp->am_al->al_mnt->mf_ops->mount_child(new_mp, &error); } if (error > 0) { @@ -647,7 +651,7 @@ mount_exported(void) void make_root_node(void) { - mntfs *root_mnt; + mntfs *root_mf; char *rootmap = ROOT_MAP; root_node = exported_ap_alloc(); @@ -659,24 +663,24 @@ make_root_node(void) /* * Allocate a new mounted filesystem */ - root_mnt = find_mntfs(&amfs_root_ops, (am_opts *) 0, "", rootmap, "", "", ""); + root_mf = find_mntfs(&amfs_root_ops, (am_opts *) NULL, "", rootmap, "", "", ""); /* * Replace the initial null reference */ - free_mntfs(root_node->am_mnt); - root_node->am_mnt = root_mnt; + free_mntfs(root_node->am_al->al_mnt); + root_node->am_al->al_mnt = root_mf; /* * Initialize the root */ - if (root_mnt->mf_ops->fs_init) - (*root_mnt->mf_ops->fs_init) (root_mnt); + if (root_mf->mf_ops->fs_init) + (*root_mf->mf_ops->fs_init) (root_mf); /* * Mount the root */ - root_mnt->mf_error = root_mnt->mf_ops->mount_fs(root_node, root_mnt); + root_mf->mf_error = root_mf->mf_ops->mount_fs(root_node, root_mf); } @@ -687,68 +691,81 @@ make_root_node(void) void umount_exported(void) { - int i; + int i, work_done; - for (i = last_used_map; i >= 0; --i) { - am_node *mp = exported_ap[i]; - mntfs *mf; + do { + work_done = 0; - if (!mp) - continue; + for (i = last_used_map; i >= 0; --i) { + am_node *mp = exported_ap[i]; + mntfs *mf; - mf = mp->am_mnt; - if (mf->mf_flags & MFF_UNMOUNTING) { - /* - * If this node is being unmounted then just ignore it. However, - * this could prevent amd from finishing if the unmount gets blocked - * since the am_node will never be free'd. am_unmounted needs - * telling about this possibility. - XXX - */ - continue; - } - - if (!(mf->mf_fsflags & FS_DIRECTORY)) - /* - * When shutting down this had better - * look like a directory, otherwise it - * can't be unmounted! - */ - mk_fattr(&mp->am_fattr, NFDIR); - - if ((--immediate_abort < 0 && - !(mp->am_flags & AMF_ROOT) && mp->am_parent) || - (mf->mf_flags & MFF_RESTART)) { + if (!mp) + continue; /* - * Just throw this node away without bothering to unmount it. If - * the server is not known to be up then don't discard the mounted - * on directory or Amd might hang... + * Wait for children to be removed first */ - if (mf->mf_server && - (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) != FSF_VALID) - mf->mf_flags &= ~MFF_MKMNT; - if (gopt.flags & CFM_UNMOUNT_ON_EXIT || mp->am_flags & AMF_AUTOFS) { - plog(XLOG_INFO, "on-exit attempt to unmount %s", mf->mf_mount); + if (mp->am_child) + continue; + + mf = mp->am_al->al_mnt; + if (mf->mf_flags & MFF_UNMOUNTING) { /* - * use unmount_mp, not unmount_node, so that unmounts be - * backgrounded as needed. + * If this node is being unmounted then just ignore it. However, + * this could prevent amd from finishing if the unmount gets blocked + * since the am_node will never be free'd. am_unmounted needs + * telling about this possibility. - XXX */ - unmount_mp((opaque_t) mp); - } else { - am_unmounted(mp); + continue; + } + + if (!(mf->mf_fsflags & FS_DIRECTORY)) + /* + * When shutting down this had better + * look like a directory, otherwise it + * can't be unmounted! + */ + mk_fattr(&mp->am_fattr, NFDIR); + + if ((--immediate_abort < 0 && + !(mp->am_flags & AMF_ROOT) && mp->am_parent) || + (mf->mf_flags & MFF_RESTART)) { + + work_done++; + + /* + * Just throw this node away without bothering to unmount it. If + * the server is not known to be up then don't discard the mounted + * on directory or Amd might hang... + */ + if (mf->mf_server && + (mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) != FSF_VALID) + mf->mf_flags &= ~MFF_MKMNT; + if (gopt.flags & CFM_UNMOUNT_ON_EXIT || mp->am_flags & AMF_AUTOFS) { + plog(XLOG_INFO, "on-exit attempt to unmount %s", mf->mf_mount); + /* + * use unmount_mp, not unmount_node, so that unmounts be + * backgrounded as needed. + */ + unmount_mp((opaque_t) mp); + } else { + am_unmounted(mp); + } + if (!(mf->mf_flags & (MFF_UNMOUNTING|MFF_MOUNTED))) + exported_ap[i] = NULL; + } else { + /* + * Any other node gets forcibly timed out. + */ + mp->am_flags &= ~AMF_NOTIMEOUT; + mp->am_al->al_mnt->mf_flags &= ~MFF_RSTKEEP; + mp->am_ttl = 0; + mp->am_timeo = 1; + mp->am_timeo_w = 0; } - exported_ap[i] = 0; - } else { - /* - * Any other node gets forcibly timed out. - */ - mp->am_flags &= ~AMF_NOTIMEOUT; - mp->am_mnt->mf_flags &= ~MFF_RSTKEEP; - mp->am_ttl = 0; - mp->am_timeo = 1; - mp->am_timeo_w = 0; } - } + } while (work_done); } @@ -762,7 +779,7 @@ int mount_node(opaque_t arg) { am_node *mp = (am_node *) arg; - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; int error = 0; #ifdef HAVE_FS_AUTOFS @@ -784,7 +801,7 @@ static int unmount_node(opaque_t arg) { am_node *mp = (am_node *) arg; - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; int error = 0; if (mf->mf_flags & MFF_ERROR) { @@ -805,7 +822,7 @@ unmount_node(opaque_t arg) } /* do this again, it might have changed */ - mf = mp->am_mnt; + mf = mp->am_al->al_mnt; if (error) { errno = error; /* XXX */ dlog("%s: unmount: %m", mf->mf_mount); @@ -819,7 +836,7 @@ static void free_map_if_success(int rc, int term, opaque_t arg) { am_node *mp = (am_node *) arg; - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; wchan_t wchan = get_mntfs_wchan(mf); /* @@ -836,6 +853,7 @@ free_map_if_success(int rc, int term, opaque_t arg) reschedule_timeout_mp(); } if (term) { + notify_child(mp, AMQ_UMNT_SIGNAL, 0, term); plog(XLOG_ERROR, "unmount for %s got signal %d", mp->am_path, term); #if defined(DEBUG) && defined(SIGTRAP) /* @@ -852,18 +870,24 @@ free_map_if_success(int rc, int term, opaque_t arg) #endif /* HAVE_FS_AUTOFS */ amd_stats.d_uerr++; } else if (rc) { + notify_child(mp, AMQ_UMNT_FAILED, rc, 0); if (mf->mf_ops == &amfs_program_ops || rc == EBUSY) plog(XLOG_STATS, "\"%s\" on %s still active", mp->am_path, mf->mf_mount); else plog(XLOG_ERROR, "%s: unmount: %s", mp->am_path, strerror(rc)); #ifdef HAVE_FS_AUTOFS - if (mf->mf_flags & MFF_IS_AUTOFS) - autofs_get_mp(mp); - if (mp->am_flags & AMF_AUTOFS) - autofs_umount_failed(mp); + if (rc != ENOENT) { + if (mf->mf_flags & MFF_IS_AUTOFS) + autofs_get_mp(mp); + if (mp->am_flags & AMF_AUTOFS) + autofs_umount_failed(mp); + } #endif /* HAVE_FS_AUTOFS */ amd_stats.d_uerr++; } else { + /* + * am_unmounted() will call notify_child() appropriately. + */ am_unmounted(mp); } @@ -878,11 +902,11 @@ int unmount_mp(am_node *mp) { int was_backgrounded = 0; - mntfs *mf = mp->am_mnt; + mntfs *mf = mp->am_al->al_mnt; #ifdef notdef plog(XLOG_INFO, "\"%s\" on %s timed out (flags 0x%x)", - mp->am_path, mp->am_mnt->mf_mount, (int) mf->mf_flags); + mp->am_path, mf->mf_mount, (int) mf->mf_flags); #endif /* notdef */ #ifndef MNT2_NFS_OPT_SYMTTL @@ -914,10 +938,11 @@ unmount_mp(am_node *mp) plog(XLOG_STATS, "file server %s is down - timeout of \"%s\" ignored", mf->mf_server->fs_host, mp->am_path); mf->mf_flags |= MFF_LOGDOWN; } + notify_child(mp, AMQ_UMNT_SERVER, 0, 0); return 0; } - dlog("\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount); + dlog("\"%s\" on %s timed out", mp->am_path, mf->mf_mount); mf->mf_flags |= MFF_UNMOUNTING; #ifdef HAVE_FS_AUTOFS @@ -926,7 +951,8 @@ unmount_mp(am_node *mp) #endif /* HAVE_FS_AUTOFS */ if ((mf->mf_fsflags & FS_UBACKGROUND) && - (mf->mf_flags & MFF_MOUNTED)) { + (mf->mf_flags & MFF_MOUNTED) && + !(mf->mf_flags & MFF_ON_AUTOFS)) { dlog("Trying unmount in background"); run_task(unmount_node, (opaque_t) mp, free_map_if_success, (opaque_t) mp); @@ -964,7 +990,7 @@ timeout_mp(opaque_t v) /* argument not used?! */ /* * Pick up mounted filesystem */ - mf = mp->am_mnt; + mf = mp->am_al->al_mnt; if (!mf) continue; @@ -1056,7 +1082,7 @@ timeout_mp(opaque_t v) /* argument not used?! */ t = now + 1; dlog("Next mount timeout in %lds", (long) (t - now)); - timeout_mp_id = timeout(t - now, timeout_mp, 0); + timeout_mp_id = timeout(t - now, timeout_mp, NULL); } @@ -1068,5 +1094,5 @@ reschedule_timeout_mp(void) { if (timeout_mp_id) untimeout(timeout_mp_id); - timeout_mp_id = timeout(0, timeout_mp, 0); + timeout_mp_id = timeout(0, timeout_mp, NULL); } diff --git a/contrib/amd/amd/mapc.c b/contrib/amd/amd/mapc.c index d7efdbcfd21..cd4b9b956a0 100644 --- a/contrib/amd/amd/mapc.c +++ b/contrib/amd/amd/mapc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -96,7 +92,7 @@ static struct opt_tab mapc_opt[] = {"regexp", MAPC_RE}, #endif /* HAVE_REGEXEC */ {"sync", MAPC_SYNC}, - {0, 0} + {NULL, 0} }; /* @@ -137,6 +133,7 @@ static const char *get_full_path(const char *map, const char *path, const char * static int mapc_meta_search(mnt_map *, char *, char **, int); static void mapc_sync(mnt_map *); static void mapc_clear(mnt_map *); +static void mapc_clear_kvhash(kv **); /* ROOT MAP */ static int root_init(mnt_map *, char *, time_t *); @@ -198,12 +195,6 @@ extern int ndbm_search(mnt_map *, char *, char *, char **, time_t *); extern int ndbm_mtime(mnt_map *, char *, time_t *); #endif /* HAVE_MAP_NDBM */ -/* EXECUTABLE MAPS */ -#ifdef HAVE_MAP_EXEC -extern int exec_init(mnt_map *, char *, time_t *); -extern int exec_search(mnt_map *, char *, char *, char **, time_t *); -#endif /* HAVE_MAP_EXEC */ - /* FILE MAPS */ #ifdef HAVE_MAP_FILE extern int file_init_or_mtime(mnt_map *, char *, time_t *); @@ -211,6 +202,16 @@ extern int file_reload(mnt_map *, char *, add_fn *); extern int file_search(mnt_map *, char *, char *, char **, time_t *); #endif /* HAVE_MAP_FILE */ +/* EXECUTABLE MAPS */ +#ifdef HAVE_MAP_EXEC +extern int exec_init(mnt_map *, char *, time_t *); +extern int exec_search(mnt_map *, char *, char *, char **, time_t *); +#endif /* HAVE_MAP_EXEC */ + +/* Sun-syntax MAPS */ +#ifdef HAVE_MAP_SUN +/* XXX: fill in */ +#endif /* HAVE_MAP_SUN */ /* note that the choice of MAPC_{INC,ALL} will affect browsable_dirs */ static map_type maptypes[] = @@ -323,6 +324,20 @@ static map_type maptypes[] = MAPC_INC }, #endif /* HAVE_MAP_EXEC */ +#ifdef notyet /* probe function needs to be there or SEGV */ +#ifdef HAVE_MAP_SUN + { + /* XXX: fill in */ + "sun", + NULL, + NULL, + NULL, /* isup function */ + NULL, + NULL, + 0 + }, +#endif /* HAVE_MAP_SUN */ +#endif { "error", error_init, @@ -412,6 +427,44 @@ mapc_add_kv(mnt_map *m, char *key, char *val) dlog("add_kv: %s -> %s", key, val); + if (val != NULL && strchr(val, '\n') != NULL) { + /* + * If the entry value contains multiple lines we need to break + * them up and add them recursively. This is a workaround to + * support Sun style multi-mounts. Amd converts Sun style + * mulit-mounts to type:=auto. The problem is that Sun packs all + * the entries on one line. When Amd does the conversion it puts + * each type:=auto entry on the same line separated by '\n'. + */ + char *entry, *tok; + + /* + * The first line should contain the first entry. The key for + * this entry is the key passed into this function. + */ + if ((tok = strtok(val, "\n")) != NULL) { + mapc_add_kv(m, key, xstrdup(tok)); + } + + /* + * For the rest of the entries we need to tokenize them by '\n' + * and separate the keys from there entries. + */ + while ((tok = strtok(NULL, "\n")) != NULL) { + key = tok; + /* find the entry */ + for (entry = key; *entry && !isspace((unsigned char)*entry); entry++); + if (*entry) { + *entry++ = '\0'; + } + + mapc_add_kv(m, xstrdup(key), xstrdup(entry)); + } + + XFREE(val); + return; + } + #ifdef HAVE_REGEXEC if (MAPC_ISRE(m)) { char pattern[MAXPATHLEN]; @@ -431,7 +484,8 @@ mapc_add_kv(mnt_map *m, char *key, char *val) plog(XLOG_USER, "error compiling RE \"%s\": %s", pattern, errstr); return; } - } + } else + memset(&re, 0, sizeof(re)); #endif /* HAVE_REGEXEC */ h = &m->kvhash[hash]; @@ -443,6 +497,7 @@ mapc_add_kv(mnt_map *m, char *key, char *val) n->val = val; n->next = *h; *h = n; + m->nentries++; } @@ -506,7 +561,7 @@ mapc_find_wildcard(mnt_map *m) int rc = search_map(m, wildcard, &m->wildcard); if (rc != 0) - m->wildcard = 0; + m->wildcard = NULL; } @@ -520,7 +575,7 @@ static int mapc_reload_map(mnt_map *m) { int error, ret = 0; - kv *maphash[NKVHASH], *tmphash[NKVHASH]; + kv *maphash[NKVHASH]; time_t t; error = (*m->mtime) (m, m->map_name, &t); @@ -546,6 +601,7 @@ mapc_reload_map(mnt_map *m) memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); dlog("calling map reload on %s", m->map_name); + m->nentries = 0; error = (*m->reload) (m, m->map_name, mapc_add_kv); if (error) { if (m->reloads == 0) @@ -561,19 +617,19 @@ mapc_reload_map(mnt_map *m) else plog(XLOG_INFO, "reload #%d of map %s succeeded", m->reloads, m->map_name); - memcpy((voidp) tmphash, (voidp) m->kvhash, sizeof(m->kvhash)); - memcpy((voidp) m->kvhash, (voidp) maphash, sizeof(m->kvhash)); - mapc_clear(m); - memcpy((voidp) m->kvhash, (voidp) tmphash, sizeof(m->kvhash)); + mapc_clear_kvhash(maphash); + if (m->wildcard) { + XFREE(m->wildcard); + m->wildcard = NULL; + } m->modify = t; ret = 1; } - m->wildcard = 0; dlog("calling mapc_search for wildcard"); error = mapc_search(m, wildcard, &m->wildcard); if (error) - m->wildcard = 0; + m->wildcard = NULL; return ret; } @@ -582,12 +638,12 @@ mapc_reload_map(mnt_map *m) * Create a new map */ static mnt_map * -mapc_create(char *map, char *opt, const char *type) +mapc_create(char *map, char *opt, const char *type, const char *mntpt) { mnt_map *m = ALLOC(struct mnt_map); map_type *mt; time_t modify = 0; - int alloc = 0; + u_int alloc = 0; cmdoption(opt, mapc_opt, &alloc); @@ -632,6 +688,7 @@ mapc_create(char *map, char *opt, const char *type) /* assert: mt in maptypes */ m->flags = alloc & ~MAPC_CACHE_MASK; + m->nentries = 0; alloc &= MAPC_CACHE_MASK; if (alloc == MAPC_DFLT) @@ -678,12 +735,12 @@ mapc_create(char *map, char *opt, const char *type) m->search = alloc >= MAPC_ALL ? error_search : mt->search; m->mtime = mt->mtime; memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); - m->map_name = strdup(map); + m->map_name = xstrdup(map); m->refc = 1; - m->wildcard = 0; + m->wildcard = NULL; m->reloads = 0; - /* Unfortunately with current code structure, this cannot be initialized here */ - m->cfm = NULL; + /* initialize per-map information (flags, etc.) */ + m->cfm = find_cf_map(mntpt); /* * synchronize cache with reality @@ -695,10 +752,10 @@ mapc_create(char *map, char *opt, const char *type) /* - * Free the cached data in a map + * Free the cached data in a map hash */ static void -mapc_clear(mnt_map *m) +mapc_clear_kvhash(kv **kvhash) { int i; @@ -707,16 +764,25 @@ mapc_clear(mnt_map *m) * along free'ing the data. */ for (i = 0; i < NKVHASH; i++) { - kv *k = m->kvhash[i]; + kv *k = kvhash[i]; while (k) { kv *n = k->next; XFREE(k->key); - if (k->val) - XFREE(k->val); + XFREE(k->val); XFREE(k); k = n; } } +} + + +/* + * Free the cached data in a map + */ +static void +mapc_clear(mnt_map *m) +{ + mapc_clear_kvhash(m->kvhash); /* * Zero the hash slots @@ -726,10 +792,10 @@ mapc_clear(mnt_map *m) /* * Free the wildcard if it exists */ - if (m->wildcard) { - XFREE(m->wildcard); - m->wildcard = 0; - } + XFREE(m->wildcard); + m->wildcard = NULL; + + m->nentries = 0; } @@ -737,7 +803,7 @@ mapc_clear(mnt_map *m) * Find a map, or create one if it does not exist */ mnt_map * -mapc_find(char *map, char *opt, const char *maptype) +mapc_find(char *map, char *opt, const char *maptype, const char *mntpt) { mnt_map *m; @@ -751,7 +817,7 @@ mapc_find(char *map, char *opt, const char *maptype) ITER(m, mnt_map, &map_list_head) if (STREQ(m->map_name, map)) return mapc_dup(m); - m = mapc_create(map, opt, maptype); + m = mapc_create(map, opt, maptype, mntpt); ins_que(&m->hdr, &map_list_head); return m; @@ -788,7 +854,7 @@ static int mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) { int error = 0; - kv *k = 0; + kv *k = NULL; /* * Firewall @@ -839,7 +905,7 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) int retval; /* XXX: this code was recently ported, and must be tested -Erez */ - retval = regexec(&k->re, key, 0, 0, 0); + retval = regexec(&k->re, key, 0, NULL, 0); if (retval == 0) { /* succeeded */ break; } else { /* failed to match, log error */ @@ -863,7 +929,7 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) */ if (k) { if (k->val) - *pval = strdup(k->val); + *pval = xstrdup(k->val); else error = ENOENT; } else if (m->alloc >= MAPC_ALL) { @@ -880,7 +946,7 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) */ error = search_map(m, key, pval); if (!error && m->alloc == MAPC_INC) - mapc_add_kv(m, strdup(key), strdup(*pval)); + mapc_add_kv(m, xstrdup(key), xstrdup(*pval)); } /* @@ -911,11 +977,11 @@ mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) dlog("mapc recurses on %s", wildname); error = mapc_meta_search(m, wildname, pval, MREC_PART); if (error) - *subp = 0; + *subp = '\0'; } if (error > 0 && m->wildcard) { - *pval = strdup(m->wildcard); + *pval = xstrdup(m->wildcard); error = 0; } } @@ -1031,7 +1097,7 @@ root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t * * First make sure we have a root map to talk about... */ if (!root_map) - root_map = mapc_find(ROOT_MAP, "mapdefault", NULL); + root_map = mapc_find(ROOT_MAP, "mapdefault", NULL, NULL); /* * Then add the entry... @@ -1071,7 +1137,7 @@ root_newmap(const char *dir, const char *opts, const char *map, const cf_map_t * else xstrlcpy(str, opts, sizeof(str)); } - mapc_repl_kv(root_map, strdup((char *)dir), strdup(str)); + mapc_repl_kv(root_map, xstrdup(dir), xstrdup(str)); } diff --git a/contrib/amd/amd/mntfs.c b/contrib/amd/amd/mntfs.c index 6021838425c..a26ff8f553f 100644 --- a/contrib/amd/amd/mntfs.c +++ b/contrib/amd/amd/mntfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -52,6 +48,16 @@ qelem mfhead = {&mfhead, &mfhead}; int mntfs_allocated; +am_loc * +dup_loc(am_loc *loc) +{ + loc->al_refc++; + if (loc->al_mnt) { + dup_mntfs(loc->al_mnt); + } + return loc; +} + mntfs * dup_mntfs(mntfs *mf) { @@ -71,24 +77,27 @@ init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto { mf->mf_ops = ops; mf->mf_fsflags = ops->nfs_fs_flags; - mf->mf_fo = mo; - mf->mf_mount = strdup(mp); - mf->mf_info = strdup(info); - mf->mf_auto = strdup(auto_opts); - mf->mf_mopts = strdup(mopts); - mf->mf_remopts = strdup(remopts); + mf->mf_fo = 0; + if (mo) + mf->mf_fo = copy_opts(mo); + + mf->mf_mount = xstrdup(mp); + mf->mf_info = xstrdup(info); + mf->mf_auto = xstrdup(auto_opts); + mf->mf_mopts = xstrdup(mopts); + mf->mf_remopts = xstrdup(remopts); mf->mf_loopdev = NULL; mf->mf_refc = 1; mf->mf_flags = 0; mf->mf_error = -1; mf->mf_cid = 0; - mf->mf_private = 0; - mf->mf_prfree = 0; + mf->mf_private = NULL; + mf->mf_prfree = NULL; if (ops->ffserver) mf->mf_server = (*ops->ffserver) (mf); else - mf->mf_server = 0; + mf->mf_server = NULL; } @@ -138,7 +147,7 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch } dlog("mf->mf_flags = %#x", mf->mf_flags); - mf->mf_fo = mo; + if ((mf->mf_flags & MFF_RESTART) && amd_state < Finishing) { /* * Restart a previously mounted filesystem. @@ -171,7 +180,7 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch if (mf->mf_private && mf->mf_prfree) { mf->mf_prfree(mf->mf_private); - mf->mf_private = 0; + mf->mf_private = NULL; } fs = ops->ffserver ? (*ops->ffserver) (mf) : (fserver *) NULL; @@ -202,26 +211,35 @@ find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char mntfs * new_mntfs(void) { - return alloc_mntfs(&amfs_error_ops, (am_opts *) 0, "//nil//", ".", "", "", ""); + return alloc_mntfs(&amfs_error_ops, (am_opts *) NULL, "//nil//", ".", "", "", ""); +} + +am_loc * +new_loc(void) +{ + am_loc *loc = CALLOC(struct am_loc); + loc->al_fo = 0; + loc->al_mnt = new_mntfs(); + loc->al_refc = 1; + return loc; } static void uninit_mntfs(mntfs *mf) { - if (mf->mf_auto) - XFREE(mf->mf_auto); - if (mf->mf_mopts) - XFREE(mf->mf_mopts); - if (mf->mf_remopts) - XFREE(mf->mf_remopts); - if (mf->mf_info) - XFREE(mf->mf_info); + if (mf->mf_fo) { + free_opts(mf->mf_fo); + XFREE(mf->mf_fo); + } + XFREE(mf->mf_auto); + XFREE(mf->mf_mopts); + XFREE(mf->mf_remopts); + XFREE(mf->mf_info); if (mf->mf_private && mf->mf_prfree) (*mf->mf_prfree) (mf->mf_private); - if (mf->mf_mount) - XFREE(mf->mf_mount); + XFREE(mf->mf_mount); /* * Clean up the file server @@ -255,6 +273,16 @@ discard_mntfs(voidp v) --mntfs_allocated; } +static void +discard_loc(voidp v) +{ + am_loc *loc = v; + if (loc->al_fo) { + free_opts(loc->al_fo); + XFREE(loc->al_fo); + } + XFREE(loc); +} void flush_mntfs(void) @@ -270,6 +298,23 @@ flush_mntfs(void) } } +void +free_loc(opaque_t arg) +{ + am_loc *loc = (am_loc *) arg; + dlog("free_loc %p", loc); + + if (loc->al_refc <= 0) { + plog(XLOG_ERROR, "IGNORING free_loc for 0x%p", loc); + return; + } + + if (loc->al_mnt) + free_mntfs(loc->al_mnt); + if (--loc->al_refc == 0) { + discard_loc(loc); + } +} void free_mntfs(opaque_t arg) @@ -356,7 +401,6 @@ realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *a if (mf->mf_ops != &amfs_error_ops && (mf->mf_flags & MFF_MOUNTED) && !FSRV_ISDOWN(mf->mf_server)) { - mf->mf_fo = mo; return mf; } diff --git a/contrib/amd/amd/nfs_prot_svc.c b/contrib/amd/amd/nfs_prot_svc.c index 0dd6992cf9e..cbde17274ae 100644 --- a/contrib/amd/amd/nfs_prot_svc.c +++ b/contrib/amd/amd/nfs_prot_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -69,6 +65,7 @@ extern nfsstatfsres *nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *); /* global variables */ SVCXPRT *current_transp; +dispatcher_t nfs_dispatcher = nfs_program_2; /* typedefs */ typedef char *(*nfssvcproc_t)(voidp, struct svc_req *); @@ -299,3 +296,193 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp) going_down(1); } } + +void +nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + am_GETATTR3args am_nfs3_getattr_3_arg; + am_SETATTR3args am_nfs3_setattr_3_arg; + am_LOOKUP3args am_nfs3_lookup_3_arg; + am_ACCESS3args am_nfs3_access_3_arg; + am_READLINK3args am_nfs3_readlink_3_arg; + am_READ3args am_nfs3_read_3_arg; + am_WRITE3args am_nfs3_write_3_arg; + am_CREATE3args am_nfs3_create_3_arg; + am_MKDIR3args am_nfs3_mkdir_3_arg; + am_SYMLINK3args am_nfs3_symlink_3_arg; + am_MKNOD3args am_nfs3_mknod_3_arg; + am_REMOVE3args am_nfs3_remove_3_arg; + am_RMDIR3args am_nfs3_rmdir_3_arg; + am_RENAME3args am_nfs3_rename_3_arg; + am_LINK3args am_nfs3_link_3_arg; + am_READDIR3args am_nfs3_readdir_3_arg; + am_READDIRPLUS3args am_nfs3_readdirplus_3_arg; + am_FSSTAT3args am_nfs3_fsstat_3_arg; + am_FSINFO3args am_nfs3_fsinfo_3_arg; + am_PATHCONF3args am_nfs3_pathconf_3_arg; + am_COMMIT3args am_nfs3_commit_3_arg; + } argument; + char *result; + xdrproc_t _xdr_argument, _xdr_result; + nfssvcproc_t local; + + switch (rqstp->rq_proc) { + case AM_NFS3_NULL: + _xdr_argument = (xdrproc_t) xdr_void; + _xdr_result = (xdrproc_t) xdr_void; + local = (nfssvcproc_t) am_nfs3_null_3_svc; + break; + + case AM_NFS3_GETATTR: + _xdr_argument = (xdrproc_t) xdr_am_GETATTR3args; + _xdr_result = (xdrproc_t) xdr_am_GETATTR3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_getattr_3_svc; + break; + + case AM_NFS3_SETATTR: + _xdr_argument = (xdrproc_t) xdr_am_SETATTR3args; + _xdr_result = (xdrproc_t) xdr_am_SETATTR3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_setattr_3_svc; + break; + + case AM_NFS3_LOOKUP: + _xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args; + _xdr_result = (xdrproc_t) xdr_am_LOOKUP3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc; + break; + + case AM_NFS3_ACCESS: + _xdr_argument = (xdrproc_t) xdr_am_ACCESS3args; + _xdr_result = (xdrproc_t) xdr_am_ACCESS3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_access_3_svc; + break; + + case AM_NFS3_READLINK: + _xdr_argument = (xdrproc_t) xdr_am_READLINK3args; + _xdr_result = (xdrproc_t) xdr_am_READLINK3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readlink_3_svc; + break; + + case AM_NFS3_READ: + _xdr_argument = (xdrproc_t) xdr_am_READ3args; + _xdr_result = (xdrproc_t) xdr_am_READ3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_read_3_svc; + break; + + case AM_NFS3_WRITE: + _xdr_argument = (xdrproc_t) xdr_am_WRITE3args; + _xdr_result = (xdrproc_t) xdr_am_WRITE3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_write_3_svc; + break; + + case AM_NFS3_CREATE: + _xdr_argument = (xdrproc_t) xdr_am_CREATE3args; + _xdr_result = (xdrproc_t) xdr_am_CREATE3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_create_3_svc; + break; + + case AM_NFS3_MKDIR: + _xdr_argument = (xdrproc_t) xdr_am_MKDIR3args; + _xdr_result = (xdrproc_t) xdr_am_MKDIR3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mkdir_3_svc; + break; + + case AM_NFS3_SYMLINK: + _xdr_argument = (xdrproc_t) xdr_am_SYMLINK3args; + _xdr_result = (xdrproc_t) xdr_am_SYMLINK3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_symlink_3_svc; + break; + + case AM_NFS3_MKNOD: + _xdr_argument = (xdrproc_t) xdr_am_MKNOD3args; + _xdr_result = (xdrproc_t) xdr_am_MKNOD3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_mknod_3_svc; + break; + + case AM_NFS3_REMOVE: + _xdr_argument = (xdrproc_t) xdr_am_REMOVE3args; + _xdr_result = (xdrproc_t) xdr_am_REMOVE3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_remove_3_svc; + break; + + case AM_NFS3_RMDIR: + _xdr_argument = (xdrproc_t) xdr_am_RMDIR3args; + _xdr_result = (xdrproc_t) xdr_am_RMDIR3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rmdir_3_svc; + break; + + case AM_NFS3_RENAME: + _xdr_argument = (xdrproc_t) xdr_am_RENAME3args; + _xdr_result = (xdrproc_t) xdr_am_RENAME3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_rename_3_svc; + break; + + case AM_NFS3_LINK: + _xdr_argument = (xdrproc_t) xdr_am_LINK3args; + _xdr_result = (xdrproc_t) xdr_am_LINK3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_link_3_svc; + break; + + case AM_NFS3_READDIR: + _xdr_argument = (xdrproc_t) xdr_am_READDIR3args; + _xdr_result = (xdrproc_t) xdr_am_READDIR3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdir_3_svc; + break; + + case AM_NFS3_READDIRPLUS: + _xdr_argument = (xdrproc_t) xdr_am_READDIRPLUS3args; + _xdr_result = (xdrproc_t) xdr_am_READDIRPLUS3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_readdirplus_3_svc; + break; + + case AM_NFS3_FSSTAT: + _xdr_argument = (xdrproc_t) xdr_am_FSSTAT3args; + _xdr_result = (xdrproc_t) xdr_am_FSSTAT3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsstat_3_svc; + break; + + case AM_NFS3_FSINFO: + _xdr_argument = (xdrproc_t) xdr_am_FSINFO3args; + _xdr_result = (xdrproc_t) xdr_am_FSINFO3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_fsinfo_3_svc; + break; + + case AM_NFS3_PATHCONF: + _xdr_argument = (xdrproc_t) xdr_am_PATHCONF3args; + _xdr_result = (xdrproc_t) xdr_am_PATHCONF3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_pathconf_3_svc; + break; + + case AM_NFS3_COMMIT: + _xdr_argument = (xdrproc_t) xdr_am_COMMIT3args; + _xdr_result = (xdrproc_t) xdr_am_COMMIT3res; + local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_commit_3_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + + memset ((char *)&argument, 0, sizeof (argument)); + + if (!svc_getargs(transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + plog(XLOG_ERROR, + "NFS xdr decode failed for %d %d %d", + (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc); + svcerr_decode(transp); + return; + } + + result = (*local) (&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { + svcerr_systemerr (transp); + } + + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_3"); + going_down(1); + } + return; +} diff --git a/contrib/amd/amd/nfs_start.c b/contrib/amd/amd/nfs_start.c index f6aba94e2b6..b6c544ddf17 100644 --- a/contrib/amd/amd/nfs_start.c +++ b/contrib/amd/amd/nfs_start.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -65,12 +61,11 @@ u_short nfs_port = 0; static void checkup(void) { - static int max_fd = 0; - static char *max_mem = 0; - + static char *max_mem = NULL; int next_fd = dup(0); caddr_t next_mem = sbrk(0); + close(next_fd); if (max_fd < next_fd) { @@ -135,8 +130,8 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp) /* * Wait for input */ - nsel = select(fds, fdp, (fd_set *) 0, (fd_set *) 0, - tvp->tv_sec ? tvp : (struct timeval *) 0); + nsel = select(fds, fdp, (fd_set *) NULL, (fd_set *) NULL, + tvp->tv_sec ? tvp : (struct timeval *) NULL); } #ifdef HAVE_SIGACTION @@ -171,7 +166,7 @@ rpc_pending_now(void) FD_SET(fwd_sock, &readfds); tvv.tv_sec = tvv.tv_usec = 0; - nsel = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &tvv); + nsel = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tvv); if (nsel < 1) return (0); if (FD_ISSET(fwd_sock, &readfds)) @@ -365,15 +360,16 @@ mount_automounter(int ppid) * already created the service during restart_automounter_nodes(). */ if (nfs_port == 0) { - ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); + ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_dispatcher, + get_nfs_dispatcher_version(nfs_dispatcher)); if (ret != 0) return ret; } xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)", am_get_hostname(), (long) am_mypid, nfs_port); - /* security: if user sets -D amq, don't even create listening socket */ - if (!amuDebug(D_AMQ)) { + /* security: if user sets -D noamq, don't even create listening socket */ + if (amuDebug(D_AMQ)) { ret = create_amq_service(&udp_soAMQ, &udp_amqp, &udp_amqncp, @@ -416,25 +412,33 @@ mount_automounter(int ppid) return 0; } - if (!amuDebug(D_AMQ)) { + if (amuDebug(D_AMQ)) { /* * Complete registration of amq (first TCP service then UDP) */ - unregister_amq(); + int tcp_ok = 0, udp_ok = 0; - ret = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION, - amq_program_1, IPPROTO_TCP, tcp_amqncp); - if (ret != 1) { - plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, tcp)", get_amd_program_number()); + unregister_amq(); /* unregister leftover Amd, if any, just in case */ + + tcp_ok = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION, + amq_program_1, IPPROTO_TCP, tcp_amqncp); + if (!tcp_ok) + plog(XLOG_FATAL, + "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)", + get_amd_program_number()); + + udp_ok = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION, + amq_program_1, IPPROTO_UDP, udp_amqncp); + if (!udp_ok) + plog(XLOG_FATAL, + "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)", + get_amd_program_number()); + + /* return error only if both failed */ + if (!tcp_ok && !udp_ok) { + amd_state = Done; return 3; } - - ret = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION, - amq_program_1, IPPROTO_UDP, udp_amqncp); - if (ret != 1) { - plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM=%d, AMQ_VERSION, udp)", get_amd_program_number()); - return 4; - } } /* diff --git a/contrib/amd/amd/nfs_subr.c b/contrib/amd/amd/nfs_subr.c index 80d3ca8e311..734c69827a3 100644 --- a/contrib/amd/amd/nfs_subr.c +++ b/contrib/amd/amd/nfs_subr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -78,6 +74,17 @@ struct am_fh { } u; }; +struct am_fh3 { + u_int fhh_gen; /* generation number */ + union { + struct { + int fhh_type; /* old or new am_fh */ + pid_t fhh_pid; /* process id */ + int fhh_id; /* map id */ + } s; + char fhh_path[AM_FHSIZE3-sizeof(u_int)]; /* path to am_node */ + } u; +}; /* forward declarations */ /* converting am-filehandles to mount-points */ @@ -96,10 +103,10 @@ do_readlink(am_node *mp, int *error_return) * otherwise if a link exists use that, * otherwise use the mount point. */ - if (mp->am_mnt->mf_ops->readlink) { + if (mp->am_al->al_mnt->mf_ops->readlink) { int retry = 0; - mp = (*mp->am_mnt->mf_ops->readlink) (mp, &retry); - if (mp == 0) { + mp = (*mp->am_al->al_mnt->mf_ops->readlink) (mp, &retry); + if (mp == NULL) { *error_return = retry; return 0; } @@ -109,7 +116,7 @@ do_readlink(am_node *mp, int *error_return) if (mp->am_link) { ln = mp->am_link; } else { - ln = mp->am_mnt->mf_mount; + ln = mp->am_al->al_mnt->mf_mount; } return ln; @@ -130,14 +137,14 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) { static nfsattrstat res; am_node *mp; - int retry; + int retry = 0; time_t now = clocktime(NULL); if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "getattr:"); mp = fh_to_mp3(argp, &retry, VLOOK_CREATE); - if (mp == 0) { + if (mp == NULL) { if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "\tretry=%d", retry); @@ -209,7 +216,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid); mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_CREATE); - if (mp == 0) { + if (mp == NULL) { if (retry < 0) { amd_stats.d_drops++; return 0; @@ -220,9 +227,9 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) am_node *ap; if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, argp->da_name); - ap = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE); + ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, argp->da_name, &error, VLOOK_CREATE); if (ap && error < 0) - ap = mp->am_mnt->mf_ops->mount_child(ap, &error); + ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error); if (ap == 0) { if (error < 0) { amd_stats.d_drops++; @@ -285,7 +292,7 @@ nfs_quick_reply(am_node *mp, int error) * Free up transp. It's only used for one reply. */ XFREE(mp->am_transp); - dlog("Quick reply sent for %s", mp->am_mnt->mf_mount); + dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount); } } @@ -301,7 +308,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) plog(XLOG_DEBUG, "readlink:"); mp = fh_to_mp3(argp, &retry, VLOOK_CREATE); - if (mp == 0) { + if (mp == NULL) { readlink_retry: if (retry < 0) { amd_stats.d_drops++; @@ -379,7 +386,7 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp) int retry; am_node *mp = fh_to_mp3(&argp->da_fhandle, &retry, VLOOK_DELETE); - if (mp == 0) { + if (mp == NULL) { if (retry < 0) { amd_stats.d_drops++; return 0; @@ -396,8 +403,8 @@ unlink_or_rmdir(nfsdiropargs *argp, struct svc_req *rqstp, int unlinkp) if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, argp->da_name); - mp = mp->am_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE); - if (mp == 0) { + mp = mp->am_al->al_mnt->mf_ops->lookup_child(mp, argp->da_name, &retry, VLOOK_DELETE); + if (mp == NULL) { /* * Ignore retries... */ @@ -510,7 +517,7 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp) plog(XLOG_DEBUG, "readdir:"); mp = fh_to_mp3(&argp->rda_fhandle, &retry, VLOOK_CREATE); - if (mp == 0) { + if (mp == NULL) { if (retry < 0) { amd_stats.d_drops++; return 0; @@ -519,7 +526,7 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp) } else { if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "\treaddir(%s)", mp->am_path); - res.rdr_status = nfs_error((*mp->am_mnt->mf_ops->readdir) + res.rdr_status = nfs_error((*mp->am_al->al_mnt->mf_ops->readdir) (mp, argp->rda_cookie, &res.rdr_u.rdr_reply_u, e_res, argp->rda_count)); mp->am_stats.s_readdir++; @@ -541,7 +548,7 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) plog(XLOG_DEBUG, "statfs:"); mp = fh_to_mp3(argp, &retry, VLOOK_CREATE); - if (mp == 0) { + if (mp == NULL) { if (retry < 0) { amd_stats.d_drops++; return 0; @@ -562,8 +569,8 @@ nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) /* check if map is browsable and show_statfs_entries=yes */ if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) && - mp->am_mnt && mp->am_mnt->mf_mopts) { - mnt.mnt_opts = mp->am_mnt->mf_mopts; + mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { + mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; if (amu_hasmntopt(&mnt, "browsable")) { count_map_entries(mp, &fp->sfrok_blocks, @@ -599,7 +606,7 @@ count_map_entries(const am_node *mp, u_int *out_blocks, u_int *out_bfree, u_int blocks = bfree = bavail = 0; if (!mp) goto out; - mf = mp->am_mnt; + mf = mp->am_al->al_mnt; if (!mf) goto out; mmp = (mnt_map *) mf->mf_private; @@ -625,58 +632,18 @@ out: *out_bavail = bavail; } - -/* - * Convert from file handle to automount node. - */ static am_node * -fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) +validate_ap(am_node *node, int *rp, u_int fhh_gen) { - struct am_fh *fp = (struct am_fh *) fhp; - am_node *ap = 0; - - if (fp->u.s.fhh_type != 0) { - /* New filehandle type */ - int len = sizeof(*fhp) - sizeof(fp->fhh_gen); - char *path = xmalloc(len+1); - /* - * Because fhp is treated as a filehandle we use memcpy - * instead of xstrlcpy. - */ - memcpy(path, (char *) fp->u.fhh_path, len); - path[len] = '\0'; - /* dlog("fh_to_mp3: new filehandle: %s", path); */ - - ap = path_to_exported_ap(path); - XFREE(path); - } else { - /* dlog("fh_to_mp3: old filehandle: %d", fp->u.s.fhh_id); */ - /* - * Check process id matches - * If it doesn't then it is probably - * from an old kernel-cached filehandle - * which is now out of date. - */ - if (fp->u.s.fhh_pid != get_server_pid()) { - dlog("fh_to_mp3: wrong pid %ld != my pid %ld", - (long) fp->u.s.fhh_pid, get_server_pid()); - goto drop; - } - - /* - * Get hold of the supposed mount node - */ - ap = get_exported_ap(fp->u.s.fhh_id); - } - + am_node *ap = node; /* * Check the generation number in the node * matches the one from the kernel. If not * then the old node has been timed out and * a new one allocated. */ - if (ap != NULL && ap->am_gen != fp->fhh_gen) - ap = 0; + if (node != NULL && node->am_gen != fhh_gen) + ap = NULL; /* * If it doesn't exists then drop the request @@ -690,12 +657,12 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) * for it. This implements the replicated filesystem * retries. */ - if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) { + if (ap->am_al->al_mnt && FSRV_ISDOWN(ap->am_al->al_mnt->mf_server) && ap->am_parent) { int error; am_node *orig_ap = ap; - dlog("fh_to_mp3: %s (%s) is hung: lookup alternative file server", - orig_ap->am_path, orig_ap->am_mnt->mf_info); + dlog("%s: %s (%s) is hung: lookup alternative file server", __func__, + orig_ap->am_path, orig_ap->am_al->al_mnt->mf_info); /* * Update modify time of parent node. @@ -712,11 +679,11 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) * to the caller. */ if (vop == VLOOK_CREATE) { - ap = orig_ap->am_parent->am_mnt->mf_ops->lookup_child(orig_ap->am_parent, orig_ap->am_name, &error, vop); + ap = orig_ap->am_parent->am_al->al_mnt->mf_ops->lookup_child(orig_ap->am_parent, orig_ap->am_name, &error, vop); if (ap && error < 0) - ap = orig_ap->am_parent->am_mnt->mf_ops->mount_child(ap, &error); + ap = orig_ap->am_parent->am_al->al_mnt->mf_ops->mount_child(ap, &error); } else { - ap = 0; + ap = NULL; error = ESTALE; } if (ap == 0) { @@ -735,13 +702,13 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) new_ttl(orig_ap); } -#endif +#endif /* 0 */ /* * Disallow references to objects being unmounted, unless * they are automount points. */ - if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) && + if (ap->am_al->al_mnt && (ap->am_al->al_mnt->mf_flags & MFF_UNMOUNTING) && !(ap->am_flags & AMF_ROOT)) { if (amd_state == Finishing) *rp = ENOENT; @@ -752,7 +719,7 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) new_ttl(ap); drop: - if (!ap || !ap->am_mnt) { + if (!ap || !ap->am_al->al_mnt) { /* * If we are shutting down then it is likely * that this node has disappeared because of @@ -764,14 +731,60 @@ drop: */ if (amd_state == Finishing) *rp = ENOENT; - else + else { *rp = ESTALE; - amd_stats.d_stale++; + amd_stats.d_stale++; + } } return ap; } +/* + * Convert from file handle to automount node. + */ +static am_node * +fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) +{ + struct am_fh *fp = (struct am_fh *) fhp; + am_node *ap = NULL; + + if (fp->u.s.fhh_type != 0) { + /* New filehandle type */ + int len = sizeof(*fhp) - sizeof(fp->fhh_gen); + char *path = xmalloc(len+1); + /* + * Because fhp is treated as a filehandle we use memcpy + * instead of xstrlcpy. + */ + memcpy(path, (char *) fp->u.fhh_path, len); + path[len] = '\0'; + dlog("%s: new filehandle: %s", __func__, path); + + ap = path_to_exported_ap(path); + XFREE(path); + } else { + dlog("%s: old filehandle: %d", __func__, fp->u.s.fhh_id); + /* + * Check process id matches + * If it doesn't then it is probably + * from an old kernel-cached filehandle + * which is now out of date. + */ + if (fp->u.s.fhh_pid != get_server_pid()) { + dlog("%s: wrong pid %ld != my pid %ld", __func__, + (long) fp->u.s.fhh_pid, get_server_pid()); + goto done; + } + + /* + * Get hold of the supposed mount node + */ + ap = get_exported_ap(fp->u.s.fhh_id); + } +done: + return validate_ap(ap, rp, fp->fhh_gen); +} static am_node * fh_to_mp(am_nfs_fh *fhp) @@ -781,6 +794,56 @@ fh_to_mp(am_nfs_fh *fhp) return fh_to_mp3(fhp, &dummy, VLOOK_CREATE); } +static am_node * +fh3_to_mp3(am_nfs_fh3 *fhp, int *rp, int vop) +{ + struct am_fh3 *fp = (struct am_fh3 *) fhp->am_fh3_data; + am_node *ap = NULL; + + if (fp->u.s.fhh_type != 0) { + /* New filehandle type */ + int len = sizeof(*fp) - sizeof(fp->fhh_gen); + char *path = xmalloc(len+1); + /* + * Because fhp is treated as a filehandle we use memcpy + * instead of xstrlcpy. + */ + memcpy(path, (char *) fp->u.fhh_path, len); + path[len] = '\0'; + dlog("%s: new filehandle: %s", __func__, path); + + ap = path_to_exported_ap(path); + XFREE(path); + } else { + dlog("%s: old filehandle: %d", __func__, fp->u.s.fhh_id); + /* + * Check process id matches + * If it doesn't then it is probably + * from an old kernel-cached filehandle + * which is now out of date. + */ + if (fp->u.s.fhh_pid != get_server_pid()) { + dlog("%s: wrong pid %ld != my pid %ld", __func__, + (long) fp->u.s.fhh_pid, get_server_pid()); + goto done; + } + + /* + * Get hold of the supposed mount node + */ + ap = get_exported_ap(fp->u.s.fhh_id); + } +done: + return validate_ap(ap, rp, fp->fhh_gen); +} + +static am_node * +fh3_to_mp(am_nfs_fh3 *fhp) +{ + int dummy; + + return fh3_to_mp3(fhp, &dummy, VLOOK_CREATE); +} /* * Convert from automount node to file handle. @@ -826,3 +889,975 @@ mp_to_fh(am_node *mp, am_nfs_fh *fhp) /* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */ } } +void +mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp) +{ + u_int pathlen; + struct am_fh3 *fp = (struct am_fh3 *) fhp->am_fh3_data; + + memset((char *) fhp, 0, sizeof(am_nfs_fh3)); + fhp->am_fh3_length = AM_FHSIZE3; + + /* Store the generation number */ + fp->fhh_gen = mp->am_gen; + + pathlen = strlen(mp->am_path); + if (pathlen <= sizeof(*fp) - sizeof(fp->fhh_gen)) { + /* dlog("mp_to_fh: new filehandle: %s", mp->am_path); */ + + /* + * Because fhp is treated as a filehandle we use memcpy instead of + * xstrlcpy. + */ + memcpy(fp->u.fhh_path, mp->am_path, pathlen); /* making a filehandle */ + } else { + /* + * Take the process id + */ + fp->u.s.fhh_pid = get_server_pid(); + + /* + * ... the map number + */ + fp->u.s.fhh_id = mp->am_mapno; + + /* + * ... and the generation number (previously stored) + * to make a "unique" triple that will never + * be reallocated except across reboots (which doesn't matter) + * or if we are unlucky enough to be given the same + * pid as a previous amd (very unlikely). + */ + /* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */ + } +} + +#ifdef HAVE_FS_NFS3 +static am_ftype3 ftype_to_ftype3(nfsftype ftype) +{ + if (ftype == NFFIFO) + return AM_NF3FIFO; + else + return ftype; +} + +static void nfstime_to_am_nfstime3(nfstime *time, am_nfstime3 *time3) +{ + time3->seconds = time->seconds; + time3->nseconds = time->useconds * 1000; +} + +static void rdev_to_am_specdata3(u_int rdev, am_specdata3 *rdev3) +{ + /* No device node here */ + rdev3->specdata1 = (u_int) -1; + rdev3->specdata2 = (u_int) -1; +} + +static void fattr_to_fattr3(nfsfattr *fattr, am_fattr3 *fattr3) +{ + fattr3->type = ftype_to_ftype3(fattr->na_type); + fattr3->mode = (am_mode3) fattr->na_mode; + fattr3->nlink = fattr->na_nlink; + fattr3->uid = (am_uid3) fattr->na_uid; + fattr3->gid = (am_uid3) fattr->na_gid; + fattr3->size = (am_size3) fattr->na_size; + fattr3->used = (am_size3) fattr->na_size; + rdev_to_am_specdata3(fattr->na_rdev, &fattr3->rdev); + fattr3->fsid = (uint64) fattr->na_fsid; + fattr3->fileid = (uint64) fattr->na_fileid; + nfstime_to_am_nfstime3(&fattr->na_atime, &fattr3->atime); + nfstime_to_am_nfstime3(&fattr->na_mtime, &fattr3->mtime); + nfstime_to_am_nfstime3(&fattr->na_ctime, &fattr3->ctime); +} + +static void fattr_to_wcc_attr(nfsfattr *fattr, am_wcc_attr *wcc_attr) +{ + wcc_attr->size = (am_size3) fattr->na_size; + nfstime_to_am_nfstime3(&fattr->na_mtime, &wcc_attr->mtime); + nfstime_to_am_nfstime3(&fattr->na_ctime, &wcc_attr->ctime); +} + +static am_nfsstat3 return_estale_or_rofs(am_nfs_fh3 *fh, + am_pre_op_attr *pre_op, + am_post_op_attr *post_op) +{ + am_node *mp; + + mp = fh3_to_mp(fh); + if (!mp) { + pre_op->attributes_follow = 0; + post_op->attributes_follow = 0; + return nfs_error(ESTALE); + } else { + am_fattr3 *fattr3 = &post_op->am_post_op_attr_u.attributes; + am_wcc_attr *wcc_attr = &pre_op->am_pre_op_attr_u.attributes; + nfsfattr *fattr = &mp->am_fattr; + pre_op->attributes_follow = 1; + fattr_to_wcc_attr(fattr, wcc_attr); + post_op->attributes_follow = 1; + fattr_to_fattr3(fattr, fattr3); + return nfs_error(EROFS); + } +} + +static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp, + am_wcc_data *wcc_data, int unlinkp) +{ + static am_nfsstat3 res; + am_nfs_fh3 *dir = &argp->dir; + am_filename3 name = argp->name; + am_pre_op_attr *pre_op_dir = &wcc_data->before; + am_post_op_attr *post_op_dir = &wcc_data->after; + nfsfattr *fattr; + am_wcc_attr *wcc_attr; + am_node *mp, *ap; + int retry; + + post_op_dir->attributes_follow = 0; + + mp = fh3_to_mp3(dir, &retry, VLOOK_DELETE); + if (!mp) { + pre_op_dir->attributes_follow = 0; + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + res = nfs_error(retry); + goto out; + } + + pre_op_dir->attributes_follow = 1; + fattr = &mp->am_fattr; + wcc_attr = &pre_op_dir->am_pre_op_attr_u.attributes; + fattr_to_wcc_attr(fattr, wcc_attr); + + if (mp->am_fattr.na_type != NFDIR) { + res = nfs_error(ENOTDIR); + goto out; + } + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\tremove(%s, %s)", mp->am_path, name); + + ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, name, &retry, VLOOK_DELETE); + if (!ap) { + /* + * Ignore retries... + */ + if (retry < 0) + retry = 0; + /* + * Usual NFS workaround... + */ + else if (retry == ENOENT) + retry = 0; + res = nfs_error(retry); + } else { + forcibly_timeout_mp(mp); + res = AM_NFS3_OK; + } + +out: + return res; +} + +voidp +am_nfs3_null_3_svc(voidp argp, struct svc_req *rqstp) +{ + static char * result; + + return (voidp) &result; +} + +am_GETATTR3res * +am_nfs3_getattr_3_svc(am_GETATTR3args *argp, struct svc_req *rqstp) +{ + static am_GETATTR3res result; + am_nfs_fh3 *fh = (am_nfs_fh3 *) &argp->object; + am_fattr3 *fattr3; + nfsfattr *fattr; + am_node *mp; + int retry = 0; + time_t now = clocktime(NULL); + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "getattr_3:"); + + mp = fh3_to_mp3(fh, &retry, VLOOK_CREATE); + if (!mp) { + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\tretry=%d", retry); + + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + result.status = nfs_error(retry); + return &result; + } + + fattr = &mp->am_fattr; + fattr3 = (am_fattr3 *) &result.res_u.ok.obj_attributes; + fattr_to_fattr3(fattr, fattr3); + + result.status = AM_NFS3_OK; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\tstat(%s), size = %lu, mtime=%d.%d", + mp->am_path, + (u_long) fattr3->size, + (u_int) fattr3->mtime.seconds, + (u_int) fattr3->mtime.nseconds); + + /* Delay unmount of what was looked up */ + if (mp->am_timeo_w < 4 * gopt.am_timeo_w) + mp->am_timeo_w += gopt.am_timeo_w; + mp->am_ttl = now + mp->am_timeo_w; + + mp->am_stats.s_getattr++; + + return &result; +} + +am_SETATTR3res * +am_nfs3_setattr_3_svc(am_SETATTR3args *argp, struct svc_req *rqstp) +{ + static am_SETATTR3res result; + am_nfs_fh3 *fh = (am_nfs_fh3 *) &argp->object; + am_pre_op_attr *pre_op_obj = &result.res_u.fail.obj_wcc.before; + am_post_op_attr *post_op_obj = &result.res_u.fail.obj_wcc.after; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "setattr_3:"); + + result.status = return_estale_or_rofs(fh, pre_op_obj, post_op_obj); + + return &result; +} + +am_LOOKUP3res * +am_nfs3_lookup_3_svc(am_LOOKUP3args *argp, struct svc_req *rqstp) +{ + static am_LOOKUP3res result; + am_nfs_fh3 *dir = &argp->what.dir; + am_post_op_attr *post_op_dir; + am_post_op_attr *post_op_obj; + am_node *mp; + int retry; + uid_t uid; + gid_t gid; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "lookup_3:"); + + /* finally, find the effective uid/gid from RPC request */ + if (getcreds(rqstp, &uid, &gid, nfsxprt) < 0) + plog(XLOG_ERROR, "cannot get uid/gid from RPC credentials"); + xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) uid); + xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) gid); + + mp = fh3_to_mp3(dir, &retry, VLOOK_CREATE); + if (!mp) { + post_op_dir = &result.res_u.fail.dir_attributes; + post_op_dir->attributes_follow = 0; + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + result.status = nfs_error(retry); + } else { + post_op_dir = &result.res_u.ok.dir_attributes; + post_op_obj = &result.res_u.ok.obj_attributes; + am_filename3 name; + am_fattr3 *fattr3; + nfsfattr *fattr; + am_node *ap; + int error; + + /* dir attributes */ + post_op_dir->attributes_follow = 1; + fattr = &mp->am_fattr; + fattr3 = &post_op_dir->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + post_op_obj->attributes_follow = 0; + + name = argp->what.name; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\tlookup_3(%s, %s)", mp->am_path, name); + + ap = mp->am_al->al_mnt->mf_ops->lookup_child(mp, name, &error, VLOOK_CREATE); + if (ap && error < 0) + ap = mp->am_al->al_mnt->mf_ops->mount_child(ap, &error); + if (ap == 0) { + if (error < 0) { + amd_stats.d_drops++; + return 0; + } + result.status = nfs_error(error); + } else { + /* + * XXX: EXPERIMENTAL! Delay unmount of what was looked up. This + * should reduce the chance for race condition between unmounting an + * entry synchronously, and re-mounting it asynchronously. + */ + if (ap->am_ttl < mp->am_ttl) + ap->am_ttl = mp->am_ttl; + + mp_to_fh3(ap, &result.res_u.ok.object); + + /* mount attributes */ + post_op_obj->attributes_follow = 1; + fattr = &ap->am_fattr; + fattr3 = &post_op_obj->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + result.status = AM_NFS3_OK; + } + mp->am_stats.s_lookup++; + } + return &result; +} + +am_ACCESS3res * +am_nfs3_access_3_svc(am_ACCESS3args *argp, struct svc_req *rqstp) +{ + static am_ACCESS3res result; + + am_nfs_fh3 *obj = &argp->object; + u_int accessbits = argp->access; + u_int accessmask = AM_ACCESS3_LOOKUP|AM_ACCESS3_READ; + am_post_op_attr *post_op_obj; + am_node *mp; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "access_3:"); + + mp = fh3_to_mp(obj); + if (!mp) { + post_op_obj = &result.res_u.fail.obj_attributes; + post_op_obj->attributes_follow = 0; + result.status = nfs_error(ENOENT); + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "access_3: ENOENT"); + } else { + nfsfattr *fattr = &mp->am_fattr; + am_fattr3 *fattr3; + post_op_obj = &result.res_u.ok.obj_attributes; + fattr3 = &post_op_obj->am_post_op_attr_u.attributes; + post_op_obj->attributes_follow = 1; + fattr_to_fattr3(fattr, fattr3); + + result.res_u.ok.access = accessbits & accessmask; + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "access_3: b=%x m=%x", accessbits, accessmask); + + result.status = AM_NFS3_OK; + } + + return &result; +} + +am_READLINK3res * +am_nfs3_readlink_3_svc(am_READLINK3args *argp, struct svc_req *rqstp) +{ + static am_READLINK3res result; + + am_nfs_fh3 *symlink = (am_nfs_fh3 *) &argp->symlink; + am_post_op_attr *post_op_sym; + am_node *mp; + int retry = 0; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "readlink_3:"); + + mp = fh3_to_mp3(symlink, &retry, VLOOK_CREATE); + if (!mp) { + readlink_retry: + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + post_op_sym = &result.res_u.fail.symlink_attributes; + post_op_sym->attributes_follow = 0; + result.status = nfs_error(retry); + } else { + nfsfattr *fattr; + am_fattr3 *fattr3; + char *ln; + + ln = do_readlink(mp, &retry); + if (!ln) + goto readlink_retry; + + if (amuDebug(D_TRACE) && ln) + plog(XLOG_DEBUG, "\treadlink_3(%s) = %s", mp->am_path, ln); + + result.res_u.ok.data = ln; + + post_op_sym = &result.res_u.ok.symlink_attributes; + post_op_sym->attributes_follow = 1; + fattr = &mp->am_fattr; + fattr3 = &post_op_sym->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + mp->am_stats.s_readlink++; + result.status = AM_NFS3_OK; + } + + return &result; +} + +am_READ3res * +am_nfs3_read_3_svc(am_READ3args *argp, struct svc_req *rqstp) +{ + static am_READ3res result; + + am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file; + am_post_op_attr *post_op_file; + am_node *mp; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "read_3:"); + + post_op_file = &result.res_u.fail.file_attributes; + result.status = nfs_error(EACCES); + + mp = fh3_to_mp(file); + if (!mp) + post_op_file->attributes_follow = 0; + else { + nfsfattr *fattr = &mp->am_fattr; + am_fattr3 *fattr3 = &post_op_file->am_post_op_attr_u.attributes; + post_op_file->attributes_follow = 1; + fattr_to_fattr3(fattr, fattr3); + } + + return &result; +} + +am_WRITE3res * +am_nfs3_write_3_svc(am_WRITE3args *argp, struct svc_req *rqstp) +{ + static am_WRITE3res result; + + am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file; + am_pre_op_attr *pre_op_file = &result.res_u.fail.file_wcc.before; + am_post_op_attr *post_op_file = &result.res_u.fail.file_wcc.after; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "write_3:"); + + result.status = return_estale_or_rofs(file, pre_op_file, post_op_file); + + return &result; +} + +am_CREATE3res * +am_nfs3_create_3_svc(am_CREATE3args *argp, struct svc_req *rqstp) +{ + static am_CREATE3res result; + + am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir; + am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before; + am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "create_3:"); + + result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir); + + return &result; +} + +am_MKDIR3res * +am_nfs3_mkdir_3_svc(am_MKDIR3args *argp, struct svc_req *rqstp) +{ + static am_MKDIR3res result; + + am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir; + am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before; + am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "mkdir_3:"); + + result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir); + + return &result; +} + +am_SYMLINK3res * +am_nfs3_symlink_3_svc(am_SYMLINK3args *argp, struct svc_req *rqstp) +{ + static am_SYMLINK3res result; + + am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir; + am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before; + am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "symlink_3:"); + + result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir); + + return &result; +} + +am_MKNOD3res * +am_nfs3_mknod_3_svc(am_MKNOD3args *argp, struct svc_req *rqstp) +{ + static am_MKNOD3res result; + + am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->where.dir; + am_pre_op_attr *pre_op_dir = &result.res_u.fail.dir_wcc.before; + am_post_op_attr *post_op_dir = &result.res_u.fail.dir_wcc.after; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "mknod_3:"); + + result.status = return_estale_or_rofs(dir, pre_op_dir, post_op_dir); + return &result; +} + +am_REMOVE3res * +am_nfs3_remove_3_svc(am_REMOVE3args *argp, struct svc_req *rqstp) +{ + static am_REMOVE3res result; + + am_diropargs3 *obj = &argp->object; + am_wcc_data dir_wcc; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "remove_3:"); + + result.status = unlink3_or_rmdir3(obj, &dir_wcc, TRUE); + + result.res_u.ok.dir_wcc = dir_wcc; + + return &result; +} + +am_RMDIR3res * +am_nfs3_rmdir_3_svc(am_RMDIR3args *argp, struct svc_req *rqstp) +{ + static am_RMDIR3res result; + + am_diropargs3 *obj = &argp->object; + am_wcc_data dir_wcc; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "rmdir_3:"); + + result.status = unlink3_or_rmdir3(obj, &dir_wcc, TRUE); + + result.res_u.ok.dir_wcc = dir_wcc; + + return &result; +} + +am_RENAME3res * +am_nfs3_rename_3_svc(am_RENAME3args *argp, struct svc_req *rqstp) +{ + static am_RENAME3res result; + + am_nfs_fh3 *fromdir = (am_nfs_fh3 *) &argp->from.dir; + am_nfs_fh3 *todir = (am_nfs_fh3 *) &argp->to.dir; + am_filename3 name = argp->to.name; + am_node *to_mp, *from_mp; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "rename_3:"); + + if (!(from_mp = fh3_to_mp(fromdir)) || !(to_mp = fh3_to_mp(todir))) + result.status = nfs_error(ESTALE); + /* + * If the kernel is doing clever things with referenced files + * then let it pretend... + */ + else { + am_wcc_attr *wcc_attr; + am_fattr3 *fattr3; + am_wcc_data *to_wcc_data, *from_wcc_data; + am_pre_op_attr *pre_op_to, *pre_op_from; + am_post_op_attr *post_op_to, *post_op_from; + nfsfattr *fattr; + + to_wcc_data = &result.res_u.ok.todir_wcc; + + pre_op_to = &to_wcc_data->before; + post_op_to = &to_wcc_data->after; + + pre_op_to->attributes_follow = 1; + fattr = &to_mp->am_fattr; + wcc_attr = &pre_op_to->am_pre_op_attr_u.attributes; + fattr_to_wcc_attr(fattr, wcc_attr); + post_op_to->attributes_follow = 1; + fattr3 = &post_op_to->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + from_wcc_data = &result.res_u.ok.fromdir_wcc; + + pre_op_from = &from_wcc_data->before; + post_op_from = &from_wcc_data->after; + + pre_op_from->attributes_follow = 1; + fattr = &from_mp->am_fattr; + wcc_attr = &pre_op_from->am_pre_op_attr_u.attributes; + fattr_to_wcc_attr(fattr, wcc_attr); + post_op_from->attributes_follow = 1; + fattr3 = &post_op_from->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + if (NSTREQ(name, ".nfs", 4)) + result.status = AM_NFS3_OK; + /* + * otherwise a failure + */ + else + result.status = nfs_error(EROFS); + } + + return &result; +} + +am_LINK3res * +am_nfs3_link_3_svc(am_LINK3args *argp, struct svc_req *rqstp) +{ + static am_LINK3res result; + + am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file; + am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->link.dir; + am_post_op_attr *post_op_file; + am_pre_op_attr *pre_op_dir; + am_post_op_attr *post_op_dir; + am_node *mp_file, *mp_dir; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "link_3:"); + + post_op_file = &result.res_u.fail.file_attributes; + post_op_file->attributes_follow = 0; + + mp_file = fh3_to_mp(file); + if (mp_file) { + nfsfattr *fattr = &mp_file->am_fattr; + am_fattr3 *fattr3 = &post_op_file->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + } + + pre_op_dir = &result.res_u.fail.linkdir_wcc.before; + pre_op_dir->attributes_follow = 0; + post_op_dir = &result.res_u.fail.linkdir_wcc.after; + post_op_dir->attributes_follow = 0; + + mp_dir = fh3_to_mp(dir); + if (mp_dir) { + nfsfattr *fattr = &mp_dir->am_fattr; + am_fattr3 *fattr3 = &post_op_dir->am_post_op_attr_u.attributes; + am_wcc_attr *wcc_attr = &pre_op_dir->am_pre_op_attr_u.attributes; + + pre_op_dir->attributes_follow = 1; + fattr_to_wcc_attr(fattr, wcc_attr); + post_op_dir->attributes_follow = 1; + fattr_to_fattr3(fattr, fattr3); + } + + if (!mp_file || !mp_dir) + result.status = nfs_error(ESTALE); + else + result.status = nfs_error(EROFS); + + return &result; +} + +am_READDIR3res * +am_nfs3_readdir_3_svc(am_READDIR3args *argp, struct svc_req *rqstp) +{ + static am_READDIR3res result; + static am_entry3 entries[MAX_READDIR_ENTRIES]; + am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->dir; + am_cookie3 cookie = argp->cookie; + am_cookieverf3 cookieverf; + am_count3 count = argp->count; + am_post_op_attr *post_op_dir; + am_node *mp; + int retry; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "readdir_3:"); + + memcpy(&cookieverf, &argp->cookieverf, sizeof(am_cookieverf3)); + + mp = fh3_to_mp3(dir, &retry, VLOOK_CREATE); + if (mp == NULL) { + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + post_op_dir = &result.res_u.fail.dir_attributes; + post_op_dir->attributes_follow = 0; + result.status = nfs_error(retry); + } else { + am_dirlist3 *list = &result.res_u.ok.reply; + am_nfsstat3 status; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\treaddir_3(%s)", mp->am_path); + + status = mp->am_al->al_mnt->mf_ops->readdir(mp, + (voidp)&cookie, list, entries, count); + if (status == 0) { + post_op_dir = &result.res_u.ok.dir_attributes; + nfsfattr *fattr; + am_fattr3 *fattr3; + + fattr = &mp->am_fattr; + fattr3 = &post_op_dir->am_post_op_attr_u.attributes; + post_op_dir->attributes_follow = 1; + fattr_to_fattr3(fattr, fattr3); + result.status = AM_NFS3_OK; + } else { + post_op_dir = &result.res_u.fail.dir_attributes; + post_op_dir->attributes_follow = 0; + result.status = nfs_error(status); + } + + mp->am_stats.s_readdir++; + } + + return &result; +} + +am_READDIRPLUS3res * +am_nfs3_readdirplus_3_svc(am_READDIRPLUS3args *argp, struct svc_req *rqstp) +{ + static am_READDIRPLUS3res result; + am_nfs_fh3 *dir = (am_nfs_fh3 *) &argp->dir; + am_post_op_attr *post_op_dir; + nfsfattr *fattr; + am_fattr3 *fattr3; + am_node *mp; + int retry; + + mp = fh3_to_mp3(dir, &retry, VLOOK_CREATE); + if (mp == NULL) { + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + post_op_dir = &result.res_u.fail.dir_attributes; + post_op_dir->attributes_follow = 0; + result.status = nfs_error(retry); + } else { + post_op_dir = &result.res_u.ok.dir_attributes; + fattr = &mp->am_fattr; + fattr3 = &post_op_dir->am_post_op_attr_u.attributes; + post_op_dir->attributes_follow = 1; + fattr_to_fattr3(fattr, fattr3); + result.status = AM_NFS3ERR_NOTSUPP; + } + + return &result; +} + +am_FSSTAT3res * +am_nfs3_fsstat_3_svc(am_FSSTAT3args *argp, struct svc_req *rqstp) +{ + static am_FSSTAT3res result; + + am_nfs_fh3 *fsroot = (am_nfs_fh3 *) &argp->fsroot; + am_post_op_attr *post_op_fsroot; + am_node *mp; + int retry; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "fsstat_3:"); + + mp = fh3_to_mp3(fsroot, &retry, VLOOK_CREATE); + if (!mp) { + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + post_op_fsroot = &result.res_u.fail.obj_attributes; + post_op_fsroot->attributes_follow = 0; + result.status = nfs_error(retry); + } else { + am_FSSTAT3resok *ok = &result.res_u.ok; + u_int blocks, bfree, bavail; + nfsfattr *fattr; + am_fattr3 *fattr3; + mntent_t mnt; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\tfsstat_3(%s)", mp->am_path); + + fattr = &mp->am_fattr; + post_op_fsroot = &ok->obj_attributes; + post_op_fsroot->attributes_follow = 1; + fattr3 = &post_op_fsroot->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + /* + * just return faked up file system information + */ + ok->tbytes = 1024; + ok->invarsec = 0; + + /* check if map is browsable and show_statfs_entries=yes */ + if ((gopt.flags & CFM_SHOW_STATFS_ENTRIES) && + mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { + mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; + if (amu_hasmntopt(&mnt, "browsable")) { + count_map_entries(mp, &blocks, &bfree, &bavail); + } + ok->fbytes = bfree; + ok->abytes = bavail; + ok->ffiles = bfree; + ok->afiles = bavail; + ok->tfiles = blocks; + } else { + ok->fbytes = 0; + ok->abytes = 0; + ok->ffiles = 0; + ok->afiles = 0; + ok->tfiles = 0; /* set to 1 if you don't want empty automounts */ + } + + result.status = AM_NFS3_OK; + mp->am_stats.s_statfs++; + } + + return &result; +} + +#define FSF3_HOMOGENEOUS 0x0008 + +am_FSINFO3res * +am_nfs3_fsinfo_3_svc(am_FSINFO3args *argp, struct svc_req *rqstp) +{ + static am_FSINFO3res result; + + am_nfs_fh3 *fsroot = (am_nfs_fh3 *) &argp->fsroot; + am_post_op_attr *post_op_fsroot; + am_node *mp; + int retry; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "fsinfo_3:"); + + mp = fh3_to_mp3(fsroot, &retry, VLOOK_CREATE); + if (!mp) { + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + post_op_fsroot = &result.res_u.fail.obj_attributes; + post_op_fsroot->attributes_follow = 0; + result.status = nfs_error(retry); + } else { + am_FSINFO3resok *ok = &result.res_u.ok; + nfsfattr *fattr; + am_fattr3 *fattr3; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\tfsinfo_3(%s)", mp->am_path); + + fattr = &mp->am_fattr; + post_op_fsroot = &ok->obj_attributes; + post_op_fsroot->attributes_follow = 1; + fattr3 = &post_op_fsroot->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + /* + * just return faked up file system information + */ + ok->rtmax = 0; + ok->rtpref = 0; + ok->rtmult = 0; + ok->wtmax = 0; + ok->wtpref = 0; + ok->wtmult = 0; + ok->dtpref = 1024; + ok->maxfilesize = 0; + ok->time_delta.seconds = 1; + ok->time_delta.nseconds = 0; + ok->properties = FSF3_HOMOGENEOUS; + + result.status = AM_NFS3_OK; + mp->am_stats.s_fsinfo++; + } + + return &result; +} + +am_PATHCONF3res * +am_nfs3_pathconf_3_svc(am_PATHCONF3args *argp, struct svc_req *rqstp) +{ + static am_PATHCONF3res result; + + am_nfs_fh3 *obj = (am_nfs_fh3 *) &argp->object; + am_post_op_attr *post_op_obj; + am_node *mp; + int retry; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "pathconf_3:"); + + mp = fh3_to_mp3(obj, &retry, VLOOK_CREATE); + if (!mp) { + if (retry < 0) { + amd_stats.d_drops++; + return 0; + } + post_op_obj = &result.res_u.fail.obj_attributes; + post_op_obj->attributes_follow = 0; + result.status = nfs_error(retry); + } else { + am_PATHCONF3resok *ok = &result.res_u.ok; + nfsfattr *fattr; + am_fattr3 *fattr3; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "\tpathconf_3(%s)", mp->am_path); + + fattr = &mp->am_fattr; + post_op_obj = &ok->obj_attributes; + post_op_obj->attributes_follow = 1; + fattr3 = &post_op_obj->am_post_op_attr_u.attributes; + fattr_to_fattr3(fattr, fattr3); + + ok->linkmax = 0; + ok->name_max = NAME_MAX; + ok->no_trunc = 1; + ok->chown_restricted = 1; + ok->case_insensitive = 0; + ok->case_preserving = 1; + + result.status = AM_NFS3_OK; + mp->am_stats.s_pathconf++; + } + + return &result; +} + +am_COMMIT3res * +am_nfs3_commit_3_svc(am_COMMIT3args *argp, struct svc_req *rqstp) +{ + static am_COMMIT3res result; + + am_nfs_fh3 *file = (am_nfs_fh3 *) &argp->file; + am_pre_op_attr *pre_op_file = &result.res_u.fail.file_wcc.before; + am_post_op_attr *post_op_file = &result.res_u.fail.file_wcc.after; + + if (amuDebug(D_TRACE)) + plog(XLOG_DEBUG, "commit_3:"); + + result.status = return_estale_or_rofs(file, pre_op_file, post_op_file); + + return &result; +} +#endif /* HAVE_FS_NFS3 */ diff --git a/contrib/amd/amd/ops_TEMPLATE.c b/contrib/amd/amd/ops_TEMPLATE.c index 3f742198441..b873c8ece27 100644 --- a/contrib/amd/amd/ops_TEMPLATE.c +++ b/contrib/amd/amd/ops_TEMPLATE.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -64,7 +60,7 @@ static int foofs_init(mntfs *mf); static int foofs_mount(am_node *mp, mntfs *mf); static int foofs_umount(am_node *mp, mntfs *mf); static am_node *foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op); -static int foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count); +static int foofs_readdir(am_node *mp, void cookie, voidp dp, voidp ep, u_int count); static am_node *foofs_readlink(am_node *mp, int *error_return); static void foofs_mounted(am_node *am, mntfs *mf); static void foofs_umounted(am_node *mp, mntfs *mf); @@ -220,7 +216,7 @@ foofs_lookuppn(am_node *mp, char *fname, int *error_return, int op) * If OK, fills in ep with chain of directory entries. */ static int -foofs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) +foofs_readdir(am_node *mp, void cookie, voidp dp, voidp ep, u_int count) { int error = 0; diff --git a/contrib/amd/amd/ops_cachefs.c b/contrib/amd/amd/ops_cachefs.c index d3e303bc2bf..26a33352745 100644 --- a/contrib/amd/amd/ops_cachefs.c +++ b/contrib/amd/amd/ops_cachefs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -99,7 +95,7 @@ cachefs_match(am_opts *fo) dlog("CACHEFS: using cache directory \"%s\"", fo->opt_cachedir); /* determine magic cookie to put in mtab */ - return strdup(fo->opt_cachedir); + return xstrdup(fo->opt_cachedir); } @@ -114,7 +110,7 @@ cachefs_init(mntfs *mf) * Save cache directory name */ if (!mf->mf_private) { - mf->mf_private = (voidp) strdup(mf->mf_fo->opt_cachedir); + mf->mf_private = (voidp) xstrdup(mf->mf_fo->opt_cachedir); mf->mf_prfree = (void (*)(voidp)) free; } diff --git a/contrib/amd/amd/ops_cdfs.c b/contrib/amd/amd/ops_cdfs.c index 40355ac5c07..6ceb76408b0 100644 --- a/contrib/amd/amd/ops_cdfs.c +++ b/contrib/amd/amd/ops_cdfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -97,7 +93,7 @@ cdfs_match(am_opts *fo) /* * Determine magic cookie to put in mtab */ - return strdup(fo->opt_dev); + return xstrdup(fo->opt_dev); } @@ -148,6 +144,7 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs) if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP)) cdfs_flags |= MNT2_CDFS_OPT_RRIP; #endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */ + #if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP)) cdfs_flags |= MNT2_CDFS_OPT_NORRIP; @@ -157,11 +154,27 @@ mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs) if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS)) cdfs_flags |= MNT2_CDFS_OPT_GENS; #endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */ + #if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT)) cdfs_flags |= MNT2_CDFS_OPT_EXTATT; #endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */ +#if defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS) + if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOCASETRANS)) + cdfs_flags |= MNT2_CDFS_OPT_NOCASETRANS; +#endif /* defined(MNT2_CDFS_OPT_NOCASETRANS) && defined(MNTTAB_OPT_NOCASETRANS) */ + +#if defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET) + if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOJOLIET)) + cdfs_flags |= MNT2_CDFS_OPT_NOJOLIET; +#endif /* defined(MNT2_CDFS_OPT_NOJOLIET) && defined(MNTTAB_OPT_NOJOLIET) */ + +#if defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS) + if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRCASEINS)) + cdfs_flags |= MNT2_CDFS_OPT_RRCASEINS; +#endif /* defined(MNT2_CDFS_OPT_RRCASEINS) && defined(MNTTAB_OPT_RRCASEINS) */ + genflags = compute_mount_flags(&mnt); #ifdef HAVE_FS_AUTOFS if (on_autofs) diff --git a/contrib/amd/amd/ops_efs.c b/contrib/amd/amd/ops_efs.c index 047fe1e4690..58bf8f0b76c 100644 --- a/contrib/amd/amd/ops_efs.c +++ b/contrib/amd/amd/ops_efs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -98,7 +94,7 @@ efs_match(am_opts *fo) /* * Determine magic cookie to put in mtab */ - return strdup(fo->opt_dev); + return xstrdup(fo->opt_dev); } @@ -137,6 +133,9 @@ mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs) #ifdef HAVE_EFS_ARGS_T_FSPEC efs_args.fspec = fs_name; #endif /* HAVE_EFS_ARGS_T_FSPEC */ +#if defined(HAVE_EFS_ARGS_T_VERSION) && defined(EFS_MNT_VERSION) + efs_args.version = EFS_MNT_VERSION; +#endif /* HAVE_EFS_ARGS_T_VERSION && EFS_MNT_VERSION */ /* * Call generic mount routine diff --git a/contrib/amd/amd/ops_ext.c b/contrib/amd/amd/ops_ext.c new file mode 100644 index 00000000000..106ab31f374 --- /dev/null +++ b/contrib/amd/amd/ops_ext.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/ops_ext.c + * + */ + +/* + * Irix UN*X file system: EXT (Extended File System) + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#include +#include + +/* forward declarations */ +static char *ext_match(am_opts *fo); +static int ext2_mount(am_node *am, mntfs *mf); +static int ext3_mount(am_node *am, mntfs *mf); +static int ext4_mount(am_node *am, mntfs *mf); +static int ext_umount(am_node *am, mntfs *mf); + +/* + * Ops structure + */ +am_ops ext2_ops = +{ + "ext2", + ext_match, + 0, /* ext_init */ + ext2_mount, + ext_umount, + amfs_error_lookup_child, + amfs_error_mount_child, + amfs_error_readdir, + 0, /* ext_readlink */ + 0, /* ext_mounted */ + 0, /* ext_umounted */ + amfs_generic_find_srvr, + 0, /* ext_get_wchan */ + FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ +#ifdef HAVE_FS_AUTOFS + AUTOFS_EXT_FS_FLAGS, +#endif /* HAVE_FS_AUTOFS */ +}; + +am_ops ext3_ops = +{ + "ext3", + ext_match, + 0, /* ext_init */ + ext3_mount, + ext_umount, + amfs_error_lookup_child, + amfs_error_mount_child, + amfs_error_readdir, + 0, /* ext_readlink */ + 0, /* ext_mounted */ + 0, /* ext_umounted */ + amfs_generic_find_srvr, + 0, /* ext_get_wchan */ + FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ +#ifdef HAVE_FS_AUTOFS + AUTOFS_EXT_FS_FLAGS, +#endif /* HAVE_FS_AUTOFS */ +}; + +am_ops ext4_ops = +{ + "ext4", + ext_match, + 0, /* ext_init */ + ext4_mount, + ext_umount, + amfs_error_lookup_child, + amfs_error_mount_child, + amfs_error_readdir, + 0, /* ext_readlink */ + 0, /* ext_mounted */ + 0, /* ext_umounted */ + amfs_generic_find_srvr, + 0, /* ext_get_wchan */ + FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ +#ifdef HAVE_FS_AUTOFS + AUTOFS_EXT_FS_FLAGS, +#endif /* HAVE_FS_AUTOFS */ +}; + +/* + * EXT needs local filesystem and device. + */ +static char * +ext_match(am_opts *fo) +{ + + if (!fo->opt_dev) { + plog(XLOG_USER, "ext: no device specified"); + return 0; + } + + dlog("EXT: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs); + + /* + * Determine magic cookie to put in mtab + */ + return xstrdup(fo->opt_dev); +} + + +static int +mount_ext(char *mntdir, char *fs_name, char *opts, int on_autofs, char * + mount_type, const char *mnttab_type) +{ + ext_args_t ext_args; + mntent_t mnt; + int flags; + + /* + * Figure out the name of the file system type. + */ + MTYPE_TYPE type = mount_type; + + memset((voidp) &ext_args, 0, sizeof(ext_args)); /* Paranoid */ + + /* + * Fill in the mount structure + */ + memset((voidp) &mnt, 0, sizeof(mnt)); + mnt.mnt_dir = mntdir; + mnt.mnt_fsname = fs_name; + mnt.mnt_type = mnttab_type; + mnt.mnt_opts = opts; + + flags = compute_mount_flags(&mnt); +#ifdef HAVE_FS_AUTOFS + if (on_autofs) + flags |= autofs_compute_mount_flags(&mnt); +#endif /* HAVE_FS_AUTOFS */ + + /* + * Call generic mount routine + */ + return mount_fs(&mnt, flags, (caddr_t) &ext_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); +} + + +static int +ext_mount(am_node *am, mntfs *mf, char *mount_type, + const char *mnttab_type) +{ + int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; + int error; + + error = mount_ext(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs, + mount_type, mnttab_type); + if (error) { + errno = error; + plog(XLOG_ERROR, "mount_ext: %m"); + return error; + } + + return 0; +} + +static int +ext2_mount(am_node *am, mntfs *mf) +{ + return ext_mount(am, mf, MOUNT_TYPE_EXT2, MNTTAB_TYPE_EXT2); +} + +static int +ext3_mount(am_node *am, mntfs *mf) +{ + return ext_mount(am, mf, MOUNT_TYPE_EXT3, MNTTAB_TYPE_EXT3); +} + +static int +ext4_mount(am_node *am, mntfs *mf) +{ + return ext_mount(am, mf, MOUNT_TYPE_EXT4, MNTTAB_TYPE_EXT4); +} + +static int +ext_umount(am_node *am, mntfs *mf) +{ + int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; + + return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); +} diff --git a/contrib/amd/amd/ops_lofs.c b/contrib/amd/amd/ops_lofs.c index 26fdc9f9b62..b04f64399c1 100644 --- a/contrib/amd/amd/ops_lofs.c +++ b/contrib/amd/amd/ops_lofs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -97,7 +93,7 @@ lofs_match(am_opts *fo) /* * Determine magic cookie to put in mtab */ - return strdup(fo->opt_rfs); + return xstrdup(fo->opt_rfs); } diff --git a/contrib/amd/amd/ops_lustre.c b/contrib/amd/amd/ops_lustre.c new file mode 100644 index 00000000000..1b321ce4e8c --- /dev/null +++ b/contrib/amd/amd/ops_lustre.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2011 Christos Zoulas + * 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 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. + * + * + * File: am-utils/amd/ops_lustre.c + * + */ + +/* + * Lustre file system + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#ifdef HAVE_FS_LUSTRE +#include +#include + +/* forward declarations */ +static char *lustre_match(am_opts *fo); +static int lustre_mount(am_node *am, mntfs *mf); +static int lustre_umount(am_node *am, mntfs *mf); + +/* + * Ops structure + */ +am_ops lustre_ops = +{ + "lustre", + lustre_match, + 0, /* lustre_init */ + lustre_mount, + lustre_umount, + amfs_error_lookup_child, + amfs_error_mount_child, + amfs_error_readdir, + 0, /* lustre_readlink */ + 0, /* lustre_mounted */ + 0, /* lustre_umounted */ + amfs_generic_find_srvr, + 0, /* lustre_get_wchan */ + FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ +#ifdef HAVE_FS_AUTOFS + AUTOFS_LUSTRE_FS_FLAGS, +#endif /* HAVE_FS_AUTOFS */ +}; + + +/* + * Lustre needs remote filesystem and host. + */ +static char * +lustre_match(am_opts *fo) +{ + char *xmtab, *cp; + size_t l; + char *rhost, *ptr, *remhost; + struct in_addr addr; + + if (fo->opt_fs && !fo->opt_rfs) + fo->opt_rfs = fo->opt_fs; + if (!fo->opt_rfs) { + plog(XLOG_USER, "lustre: no remote filesystem specified"); + return NULL; + } + if (!fo->opt_rhost) { + plog(XLOG_USER, "lustre: no remote host specified"); + return NULL; + } + + /* + * Determine magic cookie to put in mtab + */ + rhost = xstrdup(fo->opt_rhost); + remhost = NULL; + for (ptr = strtok(rhost, ":"); ptr; ptr = strtok(NULL, ":")) { + char *at = strchr(ptr, '@'); + if (at == NULL) { + plog(XLOG_USER, "lustre: missing protocol in host `%s'", ptr); + XFREE(rhost); + return NULL; + } + *at = '\0'; + /* + * Convert symbolic addresses to numbers that the kernel likes + */ + if (inet_aton(ptr, &addr) == 0) { + struct hostent *hp; + if ((hp = gethostbyname(ptr)) == NULL) { + plog(XLOG_USER, "lustre: unknown host `%s'", ptr); + XFREE(rhost); + return NULL; + } + if (hp->h_length != sizeof(addr.s_addr)) { + plog(XLOG_USER, "lustre: bad address length %zu != %d for %s", + sizeof(addr), hp->h_length, ptr); + XFREE(rhost); + return NULL; + } + memcpy(&addr.s_addr, hp->h_addr, sizeof(addr)); + } + *at = '@'; + + cp = remhost; + if (remhost) + remhost = strvcat(cp, ":", inet_ntoa(addr), at, NULL); + else + remhost = strvcat(inet_ntoa(addr), at, NULL); + XFREE(cp); + } + if (remhost == NULL) { + plog(XLOG_USER, "lustre: empty host"); + XFREE(rhost); + return NULL; + } + + XFREE(rhost); + XFREE(fo->opt_rhost); + fo->opt_rhost = remhost; + + l = strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2; + xmtab = xmalloc(l); + xsnprintf(xmtab, l, "%s:%s", fo->opt_rhost, fo->opt_rfs); + dlog("lustre: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"", + fo->opt_rhost, fo->opt_rfs, fo->opt_fs); + + + return xmtab; +} + +static int +lustre_mount(am_node *am, mntfs *mf) +{ + mntent_t mnt; + int genflags, error; + int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; + + /* + * Figure out the name of the file system type. + */ + MTYPE_TYPE type = MOUNT_TYPE_LUSTRE; + + /* + * Fill in the mount structure + */ + memset(&mnt, 0, sizeof(mnt)); + mnt.mnt_dir = mf->mf_mount; + mnt.mnt_fsname = mf->mf_info; + mnt.mnt_type = MNTTAB_TYPE_LUSTRE; + mnt.mnt_opts = mf->mf_mopts; + + genflags = compute_mount_flags(&mnt); +#ifdef HAVE_FS_AUTOFS + if (on_autofs) + genflags |= autofs_compute_mount_flags(&mnt); +#endif /* HAVE_FS_AUTOFS */ + + /* + * Call generic mount routine + */ + error = mount_fs(&mnt, genflags, NULL, 0, type, 0, + NULL, mnttab_file_name, on_autofs); + if (error) { + errno = error; + plog(XLOG_ERROR, "mount_lustre: %m"); + return error; + } + + return 0; +} + + +static int +lustre_umount(am_node *am, mntfs *mf) +{ + int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; + + return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); +} +#endif diff --git a/contrib/amd/amd/ops_mfs.c b/contrib/amd/amd/ops_mfs.c index ccaa49c569c..822a2659317 100644 --- a/contrib/amd/amd/ops_mfs.c +++ b/contrib/amd/amd/ops_mfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/ops_nfs.c b/contrib/amd/amd/ops_nfs.c index a6a85858d48..2dbfa5b5e2e 100644 --- a/contrib/amd/amd/ops_nfs.c +++ b/contrib/amd/amd/ops_nfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -113,6 +109,13 @@ static int call_mountd(fh_cache *fp, u_long proc, fwd_fun f, wchan_t wchan); static int webnfs_lookup(fh_cache *fp, fwd_fun f, wchan_t wchan); static int fh_id = 0; +/* + * clamp the filehandle version to 3, so that we can fail back to nfsv3 + * since nfsv4 does not have file handles + */ +#define SET_FH_VERSION(fs) \ + (fs)->fs_version > NFS_VERSION3 ? NFS_VERSION3 : (fs)->fs_version; + /* globals */ AUTH *nfs_auth; qelem fh_head = {&fh_head, &fh_head}; @@ -145,7 +148,7 @@ am_ops nfs_ops = static fh_cache * find_nfs_fhandle_cache(opaque_t arg, int done) { - fh_cache *fp, *fp2 = 0; + fh_cache *fp, *fp2 = NULL; int id = (long) arg; /* for 64-bit archs */ ITER(fp, fh_cache, &fh_head) { @@ -201,6 +204,10 @@ got_nfs_fh_mount(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in memmove(fp->fh_nfs_handle.v3.am_fh3_data, res3.mountres3_u.mountinfo.fhandle.fhandle3_val, fp->fh_nfs_handle.v3.am_fh3_length); + + XFREE(res3.mountres3_u.mountinfo.fhandle.fhandle3_val); + if (res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val) + XFREE(res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val); } else { #endif /* HAVE_FS_NFS3 */ memset(&res, 0, sizeof(res)); @@ -326,8 +333,7 @@ discard_fh(opaque_t arg) dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path); free_srvr(fp->fh_fs); } - if (fp->fh_path) - XFREE(fp->fh_path); + XFREE(fp->fh_path); XFREE(fp); } @@ -338,7 +344,7 @@ discard_fh(opaque_t arg) static int prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs *mf) { - fh_cache *fp, *fp_save = 0; + fh_cache *fp, *fp_save = NULL; int error; int reuse_id = FALSE; @@ -466,11 +472,11 @@ prime_nfs_fhandle_cache(char *path, fserver *fs, am_nfs_handle_t *fhbuf, mntfs * fp->fh_sin = *fs->fs_ip; if (!(mf->mf_flags & MFF_WEBNFS)) fp->fh_sin.sin_port = 0; - fp->fh_nfs_version = fs->fs_version; + fp->fh_nfs_version = SET_FH_VERSION(fs); } fp->fh_fs = dup_srvr(fs); - fp->fh_path = strdup(path); + fp->fh_path = xstrdup(path); if (mf->mf_flags & MFF_WEBNFS) error = webnfs_lookup(fp, got_nfs_fh_webnfs, get_mntfs_wchan(mf)); @@ -544,7 +550,9 @@ call_mountd(fh_cache *fp, u_long proc, fwd_fun fun, wchan_t wchan) if (error) return error; fp->fh_sin.sin_port = mountd_port; - } + dlog("%s: New %d mountd port", __func__, fp->fh_sin.sin_port); + } else + dlog("%s: Already had %d mountd port", __func__, fp->fh_sin.sin_port); /* find the right version of the mount protocol */ #ifdef HAVE_FS_NFS3 @@ -605,7 +613,7 @@ webnfs_lookup(fh_cache *fp, fwd_fun fun, wchan_t wchan) nfsdiropargs args; #ifdef HAVE_FS_NFS3 am_LOOKUP3args args3; -#endif +#endif /* HAVE_FS_NFS3 */ char *wnfs_path; size_t l; @@ -724,6 +732,17 @@ nfs_init(mntfs *mf) am_nfs_handle_t fhs; char *colon; +#ifdef NO_FALLBACK + /* + * We don't need file handles for NFS version 4, but we can fall back to + * version 3, so we allocate anyway + */ +#ifdef HAVE_FS_NFS4 + if (mf->mf_server->fs_version == NFS_VERSION4) + return 0; +#endif /* HAVE_FS_NFS4 */ +#endif /* NO_FALLBACK */ + if (mf->mf_private) { if (mf->mf_flags & MFF_NFS_SCALEDOWN) { fserver *fs; @@ -732,6 +751,9 @@ nfs_init(mntfs *mf) mf->mf_ops->umounted(mf); mf->mf_prfree(mf->mf_private); + mf->mf_private = NULL; + mf->mf_prfree = NULL; + fs = mf->mf_ops->ffserver(mf); free_srvr(mf->mf_server); mf->mf_server = fs; @@ -769,7 +791,11 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf) int retry; int proto = AMU_TYPE_NONE; mntent_t mnt; + void *argsp; nfs_args_t nfs_args; +#ifdef HAVE_FS_NFS4 + nfs4_args_t nfs4_args; +#endif /* HAVE_FS_NFS4 */ /* * Extract HOST name to give to kernel. @@ -829,10 +855,7 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf) /* * Set mount types accordingly */ -#ifndef HAVE_FS_NFS3 - type = MOUNT_TYPE_NFS; - mnt.mnt_type = MNTTAB_TYPE_NFS; -#else /* HAVE_FS_NFS3 */ +#ifdef HAVE_FS_NFS3 if (nfs_version == NFS_VERSION3) { type = MOUNT_TYPE_NFS3; /* @@ -843,16 +866,25 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf) * So on those systems, set it to "nfs". * Note: MNTTAB_OPT_VERS is always set for NFS3 (see am_compat.h). */ + argsp = &nfs_args; # if defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) mnt.mnt_type = MNTTAB_TYPE_NFS; # else /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */ mnt.mnt_type = MNTTAB_TYPE_NFS3; # endif /* defined(MNTTAB_OPT_VERS) && defined(MOUNT_TABLE_ON_FILE) */ - } else { +# ifdef HAVE_FS_NFS4 + } else if (nfs_version == NFS_VERSION4) { + argsp = &nfs4_args; + type = MOUNT_TYPE_NFS4; + mnt.mnt_type = MNTTAB_TYPE_NFS4; +# endif /* HAVE_FS_NFS4 */ + } else +#endif /* HAVE_FS_NFS3 */ + { + argsp = &nfs_args; type = MOUNT_TYPE_NFS; mnt.mnt_type = MNTTAB_TYPE_NFS; } -#endif /* HAVE_FS_NFS3 */ plog(XLOG_INFO, "mount_nfs_fh: NFS version %d", (int) nfs_version); plog(XLOG_INFO, "mount_nfs_fh: using NFS transport %s", nfs_proto); @@ -866,32 +898,44 @@ mount_nfs_fh(am_nfs_handle_t *fhp, char *mntdir, char *fs_name, mntfs *mf) genflags |= autofs_compute_mount_flags(&mnt); #endif /* HAVE_FS_AUTOFS */ - /* setup the many fields and flags within nfs_args */ - compute_nfs_args(&nfs_args, - &mnt, - genflags, - NULL, /* struct netconfig *nfsncp */ - fs->fs_ip, - nfs_version, - nfs_proto, - fhp, - host, - fs_name); + /* setup the many fields and flags within nfs_args */ + compute_nfs_args(argsp, + &mnt, + genflags, + NULL, /* struct netconfig *nfsncp */ + fs->fs_ip, + nfs_version, + nfs_proto, + fhp, + host, + fs_name); /* finally call the mounting function */ if (amuDebug(D_TRACE)) { - print_nfs_args(&nfs_args, nfs_version); + print_nfs_args(argsp, nfs_version); plog(XLOG_DEBUG, "Generic mount flags 0x%x used for NFS mount", genflags); } - error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, - nfs_version, nfs_proto, mnttab_file_name, on_autofs); - XFREE(xopts); + error = mount_fs(&mnt, genflags, argsp, retry, type, + nfs_version, nfs_proto, mnttab_file_name, on_autofs); + XFREE(mnt.mnt_opts); + discard_nfs_args(argsp, nfs_version); -#ifdef HAVE_TRANSPORT_TYPE_TLI - free_knetconfig(nfs_args.knconf); - if (nfs_args.addr) - XFREE(nfs_args.addr); /* allocated in compute_nfs_args() */ -#endif /* HAVE_TRANSPORT_TYPE_TLI */ +#ifdef HAVE_FS_NFS4 +# ifndef NO_FALLBACK + /* + * If we are using a v4 file handle, we try a v3 if we get back: + * ENOENT: NFS v4 has a different export list than v3 + * EPERM: Kernels <= 2.6.18 return that, instead of ENOENT + */ + if ((error == ENOENT || error == EPERM) && nfs_version == NFS_VERSION4) { + plog(XLOG_DEBUG, "Could not find NFS 4 mount, trying again with NFS 3"); + fs->fs_version = NFS_VERSION3; + error = mount_nfs_fh(fhp, mntdir, fs_name, mf); + if (error) + fs->fs_version = NFS_VERSION4; + } +# endif /* NO_FALLBACK */ +#endif /* HAVE_FS_NFS4 */ return error; } @@ -903,11 +947,16 @@ nfs_mount(am_node *am, mntfs *mf) int error = 0; mntent_t mnt; - if (!mf->mf_private) { + if (!mf->mf_private && mf->mf_server->fs_version != 4) { plog(XLOG_ERROR, "Missing filehandle for %s", mf->mf_info); return EINVAL; } + if (mf->mf_mopts == NULL) { + plog(XLOG_ERROR, "Missing mount options for %s", mf->mf_info); + return EINVAL; + } + mnt.mnt_opts = mf->mf_mopts; if (amu_hasmntopt(&mnt, "softlookup") || (amu_hasmntopt(&mnt, "soft") && !amu_hasmntopt(&mnt, "nosoftlookup"))) @@ -932,6 +981,7 @@ nfs_umount(am_node *am, mntfs *mf) { int unmount_flags, new_unmount_flags, error; + dlog("attempting nfs umount"); unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); @@ -1031,12 +1081,12 @@ nfs_umounted(mntfs *mf) f.fh_path = path; f.fh_sin = *fs->fs_ip; f.fh_sin.sin_port = (u_short) 0; - f.fh_nfs_version = fs->fs_version; + f.fh_nfs_version = SET_FH_VERSION(fs); f.fh_fs = fs; f.fh_id = 0; f.fh_error = 0; - prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) 0, mf); - call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) 0, (wchan_t) 0); + prime_nfs_fhandle_cache(colon + 1, mf->mf_server, (am_nfs_handle_t *) NULL, mf); + call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun *) NULL, (wchan_t) NULL); *colon = ':'; } } diff --git a/contrib/amd/amd/ops_nfs3.c b/contrib/amd/amd/ops_nfs3.c index db3c7f9d265..e07811b808e 100644 --- a/contrib/amd/amd/ops_nfs3.c +++ b/contrib/amd/amd/ops_nfs3.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/ops_nfs4.c b/contrib/amd/amd/ops_nfs4.c new file mode 100644 index 00000000000..3798590837f --- /dev/null +++ b/contrib/amd/amd/ops_nfs4.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/ops_nfs4.c + * + */ + +/* + * Network file system version 4.0 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#include +#include + +/* FEEL FREE TO IMPLEMENT THIS... :-) */ diff --git a/contrib/amd/amd/ops_nullfs.c b/contrib/amd/amd/ops_nullfs.c index cf621ec33ff..73d1f0e53f1 100644 --- a/contrib/amd/amd/ops_nullfs.c +++ b/contrib/amd/amd/ops_nullfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/ops_pcfs.c b/contrib/amd/amd/ops_pcfs.c index 527dc926ca7..b4c8dcd5fec 100644 --- a/contrib/amd/amd/ops_pcfs.c +++ b/contrib/amd/amd/ops_pcfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -97,7 +93,7 @@ pcfs_match(am_opts *fo) /* * Determine magic cookie to put in mtab */ - return strdup(fo->opt_dev); + return xstrdup(fo->opt_dev); } diff --git a/contrib/amd/amd/ops_tfs.c b/contrib/amd/amd/ops_tfs.c index 142c3202293..3276a6e62ff 100644 --- a/contrib/amd/amd/ops_tfs.c +++ b/contrib/amd/amd/ops_tfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/ops_tmpfs.c b/contrib/amd/amd/ops_tmpfs.c index eddd75569e9..d9a15ea0434 100644 --- a/contrib/amd/amd/ops_tmpfs.c +++ b/contrib/amd/amd/ops_tmpfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -51,4 +47,146 @@ #include #include -/* FEEL FREE TO IMPLEMENT THIS... :-) */ +/* forward declarations */ +static char *tmpfs_match(am_opts *fo); +static int tmpfs_mount(am_node *am, mntfs *mf); +static int tmpfs_umount(am_node *am, mntfs *mf); + +/* + * Ops structure + */ +am_ops tmpfs_ops = +{ + "tmpfs", + tmpfs_match, + 0, /* tmpfs_init */ + tmpfs_mount, + tmpfs_umount, + amfs_error_lookup_child, + amfs_error_mount_child, + amfs_error_readdir, + 0, /* tmpfs_readlink */ + 0, /* tmpfs_mounted */ + 0, /* tmpfs_umounted */ + amfs_generic_find_srvr, + 0, /* tmpfs_get_wchan */ + FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ +#if defined(HAVE_FS_AUTOFS) && defined(AUTOFS_TMPFS_FS_FLAGS) + AUTOFS_TMPFS_FS_FLAGS, +#endif /* HAVE_FS_AUTOFS */ +}; + + +/* + * EFS needs local filesystem and device. + */ +static char * +tmpfs_match(am_opts *fo) +{ + + if (!fo->opt_dev) { + plog(XLOG_USER, "tmpfs: no device specified"); + return 0; + } + + dlog("EFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs); + + /* + * Determine magic cookie to put in mtab + */ + return xstrdup(fo->opt_dev); +} + + +static int +mount_tmpfs(char *mntdir, char *fs_name, char *opts, int on_autofs) +{ + tmpfs_args_t tmpfs_args; + mntent_t mnt; + int flags; + const char *p; + + /* + * Figure out the name of the file system type. + */ + MTYPE_TYPE type = MOUNT_TYPE_TMPFS; + + p = NULL; + memset((voidp) &tmpfs_args, 0, sizeof(tmpfs_args)); /* Paranoid */ + + /* + * Fill in the mount structure + */ + memset((voidp) &mnt, 0, sizeof(mnt)); + mnt.mnt_dir = mntdir; + mnt.mnt_fsname = fs_name; + mnt.mnt_type = MNTTAB_TYPE_TMPFS; + mnt.mnt_opts = opts; + + flags = compute_mount_flags(&mnt); +#ifdef HAVE_FS_AUTOFS + if (on_autofs) + flags |= autofs_compute_mount_flags(&mnt); +#endif /* HAVE_FS_AUTOFS */ + +#if defined(HAVE_TMPFS_ARGS_T_TA_VERSION) && defined(TMPFS_ARGS_VERSION) + tmpfs_args.ta_version = TMPFS_ARGS_VERSION; +#endif /* HAVE_TMPFS_ARGS_T_TA_VERSION && TMPFS_ARGS_VERSION */ +#ifdef HAVE_TMPFS_ARGS_T_TA_NODES_MAX + if ((p = amu_hasmntopt(&mnt, "nodes")) == NULL) + p = "1000000"; + tmpfs_args.ta_nodes_max = atoi(p); +#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */ +#ifdef HAVE_TMPFS_ARGS_T_TA_SIZE_MAX + if ((p = amu_hasmntopt(&mnt, "size")) == NULL) + p = "10000000"; + tmpfs_args.ta_size_max = atoi(p); +#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */ +#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_UID + if ((p = amu_hasmntopt(&mnt, "uid")) == NULL) + p = "0"; + tmpfs_args.ta_root_uid = atoi(p); +#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_UID */ +#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_GID + if ((p = amu_hasmntopt(&mnt, "gid")) == NULL) + p = "0"; + tmpfs_args.ta_root_gid = atoi(p); +#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_GID */ +#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_MODE + if ((p = amu_hasmntopt(&mnt, "mode")) == NULL) + p = "01777"; + tmpfs_args.ta_root_mode = strtol(p, NULL, 8); +#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_MODE */ + + /* + * Call generic mount routine + */ + return mount_fs(&mnt, flags, (caddr_t) &tmpfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs); +} + + +static int +tmpfs_mount(am_node *am, mntfs *mf) +{ + int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; + int error; + + error = mount_tmpfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); + if (error) { + errno = error; + plog(XLOG_ERROR, "mount_tmpfs: %m"); + return error; + } + + return 0; +} + + +static int +tmpfs_umount(am_node *am, mntfs *mf) +{ + int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; + + return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); +} + diff --git a/contrib/amd/amd/ops_udf.c b/contrib/amd/amd/ops_udf.c new file mode 100644 index 00000000000..4230c5b12ff --- /dev/null +++ b/contrib/amd/amd/ops_udf.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/ops_udf.c + * + */ + +/* + * UDF file system + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#include +#include + +/* forward definitions */ +static char *udf_match(am_opts *fo); +static int udf_mount(am_node *am, mntfs *mf); +static int udf_umount(am_node *am, mntfs *mf); + +/* + * Ops structure + */ +am_ops udf_ops = +{ + "udf", + udf_match, + 0, /* udf_init */ + udf_mount, + udf_umount, + amfs_error_lookup_child, + amfs_error_mount_child, + amfs_error_readdir, + 0, /* udf_readlink */ + 0, /* udf_mounted */ + 0, /* udf_umounted */ + amfs_generic_find_srvr, + 0, /* udf_get_wchan */ + FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO, /* nfs_fs_flags */ +#ifdef HAVE_FS_AUTOFS + AUTOFS_UDF_FS_FLAGS, +#endif /* HAVE_FS_AUTOFS */ +}; + +#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID) +static int +a_num(const char *s, const char *id_type) +{ + int id; + char *ep; + + id = strtol(s, &ep, 0); + if (*ep || s == ep || id < 0) { + plog(XLOG_ERROR, "mount_udf: unknown %s: %s", id_type, s); + return 0; + } + return id; +} +#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID) */ + +#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) +static gid_t +a_gid(const char *s, const char *id_type) +{ + struct group *gr; + + if ((gr = getgrnam(s)) != NULL) + return gr->gr_gid; + return a_num(s, id_type); +} +#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) */ + +#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) +static uid_t +a_uid(const char *s, const char *id_type) +{ + struct passwd *pw; + + if ((pw = getpwnam(s)) != NULL) + return pw->pw_uid; + return a_num(s, id_type); +} +#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) */ + +/* + * UDF needs remote filesystem. + */ +static char * +udf_match(am_opts *fo) +{ + + if (!fo->opt_dev) { + plog(XLOG_USER, "udf: no source device specified"); + return 0; + } + dlog("UDF: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs); + + /* + * Determine magic cookie to put in mtab + */ + return xstrdup(fo->opt_dev); +} + +static int +mount_udf(char *mntdir, char *fs_name, char *opts, int on_autofs) +{ + udf_args_t udf_args; + mntent_t mnt; + int flags; + char *str; +#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) + uid_t uid_nobody; + gid_t gid_nobody; +#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */ + /* + * Figure out the name of the file system type. + */ + MTYPE_TYPE type = MOUNT_TYPE_UDF; + +#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) + uid_nobody = a_uid("nobody", "user"); + if (uid_nobody == 0) { + plog(XLOG_ERROR, "mount_udf: invalid uid for nobody"); + return EPERM; + } +#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */ + +#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID) + gid_nobody = a_gid("nobody", "group"); + if (gid_nobody == 0) { + plog(XLOG_ERROR, "mount_udf: invalid gid for nobody"); + return EPERM; + } +#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID) */ + + str = NULL; + memset((voidp) &udf_args, 0, sizeof(udf_args)); /* Paranoid */ + + /* + * Fill in the mount structure + */ + memset((voidp)&mnt, 0, sizeof(mnt)); + mnt.mnt_dir = mntdir; + mnt.mnt_fsname = fs_name; + mnt.mnt_type = MNTTAB_TYPE_UDF; + mnt.mnt_opts = opts; + + flags = compute_mount_flags(&mnt); + +#ifdef HAVE_UDF_ARGS_T_UDFMFLAGS +# if defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION) + if (amu_hasmntopt(&mnt, MNTTAB_OPT_CLOSESESSION)) + udf_args.udfmflags |= MNT2_UDF_OPT_CLOSESESSION; +# endif /* defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION) */ +#endif /* HAVE_UDF_ARGS_T_UDFMFLAGS */ + +#ifdef HAVE_UDF_ARGS_T_NOBODY_UID + udf_args.nobody_uid = uid_nobody; +#endif /* HAVE_UDF_ARGS_T_NOBODY_UID */ + +#ifdef HAVE_UDF_ARGS_T_NOBODY_GID + udf_args.nobody_gid = gid_nobody; +#endif /* HAVE_UDF_ARGS_T_NOBODY_GID */ + +#ifdef HAVE_UDF_ARGS_T_ANON_UID + udf_args.anon_uid = uid_nobody; /* default to nobody */ + if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) { + udf_args.anon_uid = a_uid(str, MNTTAB_OPT_USER); + XFREE(str); + } +#endif /* HAVE_UDF_ARGS_T_ANON_UID */ + +#ifdef HAVE_UDF_ARGS_T_ANON_GID + udf_args.anon_gid = gid_nobody; /* default to nobody */ + if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) { + udf_args.anon_gid = a_gid(str, MNTTAB_OPT_GROUP); + XFREE(str); + } +#endif /* HAVE_UDF_ARGS_T_ANON_GID */ + +#ifdef HAVE_UDF_ARGS_T_GMTOFF + udf_args.gmtoff = 0; + if ((str = hasmntstr(&mnt, MNTTAB_OPT_GMTOFF)) != NULL) { + udf_args.gmtoff = a_num(str, MNTTAB_OPT_GMTOFF); + XFREE(str); + } +#endif /* HAVE_UDF_ARGS_T_GMTOFF */ + +#ifdef HAVE_UDF_ARGS_T_SESSIONNR + udf_args.sessionnr = 0; + if ((str = hasmntstr(&mnt, MNTTAB_OPT_SESSIONNR)) != NULL) { + udf_args.sessionnr = a_num(str, MNTTAB_OPT_SESSIONNR); + XFREE(str); + } +#endif /* HAVE_UDF_ARGS_T_SESSIONNR */ + +#ifdef HAVE_UDF_ARGS_T_VERSION +# ifdef UDFMNT_VERSION + udf_args.version = UDFMNT_VERSION; +# endif /* UDFMNT_VERSION */ +#endif /* HAVE_UDF_ARGS_T_VERSION */ + +#ifdef HAVE_UDF_ARGS_T_FSPEC + udf_args.fspec = fs_name; +#endif /* HAVE_UFS_ARGS_T_FSPEC */ + + /* + * Call generic mount routine + */ + return mount_fs(&mnt, flags, (caddr_t)&udf_args, 0, type, 0, NULL, + mnttab_file_name, on_autofs); +} + +static int +udf_mount(am_node *am, mntfs *mf) +{ + int on_autofs; + int error; + + on_autofs = mf->mf_flags & MFF_ON_AUTOFS; + error = mount_udf(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); + if (error) { + errno = error; + plog(XLOG_ERROR, "mount_udf: %m"); + return error; + } + return 0; +} + + +static int +udf_umount(am_node *am, mntfs *mf) +{ + int unmount_flags; + + unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0; + return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags); +} diff --git a/contrib/amd/amd/ops_ufs.c b/contrib/amd/amd/ops_ufs.c index fd82a5cd222..0d8f3068dbe 100644 --- a/contrib/amd/amd/ops_ufs.c +++ b/contrib/amd/amd/ops_ufs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -61,7 +57,11 @@ static int ufs_umount(am_node *am, mntfs *mf); */ am_ops ufs_ops = { +#ifndef __NetBSD__ "ufs", +#else + "ffs", +#endif ufs_match, 0, /* ufs_init */ ufs_mount, @@ -98,7 +98,7 @@ ufs_match(am_opts *fo) /* * Determine magic cookie to put in mtab */ - return strdup(fo->opt_dev); + return xstrdup(fo->opt_dev); } diff --git a/contrib/amd/amd/ops_umapfs.c b/contrib/amd/amd/ops_umapfs.c index 5ba735e39c6..6f9d39d9d5d 100644 --- a/contrib/amd/amd/ops_umapfs.c +++ b/contrib/amd/amd/ops_umapfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/ops_unionfs.c b/contrib/amd/amd/ops_unionfs.c index 73f8d667620..e6286133cbf 100644 --- a/contrib/amd/amd/ops_unionfs.c +++ b/contrib/amd/amd/ops_unionfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/amd/ops_xfs.c b/contrib/amd/amd/ops_xfs.c index e0e740bc0a0..6e1495e295f 100644 --- a/contrib/amd/amd/ops_xfs.c +++ b/contrib/amd/amd/ops_xfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -98,7 +94,7 @@ xfs_match(am_opts *fo) /* * Determine magic cookie to put in mtab */ - return strdup(fo->opt_dev); + return xstrdup(fo->opt_dev); } diff --git a/contrib/amd/amd/opts.c b/contrib/amd/amd/opts.c index a3d35343adc..4bc833a8dd8 100644 --- a/contrib/amd/amd/opts.c +++ b/contrib/amd/amd/opts.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -539,7 +535,7 @@ eval_selectors(char *opts, char *mapkey) char *f; int ret = 0; - o = old_o = strdup(opts); + o = old_o = xstrdup(opts); /* * For each user-specified option @@ -570,7 +566,7 @@ eval_selectors(char *opts, char *mapkey) /* null-terminate the argument */ *arg++ = '\0'; fx = strchr(arg, ')'); - if (!arg || fx == arg) { + if (fx == NULL || fx == arg) { plog(XLOG_USER, "key %s: Malformed function in \"%s\"", mapkey, f); continue; } @@ -606,8 +602,10 @@ eval_selectors(char *opts, char *mapkey) } } else { if (eq[1] == '\0' || eq == f) { - /* misformed selector */ +#ifdef notdef + /* We allow empty assignments */ plog(XLOG_USER, "key %s: Bad selector \"%s\"", mapkey, f); +#endif continue; } } @@ -968,9 +966,7 @@ f_true(char *arg) static void free_op(opt_apply *p, int b) { - if (*p->opt) { - XFREE(*p->opt); - } + XFREE(*p->opt); } @@ -1016,7 +1012,7 @@ normalize_slash(char *p) /* assert(*f == 0 || *f == '/'); */ } while (*f); - *t = 0; /* derived from fix by Steven Glassman */ + *t = '\0'; /* derived from fix by Steven Glassman */ } } @@ -1238,8 +1234,14 @@ expand_op(char *opt, int sel_p) } if (BUFSPACE(ep, vlen+1)) { - xstrlcpy(ep, vptr, vlen+1); + /* + * Don't call xstrlcpy() to truncate a string here. It causes + * spurious xstrlcpy() syslog() errors. Use memcpy() and + * explicitly terminate the string. + */ + memcpy(ep, vptr, vlen+1); ep += vlen; + *ep = '\0'; } else { plog(XLOG_ERROR, EXPAND_ERROR, opt); goto out; @@ -1292,7 +1294,7 @@ out: * Handle common case - no expansion */ if (cp == opt) { - opt = strdup(cp); + opt = xstrdup(cp); } else { /* * Finish off the expansion @@ -1308,7 +1310,7 @@ out: /* * Save the expansion */ - opt = strdup(expbuf); + opt = xstrdup(expbuf); } normalize_slash(opt); @@ -1372,6 +1374,45 @@ free_opts(am_opts *fo) apply_opts(free_op, to_free, FALSE); } +am_opts * +copy_opts(am_opts *old) +{ + am_opts *newopts; + newopts = CALLOC(struct am_opts); + +#define _AM_OPT_COPY(field) do { \ + if (old->field) \ + newopts->field = xstrdup(old->field); \ + } while (0) + + _AM_OPT_COPY(fs_glob); + _AM_OPT_COPY(fs_local); + _AM_OPT_COPY(fs_mtab); + _AM_OPT_COPY(opt_dev); + _AM_OPT_COPY(opt_delay); + _AM_OPT_COPY(opt_dir); + _AM_OPT_COPY(opt_fs); + _AM_OPT_COPY(opt_group); + _AM_OPT_COPY(opt_mount); + _AM_OPT_COPY(opt_opts); + _AM_OPT_COPY(opt_remopts); + _AM_OPT_COPY(opt_pref); + _AM_OPT_COPY(opt_cache); + _AM_OPT_COPY(opt_rfs); + _AM_OPT_COPY(opt_rhost); + _AM_OPT_COPY(opt_sublink); + _AM_OPT_COPY(opt_type); + _AM_OPT_COPY(opt_mount_type); + _AM_OPT_COPY(opt_unmount); + _AM_OPT_COPY(opt_umount); + _AM_OPT_COPY(opt_user); + _AM_OPT_COPY(opt_maptype); + _AM_OPT_COPY(opt_cachedir); + _AM_OPT_COPY(opt_addopts); + + return newopts; +} + /* * Expand selectors (variables that cannot be assigned to or overridden) diff --git a/contrib/amd/amd/readdir.c b/contrib/amd/amd/readdir.c index 49f89943cfb..69be7a71d65 100644 --- a/contrib/amd/amd/readdir.c +++ b/contrib/amd/amd/readdir.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -42,6 +38,7 @@ */ +#include #ifdef HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ @@ -109,14 +106,14 @@ make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable plog(XLOG_DEBUG, "make_entry_chain: mp is (NULL)"); return retval; } - mf = mp->am_mnt; + mf = mp->am_al->al_mnt; if (!mf) { - plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt is (NULL)"); + plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_mnt is (NULL)"); return retval; } mmp = (mnt_map *) mf->mf_private; if (!mmp) { - plog(XLOG_DEBUG, "make_entry_chain: mp->am_mnt->mf_private is (NULL)"); + plog(XLOG_DEBUG, "make_entry_chain: mp->am_al->al_mnt->mf_private is (NULL)"); return retval; } @@ -171,7 +168,7 @@ make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable /* out of space */ plog(XLOG_DEBUG, "make_entry_chain: no more space in chain"); if (num_entries > 0) { - chain[num_entries - 1].ne_nextentry = 0; + chain[num_entries - 1].ne_nextentry = NULL; retval = &chain[0]; } return retval; @@ -192,7 +189,7 @@ make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable /* terminate chain */ if (num_entries > 0) { - chain[num_entries - 1].ne_nextentry = 0; + chain[num_entries - 1].ne_nextentry = NULL; retval = &chain[0]; } @@ -205,7 +202,7 @@ make_entry_chain(am_node *mp, const nfsentry *current_chain, int fully_browsable static int amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count, int fully_browsable) { - u_int gen = *(u_int *) cookie; + u_int gen = *(u_int *) (uintptr_t) cookie; int chain_length, i; static nfsentry *te, *te_next; static int j; @@ -225,7 +222,7 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry * * to be returned in a single packet. If it isn't (which would be * fairly unbelievable) then tough. */ - dlog("amfs_readdir_browsable: default search"); + dlog("%s: default search", __func__); /* * Check for enough room. This is extremely approximate but is more * than enough space. Really need 2 times: @@ -264,8 +261,8 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry * ep[1].ne_fileid = mp->am_gen; ep[1].ne_name = ".."; - ep[1].ne_nextentry = 0; - *(u_int *) ep[1].ne_cookie = DOT_DOT_COOKIE; + ep[1].ne_nextentry = NULL; + (void)memcpy(ep[1].ne_cookie, &dotdotcookie, sizeof(dotdotcookie)); /* * If map is browsable, call a function make_entry_chain() to construct @@ -313,12 +310,12 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry * return 0; } /* end of "if (gen == 0)" statement */ - dlog("amfs_readdir_browsable: real child"); + dlog("%s: real child", __func__); if (gen == DOT_DOT_COOKIE) { - dlog("amfs_readdir_browsable: End of readdir in %s", mp->am_path); + dlog("%s: End of readdir in %s", __func__, mp->am_path); dp->dl_eof = TRUE; - dp->dl_entries = 0; + dp->dl_entries = NULL; return 0; } @@ -332,7 +329,7 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry * te = te_next; /* reset 'te' from last saved te_next */ if (!te) { /* another indicator of end of readdir */ - dp->dl_entries = 0; + dp->dl_entries = NULL; return 0; } /* @@ -365,29 +362,14 @@ amfs_readdir_browsable(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry * return 0; } - -/* - * This readdir function which call a special version of it that allows - * browsing if browsable_dirs=yes was set on the map. - */ -int -amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) +static int +amfs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, u_int count) { - u_int gen = *(u_int *) cookie; + u_int gen = *(u_int *) (uintptr_t) cookie; am_node *xp; - mntent_t mnt; dp->dl_eof = FALSE; /* assume readdir not done */ - /* check if map is browsable */ - if (mp->am_mnt && mp->am_mnt->mf_mopts) { - mnt.mnt_opts = mp->am_mnt->mf_mopts; - if (amu_hasmntopt(&mnt, "fullybrowsable")) - return amfs_readdir_browsable(mp, cookie, dp, ep, count, TRUE); - if (amu_hasmntopt(&mnt, "browsable")) - return amfs_readdir_browsable(mp, cookie, dp, ep, count, FALSE); - } - /* when gen is 0, we start reading from the beginning of the directory */ if (gen == 0) { /* @@ -398,7 +380,7 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep * to be returned in a single packet. If it isn't (which would be * fairly unbelievable) then tough. */ - dlog("amfs_generic_readdir: default search"); + dlog("%s: default search", __func__); /* * Check for enough room. This is extremely approximate but is more * than enough space. Really need 2 times: @@ -407,8 +389,11 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep * 4byte name length * 4byte name * plus the dirlist structure */ - if (count < (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp)))) +#define NEEDROOM (2 * (2 * (sizeof(*ep) + sizeof("..") + 4) + sizeof(*dp))) + if (count < NEEDROOM) { + dlog("%s: not enough room %u < %zu", __func__, count, NEEDROOM); return EINVAL; + } xp = next_nonerror_node(mp->am_child); dp->dl_entries = ep; @@ -425,8 +410,9 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep else ep[1].ne_fileid = mp->am_gen; ep[1].ne_name = ".."; - ep[1].ne_nextentry = 0; - *(u_int *) ep[1].ne_cookie = (xp ? xp->am_gen : DOT_DOT_COOKIE); + ep[1].ne_nextentry = NULL; + (void)memcpy(ep[1].ne_cookie, (xp ? &xp->am_gen : &dotdotcookie), + sizeof(dotdotcookie)); if (!xp) dp->dl_eof = TRUE; /* by default assume readdir done */ @@ -443,12 +429,12 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep } return 0; } - dlog("amfs_generic_readdir: real child"); + dlog("%s: real child", __func__); if (gen == DOT_DOT_COOKIE) { - dlog("amfs_generic_readdir: End of readdir in %s", mp->am_path); + dlog("%s: End of readdir in %s", __func__, mp->am_path); dp->dl_eof = TRUE; - dp->dl_entries = 0; + dp->dl_entries = NULL; if (amuDebug(D_READDIR)) plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n"); return 0; @@ -491,7 +477,7 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep } } while (todo > 0); - ep->ne_nextentry = 0; + ep->ne_nextentry = NULL; if (amuDebug(D_READDIR)) { nfsentry *ne; @@ -507,3 +493,460 @@ amfs_generic_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep } return ESTALE; } + +/* + * Search a chain for an entry with some name. + */ +static int +key_already_in_chain3(char *keyname, const am_entry3 *chain) +{ + const am_entry3 *tmpchain = chain; + + while (tmpchain) { + if (keyname && tmpchain->name && STREQ(keyname, tmpchain->name)) + return 1; + tmpchain = tmpchain->nextentry; + } + + return 0; +} + +/* + * Create a chain of entries which are not linked. + */ +static am_entry3 * +make_entry_chain3(am_node *mp, const am_entry3 *current_chain, int fully_browsable) +{ + static uint64 last_cookie = (uint64) 2; /* monotonically increasing */ + static am_entry3 chain[MAX_CHAIN]; + static int max_entries = MAX_CHAIN; + char *key; + int num_entries = 0, i; + u_int preflen = 0; + am_entry3 *retval = (am_entry3 *) NULL; + mntfs *mf; + mnt_map *mmp; + + if (!mp) { + plog(XLOG_DEBUG, "make_entry_chain3: mp is (NULL)"); + return retval; + } + mf = mp->am_al->al_mnt; + if (!mf) { + plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_mnt is (NULL)"); + return retval; + } + mmp = (mnt_map *) mf->mf_private; + if (!mmp) { + plog(XLOG_DEBUG, "make_entry_chain3: mp->am_al->al_mnt->mf_private is (NULL)"); + return retval; + } + + if (mp->am_pref) + preflen = strlen(mp->am_pref); + + /* iterate over keys */ + for (i = 0; i < NKVHASH; i++) { + kv *k; + for (k = mmp->kvhash[i]; k ; k = k->next) { + + /* + * Skip unwanted entries which are either not real entries or + * very difficult to interpret (wildcards...) This test needs + * lots of improvement. Any takers? + */ + key = k->key; + if (!key) + continue; + + /* Skip '/defaults' */ + if (STREQ(key, "/defaults")) + continue; + + /* Skip '*' */ + if (!fully_browsable && strchr(key, '*')) + continue; + + /* + * If the map has a prefix-string then check if the key starts with + * this string, and if it does, skip over this prefix. If it has a + * prefix and it doesn't match the start of the key, skip it. + */ + if (preflen) { + if (preflen > strlen(key)) + continue; + if (!NSTREQ(key, mp->am_pref, preflen)) + continue; + key += preflen; + } + + /* no more '/' are allowed, unless browsable_dirs=full was used */ + if (!fully_browsable && strchr(key, '/')) + continue; + + /* no duplicates allowed */ + if (key_already_in_chain3(key, current_chain)) + continue; + + /* fill in a cell and link the entry */ + if (num_entries >= max_entries) { + /* out of space */ + plog(XLOG_DEBUG, "make_entry_chain3: no more space in chain"); + if (num_entries > 0) { + chain[num_entries - 1].nextentry = NULL; + retval = &chain[0]; + } + return retval; + } + + /* we have space. put entry in next cell */ + ++last_cookie; + chain[num_entries].fileid = last_cookie; + chain[num_entries].cookie = last_cookie; + chain[num_entries].name = key; + if (num_entries < max_entries - 1) { /* link to next one */ + chain[num_entries].nextentry = &chain[num_entries + 1]; + } + ++num_entries; + } /* end of "while (k)" */ + } /* end of "for (i ... NKVHASH ..." */ + + /* terminate chain */ + if (num_entries > 0) { + chain[num_entries - 1].nextentry = NULL; + retval = &chain[0]; + } + + return retval; +} + +static size_t needroom3(void) +{ + /* + * Check for enough room. This is extremely approximate but should + * be enough space. Really need 2 times: + * (8byte fileid + * 8byte cookie + * 8byte name pointer + * 8byte next entry addres) = sizeof(am_entry3) + * 2byte name + 1byte terminator + * plus the size of the am_dirlist3 structure */ + return ((2 * ((sizeof(am_entry3) + sizeof("..") + 1))) + sizeof(am_dirlist3)); +} + +/* This one is called only if map is browsable */ +static int +amfs_readdir3_browsable(am_node *mp, am_cookie3 cookie, + am_dirlist3 *dp, am_entry3 *ep, u_int count, + int fully_browsable) +{ + uint64 gen = *(uint64 *) (uintptr_t) cookie; + int chain_length, i; + static am_entry3 *te, *te_next; + static int j; + + dp->eof = FALSE; /* assume readdir not done */ + + if (amuDebug(D_READDIR)) + plog(XLOG_DEBUG, "amfs_readdir3_browsable gen=%lu, count=%d", (long unsigned) gen, count); + + if (gen == 0) { + size_t needed = needroom3(); + /* + * In the default instance (which is used to start a search) we return + * "." and "..". + * + * This assumes that the count is big enough to allow both "." and ".." + * to be returned in a single packet. If it isn't (which would be + * fairly unbelievable) then tough. + */ + dlog("%s: default search", __func__); + + if (count < needed) { + dlog("%s: not enough room %u < %zu", __func__, count, needed); + return EINVAL; + } + + /* + * compute # of entries to send in this chain. + * heuristics: 128 bytes per entry. + * This is too much probably, but it seems to work better because + * of the re-entrant nature of nfs_readdir, and esp. on systems + * like OpenBSD 2.2. + */ + chain_length = count / 128; + + /* reset static state counters */ + te = te_next = NULL; + + dp->entries = ep; + + /* construct "." */ + ep[0].fileid = mp->am_gen; + ep[0].name = "."; + ep[0].nextentry = &ep[1]; + ep[0].cookie = 0; + + /* construct ".." */ + if (mp->am_parent) + ep[1].fileid = mp->am_parent->am_gen; + else + ep[1].fileid = mp->am_gen; + + ep[1].name = ".."; + ep[1].nextentry = NULL; + ep[1].cookie = dotdotcookie; + + /* + * If map is browsable, call a function make_entry_chain() to construct + * a linked list of unmounted keys, and return it. Then link the chain + * to the regular list. Get the chain only once, but return + * chunks of it each time. + */ + te = make_entry_chain3(mp, dp->entries, fully_browsable); + if (!te) + return 0; + if (amuDebug(D_READDIR)) { + am_entry3 *ne; + for (j = 0, ne = te; ne; ne = ne->ne_nextentry) + plog(XLOG_DEBUG, "gen1 key %4d \"%s\"", j++, ne->ne_name); + } + + /* return only "chain_length" entries */ + te_next = te; + for (i=1; inextentry; + if (!te_next) + break; + } + if (te_next) { + am_entry3 *te_saved = te_next->nextentry; + te_next->nextentry = NULL; /* terminate "te" chain */ + te_next = te_saved; /* save rest of "te" for next iteration */ + dp->eof = FALSE; /* tell readdir there's more */ + } else { + dp->eof = TRUE; /* tell readdir that's it */ + } + ep[1].nextentry = te; /* append this chunk of "te" chain */ + if (amuDebug(D_READDIR)) { + am_entry3 *ne; + for (j = 0, ne = te; ne; ne = ne->ne_nextentry) + plog(XLOG_DEBUG, "gen2 key %4d \"%s\"", j++, ne->name); + for (j = 0, ne = ep; ne; ne = ne->ne_nextentry) { + plog(XLOG_DEBUG, "gen2+ key %4d \"%s\" fi=%lu ck=%lu", + j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie); + } + plog(XLOG_DEBUG, "EOF is %d", dp->eof); + } + return 0; + } /* end of "if (gen == 0)" statement */ + + dlog("%s: real child", __func__); + + if (gen == DOT_DOT_COOKIE) { + dlog("%s: End of readdir in %s", __func__, mp->am_path); + dp->eof = TRUE; + dp->entries = NULL; + return 0; + } + + /* + * If browsable directories, then continue serving readdir() with another + * chunk of entries, starting from where we left off (when gen was equal + * to 0). Once again, assume last chunk served to readdir. + */ + dp->eof = TRUE; + dp->entries = ep; + + te = te_next; /* reset 'te' from last saved te_next */ + if (!te) { /* another indicator of end of readdir */ + dp->entries = NULL; + return 0; + } + /* + * compute # of entries to send in this chain. + * heuristics: 128 bytes per entry. + */ + chain_length = count / 128; + + /* return only "chain_length" entries */ + for (i = 1; i < chain_length; ++i) { + te_next = te_next->nextentry; + if (!te_next) + break; + } + if (te_next) { + am_entry3 *te_saved = te_next->nextentry; + te_next->nextentry = NULL; /* terminate "te" chain */ + te_next = te_saved; /* save rest of "te" for next iteration */ + dp->eof = FALSE; /* tell readdir there's more */ + } + ep = te; /* send next chunk of "te" chain */ + dp->entries = ep; + if (amuDebug(D_READDIR)) { + am_entry3 *ne; + plog(XLOG_DEBUG, + "entries=%p, te_next=%p, eof=%d", dp->entries, te_next, dp->eof); + for (ne = te; ne; ne = ne->nextentry) + plog(XLOG_DEBUG, "gen3 key %4d \"%s\"", j++, ne->name); + } + return 0; +} + +static int +amfs_readdir3(am_node *mp, am_cookie3 cookie, + am_dirlist3 *dp, am_entry3 *ep, u_int count) +{ + uint64 gen = *(uint64 *) (uintptr_t) cookie; + am_node *xp; + + if (amuDebug(D_READDIR)) + plog(XLOG_DEBUG, "amfs_readdir3 gen=%lu, count=%d", (long unsigned) gen, count); + + dp->eof = FALSE; /* assume readdir not done */ + + /* when gen is 0, we start reading from the beginning of the directory */ + if (gen == 0) { + size_t needed = needroom3(); + /* + * In the default instance (which is used to start a search) we return + * "." and "..". + * + * This assumes that the count is big enough to allow both "." and ".." + * to be returned in a single packet. If it isn't (which would be + * fairly unbelievable) then tough. + */ + dlog("%s: default search", __func__); + + if (count < needed) { + dlog("%s: not enough room %u < %zu", __func__, count, needed); + return EINVAL; + } + + xp = next_nonerror_node(mp->am_child); + dp->entries = ep; + + /* construct "." */ + ep[0].fileid = mp->am_gen; + ep[0].name = "."; + ep[0].cookie = 0; + ep[0].nextentry = &ep[1]; + + /* construct ".." */ + if (mp->am_parent) + ep[1].fileid = mp->am_parent->am_gen; + else + ep[1].fileid = mp->am_gen; + ep[1].name = ".."; + ep[1].nextentry = NULL; + ep[1].cookie = (xp ? xp->am_gen : dotdotcookie); + + if (!xp) + dp->eof = TRUE; /* by default assume readdir done */ + + if (amuDebug(D_READDIR)) { + am_entry3 *ne; + int j; + for (j = 0, ne = ep; ne; ne = ne->nextentry) { + plog(XLOG_DEBUG, "gen1 key %4d \"%s\" fi=%lu ck=%lu", + j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie); + } + } + return 0; + } + dlog("%s: real child", __func__); + + if (gen == (uint64) DOT_DOT_COOKIE) { + dlog("%s: End of readdir in %s", __func__, mp->am_path); + dp->eof = TRUE; + dp->entries = NULL; + if (amuDebug(D_READDIR)) + plog(XLOG_DEBUG, "end of readdir eof=TRUE, dl_entries=0\n"); + return 0; + } + + /* non-browsable directories code */ + xp = mp->am_child; + while (xp && xp->am_gen != gen) + xp = xp->am_osib; + + if (xp) { + int nbytes = count / 2; /* conservative */ + int todo = MAX_READDIR_ENTRIES; + + dp->entries = ep; + do { + am_node *xp_next = next_nonerror_node(xp->am_osib); + + if (xp_next) { + ep->cookie = xp_next->am_gen; + } else { + ep->cookie = (uint64) dotdotcookie; + dp->eof = TRUE; + } + + ep->fileid = xp->am_gen; + ep->name = xp->am_name; + nbytes -= sizeof(*ep) + 1; + if (xp->am_name) + nbytes -= strlen(xp->am_name); + + xp = xp_next; + + if (nbytes > 0 && !dp->dl_eof && todo > 1) { + ep->nextentry = ep + 1; + ep++; + --todo; + } else { + todo = 0; + } + } while (todo > 0); + + ep->nextentry = NULL; + + if (amuDebug(D_READDIR)) { + am_entry3 *ne; + int j; + for (j = 0, ne = ep; ne; ne = ne->nextentry) { + plog(XLOG_DEBUG, "gen2 key %4d \"%s\" fi=%lu ck=%lu", + j++, ne->name, (long unsigned) ne->fileid, (long unsigned) ne->cookie); + } + } + return 0; + } + return ESTALE; +} + +/* + * This readdir function which call a special version of it that allows + * browsing if browsable_dirs=yes was set on the map. + */ +int +amfs_generic_readdir(am_node *mp, voidp cookie, voidp dp, voidp ep, u_int count) +{ + int browsable, full; + + /* check if map is browsable */ + browsable = 0; + if (mp->am_al->al_mnt && mp->am_al->al_mnt->mf_mopts) { + mntent_t mnt; + mnt.mnt_opts = mp->am_al->al_mnt->mf_mopts; + if (amu_hasmntopt(&mnt, "fullybrowsable")) + browsable = 2; + else if (amu_hasmntopt(&mnt, "browsable")) + browsable = 1; + } + full = (browsable == 2); + + if (nfs_dispatcher == nfs_program_2) { + if (browsable) + return amfs_readdir_browsable(mp, cookie, dp, ep, count, full); + else + return amfs_readdir(mp, cookie, dp, ep, count); + } else { + if (browsable) + return amfs_readdir3_browsable(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count, full); + else + return amfs_readdir3(mp, (am_cookie3) (uintptr_t) cookie, dp, ep, count); + } +} diff --git a/contrib/amd/amd/restart.c b/contrib/amd/amd/restart.c index 4f71e381e25..de38bcfb274 100644 --- a/contrib/amd/amd/restart.c +++ b/contrib/amd/amd/restart.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -59,21 +55,21 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops) * Partially fake up an opts structure */ memset(&mo, 0, sizeof(mo)); - mo.opt_rhost = 0; - mo.opt_rfs = 0; + mo.opt_rhost = NULL; + mo.opt_rfs = NULL; cp = strchr(me->mnt_fsname, ':'); if (cp) { *cp = '\0'; - mo.opt_rhost = strdup(me->mnt_fsname); - mo.opt_rfs = strdup(cp + 1); + mo.opt_rhost = xstrdup(me->mnt_fsname); + mo.opt_rfs = xstrdup(cp + 1); *cp = ':'; } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { /* * Hacky workaround for mnttab NFS entries that only list the server */ plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname); - mo.opt_rhost = strdup(me->mnt_fsname); - mo.opt_rfs = strdup("/"); + mo.opt_rhost = xstrdup(me->mnt_fsname); + mo.opt_rfs = xstrdup("/"); me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/"); } mo.opt_fs = me->mnt_dir; @@ -87,7 +83,6 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops) if (mf->mf_refc == 1) { mf->mf_flags |= MFF_RESTART | MFF_MOUNTED; mf->mf_error = 0; /* Already mounted correctly */ - mf->mf_fo = 0; /* * Only timeout non-NFS entries */ @@ -110,10 +105,8 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops) /* * Clean up mo */ - if (mo.opt_rhost) - XFREE(mo.opt_rhost); - if (mo.opt_rfs) - XFREE(mo.opt_rfs); + XFREE(mo.opt_rhost); + XFREE(mo.opt_rfs); } @@ -140,7 +133,7 @@ restart(void) mlp; mlp = mlp->mnext) { mntent_t *me = mlp->mnt; - am_ops *fs_ops = 0; + am_ops *fs_ops = NULL; if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { /* @@ -203,7 +196,7 @@ restart_automounter_nodes(void) mlp; mlp = mlp->mnext) { mntent_t *me = mlp->mnt; - am_ops *fs_ops = 0; + am_ops *fs_ops = NULL; char *colon; long pid; u_short port; @@ -263,7 +256,8 @@ restart_automounter_nodes(void) if (old_ports[i] == 0) { int soNFS; SVCXPRT *nfsxprt; - if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) { + if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_dispatcher, + get_nfs_dispatcher_version(nfs_dispatcher)) != 0) { plog(XLOG_WARNING, "Can't bind to port %u", port); goto give_up; } diff --git a/contrib/amd/amd/rpc_fwd.c b/contrib/amd/amd/rpc_fwd.c index b3c8be4fa3b..757b4371024 100644 --- a/contrib/amd/amd/rpc_fwd.c +++ b/contrib/amd/amd/rpc_fwd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -94,7 +90,7 @@ static rpc_forward * fwd_alloc(void) { time_t now = clocktime(NULL); - rpc_forward *p = 0, *p2; + rpc_forward *p = NULL, *p2; /* * First search for an existing expired one. @@ -183,7 +179,7 @@ fwd_init(void) /* * Some things we talk to require a priv port - so make one here */ - if (bind_resv_port(fwd_sock, (u_short *) 0) < 0) + if (bind_resv_port(fwd_sock, (u_short *) NULL) < 0) plog(XLOG_ERROR, "can't bind privileged port (rpc_fwd)"); if (fcntl(fwd_sock, F_SETFL, FNDELAY) < 0 diff --git a/contrib/amd/amd/sched.c b/contrib/amd/amd/sched.c index 8efe57a3ab8..5c816b4c205 100644 --- a/contrib/amd/amd/sched.c +++ b/contrib/amd/amd/sched.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -262,7 +258,7 @@ sigchld(int sig) #ifdef HAVE_WAITPID while ((pid = waitpid((pid_t) -1, &w, WNOHANG)) > 0) { #else /* not HAVE_WAITPID */ - while ((pid = wait3( &w, WNOHANG, (struct rusage *) 0)) > 0) { + while ((pid = wait3( &w, WNOHANG, (struct rusage *) NULL)) > 0) { #endif /* not HAVE_WAITPID */ pjob *p, *p2; diff --git a/contrib/amd/amd/srvr_amfs_auto.c b/contrib/amd/amd/srvr_amfs_auto.c index 4742cf6f750..44b130254d3 100644 --- a/contrib/amd/amd/srvr_amfs_auto.c +++ b/contrib/amd/amd/srvr_amfs_auto.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -69,14 +65,14 @@ amfs_generic_find_srvr(mntfs *mf) if (!fs) { fs = ALLOC(struct fserver); fs->fs_refc = 0; - fs->fs_host = strdup("localhost"); - fs->fs_ip = 0; + fs->fs_host = xstrdup("localhost"); + fs->fs_ip = NULL; fs->fs_cid = 0; fs->fs_pinger = AM_PINGER; fs->fs_flags = FSF_VALID | FSF_PING_UNINIT; fs->fs_type = "local"; - fs->fs_private = 0; - fs->fs_prfree = 0; + fs->fs_private = NULL; + fs->fs_prfree = NULL; ins_que(&fs->fs_q, &amfs_auto_srvr_list); @@ -135,8 +131,7 @@ timeout_srvr(voidp v) /* * Free the net address */ - if (fs->fs_ip) - XFREE(fs->fs_ip); + XFREE(fs->fs_ip); /* * Free the host name. diff --git a/contrib/amd/amd/srvr_nfs.c b/contrib/amd/amd/srvr_nfs.c index 0c74a658e5e..b7c852c9e1d 100644 --- a/contrib/amd/amd/srvr_nfs.c +++ b/contrib/amd/amd/srvr_nfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -75,6 +71,7 @@ typedef struct nfs_private { u_short np_mountd; /* Mount daemon port number */ char np_mountd_inval; /* Port *may* be invalid */ + /* 'Y' invalid, 'N' valid, 'P' permanent */ int np_ping; /* Number of failed ping attempts */ time_t np_ttl; /* Time when server is thought dead */ int np_xid; /* RPC transaction id for pings */ @@ -88,7 +85,9 @@ qelem nfs_srvr_list = {&nfs_srvr_list, &nfs_srvr_list}; static int global_xid; /* For NFS pings */ #define XID_ALLOC() (++global_xid) -#ifdef HAVE_FS_NFS3 +#if defined(HAVE_FS_NFS4) +# define NUM_NFS_VERS 3 +#elif defined(HAVE_FS_NFS3) # define NUM_NFS_VERS 2 #else /* not HAVE_FS_NFS3 */ # define NUM_NFS_VERS 1 @@ -124,8 +123,8 @@ flush_srvr_nfs_cache(fserver *fs) ITER(fs2, fserver, &nfs_srvr_list) { if (fs == NULL || fs == fs2) { nfs_private *np = (nfs_private *) fs2->fs_private; - if (np) { - np->np_mountd_inval = TRUE; + if (np && np->np_mountd_inval != 'P') { + np->np_mountd_inval = 'Y'; np->np_error = -1; } } @@ -147,9 +146,9 @@ create_ping_payload(u_long nfs_version) */ if (nfs_version == 0) { nfs_version = NFS_VERSION; - plog(XLOG_WARNING, "create_ping_payload: nfs_version = 0, changed to 2"); + plog(XLOG_WARNING, "%s: nfs_version = 0, changed to 2", __func__); } else - plog(XLOG_INFO, "create_ping_payload: nfs_version: %d", (int) nfs_version); + plog(XLOG_INFO, "%s: nfs_version: %d", __func__, (int) nfs_version); rpc_msg_init(&ping_msg, NFS_PROGRAM, nfs_version, NFSPROC_NULL); @@ -164,6 +163,7 @@ create_ping_payload(u_long nfs_version) if (!xdr_callmsg(&ping_xdr, &ping_msg)) { plog(XLOG_ERROR, "Couldn't create ping RPC message"); going_down(3); + return; } /* * Find out how long it is @@ -184,7 +184,7 @@ static void got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, voidp idv, int done) { fserver *fs2 = (fserver *) idv; - fserver *fs = 0; + fserver *fs = NULL; /* * Find which fileserver we are talking about @@ -207,7 +207,7 @@ got_portmap(voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, * network ordering. */ np->np_mountd = htons((u_short) port); - np->np_mountd_inval = FALSE; + np->np_mountd_inval = 'N'; np->np_error = 0; } else { dlog("Error fetching port for mountd on %s", fs->fs_host); @@ -291,9 +291,9 @@ recompute_portmap(fserver *fs) } if (fs->fs_version == 0) - plog(XLOG_WARNING, "recompute_portmap: nfs_version = 0 fixed"); + plog(XLOG_WARNING, "%s: nfs_version = 0 fixed", __func__); - plog(XLOG_INFO, "recompute_portmap: NFS version %d on %s", + plog(XLOG_INFO, "%s: NFS version %d on %s", __func__, (int) fs->fs_version, fs->fs_host); #ifdef HAVE_FS_NFS3 if (fs->fs_version == NFS_VERSION3) @@ -311,6 +311,7 @@ int get_mountd_port(fserver *fs, u_short *port, wchan_t wchan) { int error = -1; + if (FSRV_ISDOWN(fs)) return EWOULDBLOCK; @@ -329,10 +330,18 @@ get_mountd_port(fserver *fs, u_short *port, wchan_t wchan) * indication that the mountd may be invalid, not * that it is known to be invalid. */ - if (np->np_mountd_inval) + switch (np->np_mountd_inval) { + case 'Y': recompute_portmap(fs); - else - np->np_mountd_inval = TRUE; + break; + case 'N': + np->np_mountd_inval = 'Y'; + break; + case 'P': + break; + default: + abort(); + } } if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) { /* @@ -425,7 +434,7 @@ nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockad /* * Recompute portmap information if not known */ - if (np->np_mountd_inval) + if (np->np_mountd_inval == 'Y') recompute_portmap(fs); found_map++; @@ -454,7 +463,7 @@ check_fs_addr_change(fserver *fs) sizeof(fs->fs_ip->sin_addr)) == 0) return; /* if got here: downed server changed IP address */ - old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr)); + old_ipaddr = xstrdup(inet_ntoa(fs->fs_ip->sin_addr)); memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr)); new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */ plog(XLOG_WARNING, "EZK: down fileserver %s changed ip: %s -> %s", @@ -474,7 +483,7 @@ check_fs_addr_change(fserver *fs) #if 0 flush_nfs_fhandle_cache(fs); /* done in caller: nfs_keepalive_timeout */ /* XXX: need to purge nfs_private so that somehow it will get re-initialized? */ -#endif +#endif /* 0 */ } @@ -562,22 +571,24 @@ nfs_keepalive(voidp v) int error; nfs_private *np = (nfs_private *) fs->fs_private; int fstimeo = -1; + int fs_version = nfs_valid_version(gopt.nfs_vers_ping) && + gopt.nfs_vers_ping < fs->fs_version ? gopt.nfs_vers_ping : fs->fs_version; /* * Send an NFS ping to this node */ - if (ping_len[fs->fs_version - NFS_VERSION] == 0) - create_ping_payload(fs->fs_version); + if (ping_len[fs_version - NFS_VERSION] == 0) + create_ping_payload(fs_version); /* * Queue the packet... */ error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid), - ping_buf[fs->fs_version - NFS_VERSION], - ping_len[fs->fs_version - NFS_VERSION], + ping_buf[fs_version - NFS_VERSION], + ping_len[fs_version - NFS_VERSION], fs->fs_ip, - (struct sockaddr_in *) 0, + (struct sockaddr_in *) NULL, (voidp) ((long) np->np_xid), /* cast needed for 64-bit archs */ nfs_keepalive_callback); @@ -673,7 +684,7 @@ start_nfs_pings(fserver *fs, int pingval) fserver * find_nfs_srvr(mntfs *mf) { - char *host = mf->mf_fo->opt_rhost; + char *host; fserver *fs; int pingval; mntent_t mnt; @@ -687,6 +698,11 @@ find_nfs_srvr(mntfs *mf) int nfs_port_opt = 0; int fserver_is_down = 0; + if (mf->mf_fo == NULL) { + plog(XLOG_ERROR, "%s: NULL mf_fo", __func__); + return NULL; + } + host = mf->mf_fo->opt_rhost; /* * Get ping interval from mount options. * Current only used to decide whether pings @@ -702,7 +718,8 @@ find_nfs_srvr(mntfs *mf) */ nfs_version = NFS_VERSION; nfs_proto = "udp"; - plog(XLOG_WARNING, "find_nfs_srvr: NFS mount failed, trying again with NFSv2/UDP"); + plog(XLOG_WARNING, "%s: NFS mount failed, trying again with NFSv2/UDP", + __func__); mf->mf_flags &= ~MFF_NFS_SCALEDOWN; } else { /* @@ -742,12 +759,13 @@ find_nfs_srvr(mntfs *mf) /* check if we've globally overridden the NFS version/protocol */ if (gopt.nfs_vers) { nfs_version = gopt.nfs_vers; - plog(XLOG_INFO, "find_nfs_srvr: force NFS version to %d", + plog(XLOG_INFO, "%s: force NFS version to %d", __func__, (int) nfs_version); } if (gopt.nfs_proto) { nfs_proto = gopt.nfs_proto; - plog(XLOG_INFO, "find_nfs_srvr: force NFS protocol transport to %s", nfs_proto); + plog(XLOG_INFO, "%s: force NFS protocol transport to %s", __func__, + nfs_proto); } } @@ -769,7 +787,7 @@ find_nfs_srvr(mntfs *mf) if (hp) { switch (hp->h_addrtype) { case AF_INET: - ip = ALLOC(struct sockaddr_in); + ip = CALLOC(struct sockaddr_in); memset((voidp) ip, 0, sizeof(*ip)); /* as per POSIX, sin_len need not be set (used internally by kernel) */ ip->sin_family = AF_INET; @@ -795,8 +813,7 @@ find_nfs_srvr(mntfs *mf) STREQ(host, fs->fs_host)) { plog(XLOG_WARNING, "fileserver %s is already hung - not running NFS proto/version discovery", host); fs->fs_refc++; - if (ip) - XFREE(ip); + XFREE(ip); return fs; } } @@ -821,10 +838,12 @@ find_nfs_srvr(mntfs *mf) plog(XLOG_INFO, "%s option used, NOT contacting the portmapper on %s", MNTTAB_OPT_PUBLIC, host); /* - * Prefer NFSv3/tcp if the client supports it (cf. RFC 2054, 7). + * Prefer NFSv4/tcp if the client supports it (cf. RFC 2054, 7). */ if (!nfs_version) { -#ifdef HAVE_FS_NFS3 +#if defined(HAVE_FS_NFS4) + nfs_version = NFS_VERSION4; +#elif defined(HAVE_FS_NFS3) nfs_version = NFS_VERSION3; #else /* not HAVE_FS_NFS3 */ nfs_version = NFS_VERSION; @@ -833,11 +852,11 @@ find_nfs_srvr(mntfs *mf) (int) nfs_version); } if (!nfs_proto) { -#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) +#if defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4) nfs_proto = "tcp"; -#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */ +#else /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4) */ nfs_proto = "udp"; -#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) */ +#endif /* not defined(MNTTAB_OPT_PROTO) || defined(HAVE_FS_NFS3) || defined(HAVE_FS_NFS4) */ plog(XLOG_INFO, "No NFS protocol transport specified, will use %s", nfs_proto); } @@ -849,7 +868,8 @@ find_nfs_srvr(mntfs *mf) */ if (check_pmap_up(host, ip)) { if (nfs_proto) { - best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto); + best_nfs_version = get_nfs_version(host, ip, nfs_version, nfs_proto, + gopt.nfs_vers); nfs_port = ip->sin_port; } #ifdef MNTTAB_OPT_PROTO @@ -858,8 +878,8 @@ find_nfs_srvr(mntfs *mf) char **p; for (p = protocols; *p; p++) { - proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p); - + proto_nfs_version = get_nfs_version(host, ip, nfs_version, *p, + gopt.nfs_vers); if (proto_nfs_version > best_nfs_version) { best_nfs_version = proto_nfs_version; nfs_proto = *p; @@ -908,8 +928,8 @@ find_nfs_srvr(mntfs *mf) if (!nfs_port) nfs_port = htons(NFS_PORT); - dlog("find_nfs_srvr: using port %d for nfs on %s", - (int) ntohs(nfs_port), host); + dlog("%s: using port %d for nfs on %s", __func__, + (int) ntohs(nfs_port), host); ip->sin_port = nfs_port; no_dns: @@ -935,7 +955,7 @@ no_dns: sizeof(fs->fs_ip->sin_addr)) != 0) { struct in_addr ia; char *old_ipaddr, *new_ipaddr; - old_ipaddr = strdup(inet_ntoa(fs->fs_ip->sin_addr)); + old_ipaddr = xstrdup(inet_ntoa(fs->fs_ip->sin_addr)); memmove((voidp) &ia, (voidp) hp->h_addr, sizeof(struct in_addr)); new_ipaddr = inet_ntoa(ia); /* ntoa uses static buf */ plog(XLOG_WARNING, "fileserver %s changed ip: %s -> %s", @@ -962,24 +982,28 @@ no_dns: */ if (!(fs->fs_flags & FSF_PINGING)) { np = (nfs_private *) fs->fs_private; - np->np_mountd_inval = TRUE; - np->np_xid = XID_ALLOC(); - np->np_error = -1; - np->np_ping = 0; - /* - * Initially the server will be deemed dead - * after MAX_ALLOWED_PINGS of the fast variety - * have failed. - */ - np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1; - start_nfs_pings(fs, pingval); - if (fserver_is_down) - fs->fs_flags |= FSF_VALID | FSF_DOWN; + if (np->np_mountd_inval != 'P') { + np->np_mountd_inval = TRUE; + np->np_xid = XID_ALLOC(); + np->np_error = -1; + np->np_ping = 0; + /* + * Initially the server will be deemed dead + * after MAX_ALLOWED_PINGS of the fast variety + * have failed. + */ + np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1; + start_nfs_pings(fs, pingval); + if (fserver_is_down) + fs->fs_flags |= FSF_VALID | FSF_DOWN; + } else { + fs->fs_flags = FSF_VALID; + } + } fs->fs_refc++; - if (ip) - XFREE(ip); + XFREE(ip); return fs; } } @@ -993,7 +1017,7 @@ no_dns: */ fs = ALLOC(struct fserver); fs->fs_refc = 1; - fs->fs_host = strdup(hp ? hp->h_name : "unknown_hostname"); + fs->fs_host = xstrdup(hp ? hp->h_name : "unknown_hostname"); if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) host_normalize(&fs->fs_host); fs->fs_ip = ip; @@ -1014,9 +1038,18 @@ no_dns: fs->fs_flags |= FSF_PING_UNINIT; /* pinger hasn't been initialized */ np = ALLOC(struct nfs_private); memset((voidp) np, 0, sizeof(*np)); - np->np_mountd_inval = TRUE; - np->np_xid = XID_ALLOC(); - np->np_error = -1; + np->np_mountd = htons(hasmntval(&mnt, "mountport")); + if (np->np_mountd == 0) { + np->np_mountd_inval = 'Y'; + np->np_xid = XID_ALLOC(); + np->np_error = -1; + } else { + plog(XLOG_INFO, "%s: using mountport: %d", __func__, + (int) ntohs(np->np_mountd)); + np->np_mountd_inval = 'P'; + np->np_xid = 0; + np->np_error = 0; + } /* * Initially the server will be deemed dead after diff --git a/contrib/amd/amd/sun2amd.8 b/contrib/amd/amd/sun2amd.8 new file mode 100644 index 00000000000..67d241f32cd --- /dev/null +++ b/contrib/amd/amd/sun2amd.8 @@ -0,0 +1,92 @@ +.\" +.\" Copyright (c) 1997-2014 Erez Zadok +.\" Copyright (c) 2005 Daniel P. Ottavio +.\" Copyright (c) 1990 Jan-Simon Pendry +.\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine +.\" Copyright (c) 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Jan-Simon Pendry at Imperial College, London. +.\" +.\" 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. +.\" +.\" +.\" File: am-utils/amd/sun2amd.8 +.\" +.TH SUN2AMD 8L "14 August 2005" + +.SH NAME +sun2amd \- converts Sun automount maps to Amd maps + +.SH SYNOPSIS +.B sun2amd +[-hH] [-i infile] [-o outfile] + +.SH DESCRIPTION +.B sun2amd +is used to convert Sun style automount maps to Amd style automount +maps. By default +.B sun2amd +reads from stdin and writes to stdout. + +.SH OPTIONS +.TP +.B -h +Help +.TP +.B -i +Read Sun map information from specified file. +.TP +.B -o +Write Amd map information to specified file. + +.SH EXAMPLE +To convert a Sun automount file called auto_foo to an Amd file called +auto.amd type: + +.B sun2amd +-i auto_foo -o auto.amd + +.SH BUGS +* Can not convert master maps yet. + +* NFS is the only automount type currently supported. + +total_bug_count = number_found + 1; + +.SH "SEE ALSO" +.BR automount(8), +.BR amd(8) + +.I "Linux NFS and Automounter Administration" +by Erez Zadok, ISBN 0-7821-2739-8, (Sybex, 2001). +.LP +.I http://www.am-utils.org +.LP + +.SH AUTHOR +Daniel P. Ottavio +.I diff --git a/contrib/amd/amd/sun2amd.c b/contrib/amd/amd/sun2amd.c new file mode 100644 index 00000000000..ee6fbb59626 --- /dev/null +++ b/contrib/amd/amd/sun2amd.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 2005 Daniel P. Ottavio + * Copyright (c) 1989 Jan-Simon Pendry + * Copyright (c) 1989 Imperial College of Science, Technology & Medicine + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/sun2amd.c + * + */ + +/* + * Translate Sun-syntax maps to Amd maps + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#include +#include +#include + + +/* dummies to make the program compile and link */ +struct amu_global_options gopt; +#if defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) +# ifdef NEED_LIBWRAP_SEVERITY_VARIABLES +/* + * Some systems that define libwrap already define these two variables + * in libwrap, while others don't: so I need to know precisely iff + * to define these two severity variables. + */ +int allow_severity=0, deny_severity=0, rfc931_timeout=0; +# endif /* NEED_LIBWRAP_SEVERITY_VARIABLES */ +#endif /* defined(HAVE_TCPD_H) && defined(HAVE_LIBWRAP) */ + + +/* + * Parse the stream sun_in, convert the map information to amd, write + * the results to amd_out. + */ +static int +sun2amd_convert(FILE *sun_in, FILE *amd_out) +{ + char line_buff[INFO_MAX_LINE_LEN], *tmp, *key, *entry; + int pos, line = 0, retval = 1; + + /* just to be safe */ + memset(line_buff, 0, sizeof(line_buff)); + + /* Read the input line by line and do the conversion. */ + while ((pos = file_read_line(line_buff, sizeof(line_buff), sun_in))) { + line++; + line_buff[pos - 1] = '\0'; + + /* remove comments */ + if ((tmp = strchr(line_buff, '#')) != NULL) { + *tmp = '\0'; + } + + /* find start of key */ + key = line_buff; + while (*key != '\0' && isspace((unsigned char)*key)) { + key++; + } + + /* ignore blank lines */ + if (*key == '\0') { + continue; + } + + /* find the end of the key and NULL terminate */ + tmp = key; + while (*tmp != '\0' && isspace((unsigned char)*tmp) == 0) { + tmp++; + } + if (*tmp == '\0') { + plog(XLOG_ERROR, "map line %d has no entry", line); + goto err; + } + *tmp++ = '\0'; + if (*tmp == '\0') { + plog(XLOG_ERROR, "map line %d has no entry", line); + goto err; + } + entry = tmp; + + /* convert the sun entry to an amd entry */ + if ((tmp = sun_entry2amd(key, entry)) == NULL) { + plog(XLOG_ERROR, "parse error on line %d", line); + goto err; + } + + if (fprintf(amd_out, "%s %s\n", key, tmp) < 0) { + plog(XLOG_ERROR, "can't write to output stream: %s", strerror(errno)); + goto err; + } + + /* just to be safe */ + memset(line_buff, 0, sizeof(line_buff)); + } + + /* success */ + retval = 0; + + err: + return retval; +} + + +/* + * wrapper open function + */ +static FILE * +sun2amd_open(const char *path, const char *mode) +{ + FILE *retval = NULL; + + if ((retval = fopen(path,mode)) == NULL) { + plog(XLOG_ERROR,"could not open file %s",path); + } + + return retval; +} + + +/* + * echo the usage and exit + */ +static void +sun2amd_usage(void) +{ + fprintf(stderr, + "usage : sun2amd [-hH] [-i infile] [-o outfile]\n" + "-h\thelp\n" + "-i\tspecify an infile (defaults to stdin)\n" + "-o\tspecify an outfile (defaults to stdout)\n"); +} + + +int +main(int argc, char **argv) +{ + /* default in/out to stdin/stdout */ + FILE *sun_in = stdin, *amd_out = stdout; + int opt, retval = 1; + + while ((opt = getopt(argc, argv , "i:o:hH")) != -1) { + switch (opt) { + + case 'i': + if ((sun_in = sun2amd_open(optarg,"r")) == NULL) { + goto err; + } + break; + + case 'o': + if ((amd_out = sun2amd_open(optarg,"w")) == NULL) { + goto err; + } + break; + + case 'h': + case 'H': + sun2amd_usage(); + goto err; + } + } + + retval = sun2amd_convert(sun_in,amd_out); + + err: + exit(retval); +} diff --git a/contrib/amd/amd/sun_map.c b/contrib/amd/amd/sun_map.c new file mode 100644 index 00000000000..8e3559960cd --- /dev/null +++ b/contrib/amd/amd/sun_map.c @@ -0,0 +1,595 @@ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 2005 Daniel P. Ottavio + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/sun_map.c + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#include +#include +#include + + + +/* + * Add a data pointer to the end of the list. + */ +void +sun_list_add(struct sun_list *list, qelem *item) +{ + if (list->last == NULL) { + list->last = item; + list->first = item; + item->q_back = NULL; + } + else { + list->last->q_forw = item; + item->q_back = list->last; + list->last = item; + } + + item->q_forw = NULL; +} + + +/* + * Sun2Amd conversion routines + */ + +/* + * AMD entry keywords + */ +#define AMD_OPTS_KW "addopts:=" /* add entry options */ +#define AMD_RHOST_KW "rhost:=" /* remote host */ +#define AMD_RFS_KW "rfs:=" /* remote file system */ +#define AMD_FS_KW "fs:=" /* local file system */ +#define AMD_DEV_KW "dev:=" /* device */ +#define AMD_TYPE_NFS_KW "type:=nfs;" /* fs type nfs */ +#define AMD_TYPE_AUTO_KW "type:=auto;" /* fs type auto */ +#define AMD_TYPE_CDFS_KW "type:=cdfs;" /* fs type cd */ +#define AMD_MAP_FS_KW "fs:=${map};" /* set the mount map as current map */ +#define AMD_MAP_PREF_KW "pref:=${key}/" /* set the mount map as current map */ + +/* + * A set of string Sun fstypes. + */ +#define SUN_NFS_TYPE "nfs" +#define SUN_HSFS_TYPE "hsfs" /* CD fs */ +#define SUN_AUTOFS_TYPE "autofs" +#define SUN_CACHEFS_TYPE "cachefs" + +#define SUN_KEY_SUB "&" /* Sun key substitution */ + +/* a set a Sun variable substitutions for map entries */ +#define SUN_ARCH "$ARCH" /* host architecture */ +#define SUN_CPU "$CPU" /* processor type */ +#define SUN_HOST "$HOST" /* host name */ +#define SUN_OSNAME "$OSNAME" /* OS name */ +#define SUN_OSREL "$OSREL" /* OS release */ +#define SUN_OSVERS "$OSVERS" /* OS version */ +#define SUN_NATISA "$NATISA" /* native instruction set */ + +/* a set of Amd variable substitutions */ +#define AMD_ARCH "${arch}" /* host architecture */ +#define AMD_HOST "${host}" /* host name */ +#define AMD_OSNAME "${os}" /* OS name */ +#define AMD_OSVER "${osver}" /* OS version */ + + +/* + * Return a copy of src that has all occurrences of 'str' replaced + * with sub. + * + * param src - the original string + * param str - string that is the replaced with str + * param sub - string that replaces an occurrences of 'delim' + * + * return - new string with str substitutions, NULL on error + */ +static char * +sun_strsub(const char *src, const char *str, const char *sub) +{ + + char *retval = NULL, *str_start, *str_end, *src_end; + size_t total_size, first_half, second_half, sub_size; + + /* assign pointers to the start and end of str */ + if ((str_start = strstr(src, str)) == NULL) { + return retval; + } + str_end = (strlen(str) - 1) + str_start; + + /* assign to the end of the src. */ + src_end = (strlen(src) - 1) + (char*)src; + + /* size from the beginning of src to the start of str */ + first_half = (size_t)(str_start - src); + + /* size from the end of str to the end of src */ + second_half = (size_t)(src_end - str_end); + + sub_size = strlen(sub); + + total_size = (first_half + sub_size + second_half + 1); + + retval = (char*)xmalloc(total_size); + memset(retval, 0, total_size); + + /* + * Put together the string such that the first half is copied + * followed the sub and second half. + * + * We use strncpy instead of xstrlcpy because we are intentionally + * causing truncation and we don't want this to cause errors in the + * log. + */ + (void)strncpy(retval, src, first_half); + (void)strncat(retval, sub, sub_size); + (void)strncat(retval, str_end + 1, second_half); + + if (strstr(retval, str) != NULL) { + /* + * If there is another occurrences of str call this function + * recursively. + */ + char* tmp; + if ((tmp = sun_strsub(retval, str, sub)) != NULL) { + XFREE(retval); + retval = tmp; + } + } + return retval; +} + + +/* + * Return a new string that is a copy of str, all occurrences of a Sun + * variable substitutions are replaced by there equivalent Amd + * substitutions. + * + * param str - source string + * + * return - A new string with the expansions, NULL if str does not + * exist in src or error. + */ +static char * +sun_expand2amd(const char *str) +{ + + char *retval = NULL, *tmp = NULL, *tmp2 = NULL; + const char *pos; + + /* + * Iterator through the string looking for '$' chars. For each '$' + * found try to replace it with Sun variable substitutions. If we + * find a '$' that is not a substation each of the i.e $blah than + * each of the replace attempt will fail and we'll move on to the + * next char. + */ + tmp = xstrdup(str); + for (pos = str; *pos != '\0'; pos++) { + if (*pos != '$') { + continue; + } + if (tmp2 != NULL) { + XFREE(tmp); + tmp = tmp2; + } + + /* + * If a 'replace' does not return NULL than a variable was + * successfully substituted. + */ + + /* architecture */ + if ((tmp2 = sun_strsub(tmp, SUN_ARCH, AMD_ARCH)) != NULL) { + continue; + } + /* cpu - there is not POSIX uname for cpu so just use machine */ + if ((tmp2 = sun_strsub(tmp, SUN_CPU, AMD_ARCH)) != NULL) { + continue; + } + /* hostname */ + if ((tmp2 = sun_strsub(tmp, SUN_HOST, AMD_HOST)) != NULL) { + continue; + } + /* os name */ + if ((tmp2 = sun_strsub(tmp, SUN_OSNAME, AMD_OSNAME)) != NULL) { + continue; + } + /* + * os release - Amd doesn't hava a OS release var just usr os + * version or now. + */ + if ((tmp2 = sun_strsub(tmp, SUN_OSREL, AMD_OSVER)) != NULL) { + continue; + } + /* os version */ + if ((tmp2 = sun_strsub(tmp, SUN_OSVERS, AMD_OSVER)) != NULL) { + continue; + } + /* native instruction set - there is no POSIX natisa so just use system */ + if ((tmp2 = sun_strsub(tmp, SUN_NATISA, AMD_ARCH)) != NULL) { + continue; + } + } + if (tmp2 == NULL) { + retval = tmp; + } + else { + retval = tmp2; + XFREE(tmp); + } + + return retval; +} + + +/* + * This is a wrapper function for appending Amd entry information to a + * buffer. Any Sun variable substitutions will be converted into Amd + * equivalents. + * + * param dest - destination buffer + * param deslen - destination buffer length + * param key - entry key, this might be needed for key substitutions + * param str - string to append + */ +static void +sun_append_str(char *dest, + size_t destlen, + const char *key, + const char *str) +{ + char *sub = NULL, *sub2 = NULL, *out = NULL; + + /* By default we are going to just write the original string. */ + out = (char*)str; + + /* + * Resolve variable substitutions in two steps; 1) replace any key + * map substitutions with the entry key 2) expand any variable + * substitutions i.e $HOST. + * + * Try to replace the key substitution '&'. If this function returns + * with a new string, one or more key subs. where replaced with the + * entry key. + */ + if ((sub = sun_strsub(str, SUN_KEY_SUB, "${key}")) != NULL) { + out = sub; + /* + * Try to convert any variable substitutions. If this function + * returns a new string one or more var subs where expanded. + */ + if ((sub2 = sun_expand2amd(sub)) != NULL) { + out = sub2; + } + } + /* + * Try to convert any variable substitutions. If this function + * returns a new string one or more var subs where expanded. + */ + else if (out != NULL && (sub = sun_expand2amd(out)) != NULL) { + out = sub; + } + + if (out != NULL) { + xstrlcat(dest, out, destlen); + } + XFREE(sub); + XFREE(sub2); +} + + +/* + * Convert the list of Sun mount options to Amd mount options. The + * result is concatenated to dest. + * + * param dest - destination buffer + * param destlen - destination buffer length + * param key - automount key + * param opt_list - list of Sun mount options + */ +static void +sun_opts2amd(char *dest, + size_t destlen, + const char *key, + const struct sun_opt *opt_list) +{ + const struct sun_opt *opt; + + xstrlcat(dest, AMD_OPTS_KW, destlen); + + /* Iterate through each option and append it to the buffer. */ + for(opt = opt_list; opt != NULL; opt = NEXT(struct sun_opt, opt)) { + sun_append_str(dest, destlen, key, opt->str); + /* If there are more options add some commas. */ + if (NEXT(struct sun_opt, opt) != NULL) { + xstrlcat(dest, ",", destlen); + } + } + xstrlcat(dest, ";", destlen); +} + + +/* + * Convert the list of Sun mount locations to a list of Amd mount + * locations. The result is concatenated to dest. + * + * param dest - destination buffer + * param destlen - destination buffer length + * param key - automount key + * param local_list - list of Sun mount locations + */ +static void +sun_locations2amd(char *dest, + size_t destlen, + const char *key, + const struct sun_location *local_list) +{ + const struct sun_location *local; + const struct sun_host *host; + + for (local = local_list; + local != NULL; + local = NEXT(struct sun_location,local)) { + /* + * Check to see if the list of hosts is empty. Some mount types + * i.e cd-rom may have mount location with no host. + */ + if (local->host_list != NULL) { + /* Write each host that belongs to this location. */ + for (host = local->host_list; + host != NULL; + host = NEXT(struct sun_host, host)) { + /* set fstype NFS */ + xstrlcat(dest, AMD_TYPE_NFS_KW, destlen); + /* add rhost key word */ + xstrlcat(dest, AMD_RHOST_KW, destlen); + /* add host name */ + sun_append_str(dest, destlen, key, host->name); + xstrlcat(dest, ";", destlen); + /* add remote fs key word */ + xstrlcat(dest, AMD_RFS_KW, destlen); + /* add local path */ + sun_append_str(dest, destlen, key, local->path); + if (NEXT(struct sun_host, host) != NULL) { + xstrlcat(dest, ";", destlen); + xstrlcat(dest, " ", destlen); + } + } + } + else { + /* no host location */ + xstrlcat(dest, AMD_FS_KW, destlen); + sun_append_str(dest, destlen, key, local->path); + } + if (NEXT(struct sun_location, local) != NULL) { + /* add a space to separate each location */ + xstrlcat(dest, " ", destlen); + } + } +} + + +/* + * Convert a Sun HSFS mount point to an Amd. The result is + * concatenated intp dest. + * + * param dest - destination buffer + * param destlen - destination buffer length + * param key - automount key + * param s_entry - Sun entry + */ +static void +sun_hsfs2amd(char *dest, + size_t destlen, + const char *key, + const struct sun_entry *s_entry) +{ + /* set fstype CDFS */ + xstrlcat(dest, AMD_TYPE_CDFS_KW, destlen); + /* set the cdrom device */ + xstrlcat(dest, AMD_DEV_KW, destlen); + /* XXX: For now just assume that there is only one device. */ + xstrlcat(dest, s_entry->location_list->path, destlen); +} + + +/* + * Convert a Sun NFS automount entry to an Amd. The result is concatenated + * into dest. + * + * param dest - destination buffer + * param destlen - destination buffer length + * param key - automount key + * param s_entry - Sun entry + */ +static void +sun_nfs2amd(char *dest, + size_t destlen, + const char *key, + const struct sun_entry *s_entry) +{ + if (s_entry->location_list != NULL) { + /* write out the list of mountpoint locations */ + sun_locations2amd(dest, destlen, key, s_entry->location_list); + } +} + + +/* + * Convert a Sun multi-mount point entry to an Amd. This is done + * using the Amd type auto. Each auto entry is separated with a \n. + * + * param dest - destination buffer + * param destlen - destination buffer length + * param key - automount key + * param s_entry - Sun entry + */ +static void +sun_multi2amd(char *dest, + size_t destlen, + const char *key, + const struct sun_entry *s_entry) +{ + const struct sun_mountpt *mountpt; + + /* We need to setup a auto fs Amd automount point. */ + xstrlcat(dest, AMD_TYPE_AUTO_KW, destlen); + xstrlcat(dest, AMD_MAP_FS_KW, destlen); + xstrlcat(dest, AMD_MAP_PREF_KW, destlen); + + /* write the mountpts to dest */ + for (mountpt = s_entry->mountpt_list; + mountpt != NULL; + mountpt = NEXT(struct sun_mountpt, mountpt)) { + xstrlcat(dest, "\n", destlen); + /* write the key */ + xstrlcat(dest, key, destlen); + /* write the mount path */ + sun_append_str(dest, destlen, key, mountpt->path); + /* space */ + xstrlcat(dest, " ", destlen); + /* Write all the host locations for this mount point. */ + sun_locations2amd(dest, destlen, key, mountpt->location_list); + } +} + + +/* + * Convert the sun_entry into an Amd equivalent string. + * + * param key - automount key + * param s_entry - Sun style automap entry + * + * return - Amd entry on succes, NULL on error + */ +char * +sun_entry2amd(const char *key, const char *s_entry_str) +{ + char *retval = NULL; + char line_buff[INFO_MAX_LINE_LEN]; + int ws; + struct sun_entry *s_entry = NULL; + + /* The key should not be NULL. */ + if (key == NULL) { + plog(XLOG_ERROR,"Sun key value was null"); + goto err; + } + /* The Sun entry string should never be NULL. */ + if (s_entry_str == NULL) { + plog(XLOG_ERROR,"Sun entry value was null"); + goto err; + } + + /* Make sure there are no trailing white spaces or '\n'. */ + xstrlcpy(line_buff, s_entry_str, sizeof(line_buff)); + ws = strlen(line_buff) - 1; + while (ws >= 0 && (isspace((unsigned char)line_buff[ws]) || line_buff[ws] == '\n')) { + line_buff[ws--] = '\0'; + } + + /* Parse the sun entry line. */ + s_entry = sun_map_parse_read(line_buff); + if (s_entry == NULL) { + plog(XLOG_ERROR,"could not parse Sun style map"); + goto err; + } + + memset(line_buff, 0, sizeof(line_buff)); + + if (s_entry->opt_list != NULL) { + /* write the mount options to the buffer */ + sun_opts2amd(line_buff, sizeof(line_buff), key, s_entry->opt_list); + } + + /* Check if this is a multi-mount entry. */ + if (s_entry->mountpt_list != NULL) { + /* multi-mount point */ + sun_multi2amd(line_buff, sizeof(line_buff), key, s_entry); + retval = xstrdup(line_buff); + } + else { + /* single mount point */ + if (s_entry->fstype != NULL) { + if (NSTREQ(s_entry->fstype, SUN_NFS_TYPE, strlen(SUN_NFS_TYPE))) { + /* NFS Type */ + sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry); + retval = xstrdup(line_buff); + } + else if (NSTREQ(s_entry->fstype, SUN_HSFS_TYPE, strlen(SUN_HSFS_TYPE))) { + /* HSFS Type (CD fs) */ + sun_hsfs2amd(line_buff, sizeof(line_buff), key, s_entry); + retval = xstrdup(line_buff); + } + /* + * XXX: The following fstypes are not yet supported. + */ + else if (NSTREQ(s_entry->fstype, SUN_AUTOFS_TYPE, strlen(SUN_AUTOFS_TYPE))) { + /* AutoFS Type */ + plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.", + s_entry->fstype); + goto err; + + } + else if (NSTREQ(s_entry->fstype, SUN_CACHEFS_TYPE, strlen(SUN_CACHEFS_TYPE))) { + /* CacheFS Type */ + plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.", + s_entry->fstype); + goto err; + } + else { + plog(XLOG_ERROR, "Sun fstype %s is currently not supported by Amd.", + s_entry->fstype); + goto err; + } + } + else { + plog(XLOG_INFO, "No SUN fstype specified defaulting to NFS."); + sun_nfs2amd(line_buff, sizeof(line_buff), key, s_entry); + retval = xstrdup(line_buff); + } + } + + err: + XFREE(s_entry); + return retval; +} diff --git a/contrib/amd/amd/sun_map.h b/contrib/amd/amd/sun_map.h new file mode 100644 index 00000000000..75e707ae700 --- /dev/null +++ b/contrib/amd/amd/sun_map.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 2005 Daniel P. Ottavio + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/sun_map.h + * + */ + +#ifndef _SUN_MAP_H +#define _SUN_MAP_H + +/* host */ +struct sun_host { + qelem head; /* link-list header */ + char *name; /* hostname */ + int weight; /* weight given to the host */ +}; + +/* location */ +struct sun_location { + qelem head; /* link-list header */ + char *path; /* server path */ + struct sun_host *host_list; /* list of hosts */ +}; + +/* sun mount option */ +struct sun_opt { + qelem head; /* link-list header */ + char *str; /* option string */ +}; + +/* mount point */ +struct sun_mountpt { + qelem head; /* link-list header */ + char *path; /* optional mount point path */ + char *fstype; /* filesystem type */ + struct sun_opt *opt_list; /* list of option strings */ + struct sun_location *location_list; /* list of 'struct s2a_location' */ +}; + +/* automount entry */ +struct sun_entry { + qelem head; /* link-list header */ + char *key; /* auto map key */ + char *fstype; /* filesystem type */ + struct sun_opt *opt_list; /* list of mount options */ + struct sun_location *location_list; /* list of mount locations */ + struct sun_mountpt *mountpt_list; /* list of mount points */ +}; + +/* + * automount map file + * + * XXX: Only a place holder structure, not implemented yet. + */ +struct sun_map { + qelem head; /* link-list header */ + char *path; /* directory path of the map file */ + char *mount_dir; /* top level mount point for this map */ + int lookup; /* lookup type i.e file, yp, program, etc. */ + int direct_bool; /* set true if this map is a direct map */ + struct sun_opt *opt_list; /* list of global map options */ + struct sun_opt *include_list; /* list of included map files */ + struct sun_entry *entry_list; /* list of 'struct s2a_entry' */ +}; + +/* + * master map file + * + * XXX: Only a place holder structure, not implemented yet. + */ +struct sun_mmap { + qelem head; /* link-list header */ + struct sun_opt *include_list; /* list of included master maps */ + struct sun_map *amap_list; /* list of 'struct s2a_amap' */ +}; + +struct sun_list { + qelem *first; + qelem *last; +}; + + +/* + * EXTERNS + */ +extern char *sun_entry2amd(const char *, const char *); +extern struct sun_entry *sun_map_parse_read(const char *); +extern void sun_list_add(struct sun_list *, qelem *); + +#endif /* not _SUN_MAP_H */ diff --git a/contrib/amd/amd/sun_map_parse.y b/contrib/amd/amd/sun_map_parse.y new file mode 100644 index 00000000000..ccf258e2dcc --- /dev/null +++ b/contrib/amd/amd/sun_map_parse.y @@ -0,0 +1,492 @@ +%{ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 2005 Daniel P. Ottavio + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/sun_map_parse.y + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +#include +#include +#include + + +#define SUN_FSTYPE_STR "fstype=" + + +extern int sun_map_lex(void); +extern int sun_map_error(const char *); +extern void sun_map_tok_setbuff(const char *); +extern int sun_map_parse(void); + +struct sun_entry *sun_map_parse_read(const char *); + +static struct sun_list *sun_entry_list = NULL; +static struct sun_list *sun_opt_list = NULL; +static struct sun_list *sun_host_list = NULL; +static struct sun_list *sun_location_list = NULL; +static struct sun_list *mountpt_list = NULL; +static char *tmpFsType = NULL; + + +/* + * Each get* function returns a pointer to the corresponding global + * list structure. If the structure is NULL than a new instance is + * returned. + */ +static struct sun_list *get_sun_opt_list(void); +static struct sun_list *get_sun_host_list(void); +static struct sun_list *get_sun_location_list(void); +static struct sun_list *get_mountpt_list(void); +static struct sun_list *get_sun_entry_list(void); + +%} + +%union { + char strval[2048]; +} + +%token NEWLINE COMMENT WSPACE +%token WORD + +%% + +amap : file + ; + +file : new_lines entries + | entries + ; + +entries : entry + | entry new_lines + | entry new_lines entries + ; + +new_lines : NEWLINE + | NEWLINE new_lines + ; + +entry : locations { + + struct sun_list *list; + struct sun_entry *entry; + + /* allocate an entry */ + entry = CALLOC(struct sun_entry); + + /* + * Assign the global location list to this entry and reset the + * global pointer. Reseting the global pointer will create a new + * list instance next time get_sun_location_list() is called. + */ + list = get_sun_location_list(); + entry->location_list = (struct sun_location *)list->first; + sun_location_list = NULL; + + /* Add this entry to the entry list. */ + sun_list_add(get_sun_entry_list(), (qelem *)entry); +} + +| '-' options WSPACE locations { + + struct sun_list *list; + struct sun_entry *entry; + + entry = CALLOC(struct sun_entry); + + /* An fstype may have been defined in the 'options'. */ + if (tmpFsType != NULL) { + entry->fstype = tmpFsType; + tmpFsType = NULL; + } + + /* + * Assign the global location list to this entry and reset the + * global pointer. Reseting the global pointer will create a new + * list instance next time get_sun_location_list() is called. + */ + list = get_sun_location_list(); + entry->location_list = (struct sun_location *)list->first; + sun_location_list = NULL; + + /* + * Assign the global opt list to this entry and reset the global + * pointer. Reseting the global pointer will create a new list + * instance next time get_sun_opt_list() is called. + */ + list = get_sun_opt_list(); + entry->opt_list = (struct sun_opt *)list->first; + sun_opt_list = NULL; + + /* Add this entry to the entry list. */ + sun_list_add(get_sun_entry_list(), (qelem *)entry); +} + +| mountpoints { + + struct sun_list *list; + struct sun_entry *entry; + + /* allocate an entry */ + entry = CALLOC(struct sun_entry); + + /* + * Assign the global mountpt list to this entry and reset the global + * pointer. Reseting the global pointer will create a new list + * instance next time get_mountpt_list() is called. + */ + list = get_mountpt_list(); + entry->mountpt_list = (struct sun_mountpt *)list->first; + mountpt_list = NULL; + + /* Add this entry to the entry list. */ + sun_list_add(get_sun_entry_list(), (qelem *)entry); +} + +| '-' options WSPACE mountpoints { + + struct sun_list *list; + struct sun_entry *entry; + + /* allocate an entry */ + entry = CALLOC(struct sun_entry); + + /* An fstype may have been defined in the 'options'. */ + if (tmpFsType != NULL) { + entry->fstype = tmpFsType; + tmpFsType = NULL; + } + + /* + * Assign the global mountpt list to this entry and reset the global + * pointer. Reseting the global pointer will create a new list + * instance next time get_mountpt_list() is called. + */ + list = get_mountpt_list(); + entry->mountpt_list = (struct sun_mountpt *)list->first; + mountpt_list = NULL; + + /* + * Assign the global opt list to this entry and reset the global + * pointer. Reseting the global pointer will create a new list + * instance next time get_sun_opt_list() is called. + */ + list = get_sun_opt_list(); + entry->opt_list = (struct sun_opt *)list->first; + sun_opt_list = NULL; + + /* Add this entry to the entry list. */ + sun_list_add(get_sun_entry_list(), (qelem *)entry); +} +; + +mountpoints : mountpoint + | mountpoint WSPACE mountpoints + ; + +mountpoint : WORD WSPACE location { + + struct sun_list *list; + struct sun_mountpt *mountpt; + + /* allocate a mountpt */ + mountpt = CALLOC(struct sun_mountpt); + + /* + * Assign the global loaction list to this entry and reset the + * global pointer. Reseting the global pointer will create a new + * list instance next time get_sun_location_list() is called. + */ + list = get_sun_location_list(); + mountpt->location_list = (struct sun_location *)list->first; + sun_location_list = NULL; + + mountpt->path = xstrdup($1); + + /* Add this mountpt to the mountpt list. */ + sun_list_add(get_mountpt_list(), (qelem *)mountpt); +} + +| WORD WSPACE '-' options WSPACE location { + + struct sun_list *list; + struct sun_mountpt *mountpt; + + /* allocate a mountpt */ + mountpt = CALLOC(struct sun_mountpt); + + /* An fstype may have been defined in the 'options'. */ + if (tmpFsType != NULL) { + mountpt->fstype = tmpFsType; + tmpFsType = NULL; + } + + /* + * Assign the global location list to this entry and reset the + * global pointer. Reseting the global pointer will create a new + * list instance next time get_sun_location_list() is called. + */ + list = get_sun_location_list(); + mountpt->location_list = (struct sun_location *)list->first; + sun_location_list = NULL; + + /* + * Assign the global opt list to this entry and reset the global + * pointer. Reseting the global pointer will create a new list + * instance next time get_sun_opt_list() is called. + */ + list = get_sun_opt_list(); + mountpt->opt_list = (struct sun_opt *)list->first; + sun_opt_list = NULL; + + mountpt->path = xstrdup($1); + + /* Add this mountpt to the mountpt list. */ + sun_list_add(get_mountpt_list(), (qelem *)mountpt); +} +; + +locations : location + | location WSPACE locations + ; + +location : hosts ':' WORD { + + struct sun_list *list; + struct sun_location *location; + + /* allocate a new location */ + location = CALLOC(struct sun_location); + + /* + * Assign the global opt list to this entry and reset the global + * pointer. Reseting the global pointer will create a new list + * instance next time get_sun_opt_list() is called. + */ + list = get_sun_host_list(); + location->host_list = (struct sun_host *)list->first; + sun_host_list = NULL; + + location->path = xstrdup($3); + + /* Add this location to the location list. */ + sun_list_add(get_sun_location_list(), (qelem *)location); +} + +| ':' WORD { + + struct sun_location *location; + + /* allocate a new location */ + location = CALLOC(struct sun_location); + + location->path = xstrdup($2); + + /* Add this location to the location list. */ + sun_list_add(get_sun_location_list(), (qelem *)location); +} +; + +hosts : host + | host ',' hosts + ; + +host : WORD { + + /* allocate a new host */ + struct sun_host *host = CALLOC(struct sun_host); + + host->name = xstrdup($1); + + /* Add this host to the host list. */ + sun_list_add(get_sun_host_list(),(qelem *)host); +} + +| WORD weight { + + /* + * It is assumed that the host for this rule was allocated by the + * 'weight' rule and assigned to be the last host item on the host + * list. + */ + struct sun_host *host = (struct sun_host *)sun_host_list->last; + + host->name = xstrdup($1); +} +; + +weight : '(' WORD ')' { + + int val; + /* allocate a new host */ + struct sun_host *host = CALLOC(struct sun_host); + + val = atoi($2); + + host->weight = val; + + /* Add this host to the host list. */ + sun_list_add(get_sun_host_list(), (qelem *)host); +} +; + +options : option + | option ',' options + ; + +option : WORD { + + char *type; + + /* check if this is an fstype option */ + if ((type = strstr($1,SUN_FSTYPE_STR)) != NULL) { + /* parse out the fs type from the Sun fstype keyword */ + if ((type = type + strlen(SUN_FSTYPE_STR)) != NULL) { + /* + * This global fstype str will be assigned to the current being + * parsed later in the parsing. + */ + tmpFsType = xstrdup(type); + } + } + else { + /* + * If it is not an fstype option allocate an opt struct and assign + * the value. + */ + struct sun_opt *opt = CALLOC(struct sun_opt); + opt->str = xstrdup($1); + /* Add this opt to the opt list. */ + sun_list_add(get_sun_opt_list(), (qelem *)opt); + } +} + +; + +%% + +/* + * Parse 'map_data' which is assumed to be a Sun-syle map. If + * successful a sun_entry is returned. + * + * The parser is designed to parse map entries with out the keys. For + * example the entry: + * + * usr -ro pluto:/usr/local + * + * should be passed to the parser as: + * + * -ro pluto:/usr/local + * + * The reason for this is that the Amd info services already strip off + * the key when they read map info. + */ +struct sun_entry * +sun_map_parse_read(const char *map_data) +{ + struct sun_entry *retval = NULL; + + /* pass map_data to lex */ + sun_map_tok_setbuff(map_data); + + /* call yacc */ + sun_map_parse(); + + if (sun_entry_list != NULL) { + /* return the first Sun entry in the list */ + retval = (struct sun_entry*)sun_entry_list->first; + sun_entry_list = NULL; + } + else { + plog(XLOG_ERROR, "Sun map parser did not produce data structs."); + } + + return retval; +} + + +static struct sun_list * +get_sun_entry_list(void) +{ + if (sun_entry_list == NULL) { + sun_entry_list = CALLOC(struct sun_list); + } + return sun_entry_list; +} + + +static struct sun_list * +get_mountpt_list(void) +{ + if (mountpt_list == NULL) { + mountpt_list = CALLOC(struct sun_list); + } + return mountpt_list; +} + + +static struct sun_list * +get_sun_location_list(void) +{ + if (sun_location_list == NULL) { + sun_location_list = CALLOC(struct sun_list); + } + return sun_location_list; +} + + +static struct sun_list * +get_sun_host_list(void) +{ + if (sun_host_list == NULL) { + sun_host_list = CALLOC(struct sun_list); + } + return sun_host_list; +} + + +static struct sun_list * +get_sun_opt_list(void) +{ + if (sun_opt_list == NULL) { + sun_opt_list = CALLOC(struct sun_list); + } + return sun_opt_list; +} diff --git a/contrib/amd/amd/sun_map_tok.l b/contrib/amd/amd/sun_map_tok.l new file mode 100644 index 00000000000..f979bea4cf1 --- /dev/null +++ b/contrib/amd/amd/sun_map_tok.l @@ -0,0 +1,233 @@ +%{ +/* + * Copyright (c) 1997-2014 Erez Zadok + * Copyright (c) 2005 Daniel P. Ottavio + * Copyright (c) 1990 Jan-Simon Pendry + * Copyright (c) 1990 Imperial College of Science, Technology & Medicine + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry at Imperial College, London. + * + * 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. + * + * + * File: am-utils/amd/sun_map_tok.l + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ +/* + * Some systems include a definition for the macro ECHO in , + * and their (bad) version of lex defines it too at the very beginning of + * the generated lex.yy.c file (before it can be easily undefined), + * resulting in a conflict. So undefine it here before needed. + * Luckily, it does not appear that this macro is actually used in the rest + * of the generated lex.yy.c file. + */ +#ifdef ECHO +# undef ECHO +#endif /* ECHO */ +#include +#include +#include +/* and once again undefine this, just in case */ +#ifdef ECHO +# undef ECHO +#endif /* ECHO */ + +/* + * There are some things that need to be defined only if using GNU flex. + * These must not be defined if using standard lex + */ +#ifdef FLEX_SCANNER +# ifndef ECHO +# define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout )) +# endif /* not ECHO */ +#endif /* FLEX_SCANNER */ + +int yylex(void); +int sun_map_error(const char *); + +/* + * We need to configure lex to parse from a string + * instead of a file. Each version of lex has it's + * own way of doing this (sigh). + */ + +/* assign the buffer to parse */ +void sun_map_tok_setbuff(const char* buff); + +/* buffer that contains the string to parse */ +const char *sun_map_tok_buff = NULL; + +#ifdef FLEX_SCANNER +/* + * The flex scanner uses the YY_INPUT to parse the input. + * We need to redefine it so that it can parse strings. + * In addition to the above string buffer we need to have + * a position pointer and a end pointer. + */ + +/* current position of the buffer */ +const char *sun_map_tok_pos = NULL; + +/* size of the buffer */ +const char *sun_map_tok_end = NULL; + +/* copies the current position + maxsize into buff */ +int sun_map_input(char *buff, int maxsize); + +# undef YY_INPUT +# define YY_INPUT(buff,result,maxsize) (result = sun_map_input(buff,maxsize)) + +#else +/* + * If this is not Flex than fall back to an AT&T style lex. + * We can parse strings by redefining input and unput. + */ +#undef input +#undef unput +#define input() (*(char *)sun_map_tok_buff++) +#define unput(c) (*(char *)--sun_map_tok_buff = c) + +#endif /* FLEX_SCANNER */ + +/* + * some systems such as DU-4.x have a different GNU flex in /usr/bin + * which automatically generates yywrap macros and symbols. So I must + * distinguish between them and when yywrap is actually needed. + */ +#if !defined(yywrap) || defined(yylex) +int yywrap(void); +#endif /* not yywrap or yylex */ + +/* no need to use yywrap() */ +#define YY_SKIP_YYWRAP + +int sun_map_line = 1; +int sun_map_tokpos = 1; + +%} + +/* This option causes Solaris lex to fail. Use flex. See BUGS file */ +/* no need to use yyunput() */ +%option nounput +%option noinput + +/* allocate more output slots so lex scanners don't run out of mem */ +%o 1024 + +WORD_REX [A-Za-z0-9_/&\.$=]+[A-Za-z0-9_/&\.$=-]* +COMMENT_REX ^#.*\n +WSPACE_REX [ \t]* +NEWLINE_REX [ \t]*\n +CONTINUE_REX "\\"\n + +%% + +{WORD_REX} { + sun_map_tokpos += yyleng; + xstrlcpy((char *)sun_map_lval.strval,(const char *)yytext,sizeof(sun_map_lval.strval)); + return WORD; + } + +{WSPACE_REX} { + sun_map_tokpos += yyleng; + return WSPACE; + } + +{NEWLINE_REX} { + sun_map_tokpos = 0; + sun_map_line++; + return NEWLINE; + } + +{CONTINUE_REX} { + sun_map_tokpos = 0; + sun_map_line++; + } + +{COMMENT_REX} { + sun_map_line++; + } + +. { + return yytext[0]; + } + +%% + + +int +sun_map_error(const char* s) +{ + return 1; +} + +#ifdef FLEX_SCANNER +void +sun_map_tok_setbuff(const char* buff) +{ + sun_map_tok_end = buff + strlen(buff); + sun_map_tok_pos = buff; + sun_map_tok_buff = buff; +} + + +int +sun_map_input(char *buff, int maxsize) +{ + int size = MIN(maxsize, (sun_map_tok_end - sun_map_tok_pos)); + if (size > 0) { + memcpy(buff,sun_map_tok_pos,size); + sun_map_tok_pos += size; + } + + return size; +} +#else +void +sun_map_tok_setbuff(const char* buff) +{ + sun_map_tok_buff = buff; +} + +#endif /* FLEX_SCANNER */ + +/* + * some systems such as DU-4.x have a different GNU flex in /usr/bin + * which automatically generates yywrap macros and symbols. So I must + * distinguish between them and when yywrap is actually needed. + */ +#if !defined(yywrap) || defined(yylex) +int yywrap(void) +{ + return 1; +} +#endif /* not yywrap or yylex */ diff --git a/contrib/amd/amd/test1.sh b/contrib/amd/amd/test1.sh new file mode 100755 index 00000000000..44cafbcbc71 --- /dev/null +++ b/contrib/amd/amd/test1.sh @@ -0,0 +1,2 @@ +#!/bin/sh +./amd -v 2> /dev/null diff --git a/contrib/amd/amq/amq.8 b/contrib/amd/amq/amq.8 index c9fb265e9ab..4cfdf84423b 100644 --- a/contrib/amd/amq/amq.8 +++ b/contrib/amd/amq/amq.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1990 Jan-Simon Pendry .\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,12 +32,11 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" %W% (Berkeley) %G% .\" -.\" $Id: amq.8,v 1.15.2.1 2006/01/02 18:48:24 ezk Exp $ +.\" File: am-utils/amq/amq.8 .\" $FreeBSD$ .\" -.Dd February 26, 2016 +.Dd August 31, 2016 .Dt AMQ 8 .Os .Sh NAME @@ -49,7 +44,7 @@ .Nd automounter query tool .Sh SYNOPSIS .Nm -.Op Fl fmpsvwHTU +.Op Fl fimpqsvwHTU .Op Fl h Ar hostname .Op Fl l Ar log_file .Op Fl x Ar log_options @@ -96,6 +91,10 @@ an .Tn HP-UX cluster, the root server is queried by default, since that is the system on which the automounter is normally run. +.TP +.It Fl i +Print information about the mount maps. +.TP .It Fl l Ar log_file Tell .Xr amd 8 @@ -126,6 +125,13 @@ search through the process table. This option is used in the .Pa ctl-amd script. +.TP +.It Fl q +Suppress error messages produced when attempting synchronous unmounts +with the +.B \-u +option. +.TP .It Fl s Ask the automounter to provide system-wide mount statistics. .It Fl u @@ -138,9 +144,19 @@ They merely cause the mounted file system to timeout, which will be picked up by .Nm amd Ns 's main scheduler thus causing the normal timeout action to be taken. +If the +.B \-u +option is repeated, +.B amq +will attempt to unmount the file system synchronously by waiting until +the timeout action is taken and returning an error if the unmount +fails. +Any error messages produced may be suppressed with the +.B \-q +option. +.TP .It Fl v -Ask the automounter for its version information. -This is a subset of the +Ask the automounter for its version information. This is a subset of the information output by .Xr amd 8 Ns 's .Fl v @@ -157,8 +173,10 @@ is running. .It Fl x Ar log_options Ask the automounter to use the logging options specified in .Ar log_options -from now on. +from now on. Note that the "fatal" and "error" options cannot be turned +off. .It Fl D Ar debug_options +.BI \-D " debug_options" Ask the automounter to use the debugging options specified in .Ar debug_options from now on. @@ -244,11 +262,13 @@ add this line to and this line to .Pa /etc/hosts.deny : .Pp +.RS .Dl "amd: ALL" .Sh SEE ALSO .Xr amd.conf 5 , -.Xr hosts_access 5 , -.Xr amd 8 +.Xr hosts_access 5 . +.Xr amd 8 , +.\" .Xr ctl-amd 8 , .Pp .Dq am-utils .Xr info 1 diff --git a/contrib/amd/amq/amq.c b/contrib/amd/amq/amq.c index 2379b621476..7140784c863 100644 --- a/contrib/amd/amq/amq.c +++ b/contrib/amd/amq/amq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -53,14 +49,17 @@ /* locals */ static int flush_flag; -static int minfo_flag; static int getpid_flag; -static int unmount_flag; -static int stats_flag; -static int getvers_flag; -static int amd_program_number = AMQ_PROGRAM; -static int use_tcp_flag, use_udp_flag; static int getpwd_flag; +static int getvers_flag; +static int minfo_flag; +static int mapinfo_flag; +static int quiet_flag; +static int stats_flag; +static int unmount_flag; +static int use_tcp_flag; +static int use_udp_flag; +static u_long amd_program_number = AMQ_PROGRAM; static char *debug_opts; static char *amq_logfile; static char *xlog_optstr; @@ -77,6 +76,17 @@ enum show_opt { }; +static void +time_print(time_type tt) +{ + time_t t = (time_t)*tt; + struct tm *tp = localtime(&t); + printf("%02d/%02d/%04d %02d:%02d:%02d", + tp->tm_mon + 1, tp->tm_mday, + tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year, + tp->tm_hour, tp->tm_min, tp->tm_sec); +} + /* * If (e) is Calc then just calculate the sizes * Otherwise display the mount node on stdout @@ -101,8 +111,7 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid) case Full: { - struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime)); - printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%04d %02d:%02d:%02d\n", + printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d", *dwid, *dwid, *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ *twid, *twid, @@ -116,18 +125,15 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid) mt->mt_lookup, mt->mt_readdir, mt->mt_readlink, - mt->mt_statfs, - - tp->tm_mon + 1, tp->tm_mday, - tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year, - tp->tm_hour, tp->tm_min, tp->tm_sec); + mt->mt_statfs); + time_print(mt->mt_mounttime); + printf("\n"); } break; case Stats: { - struct tm *tp = localtime((time_t *) ((voidp) &mt->mt_mounttime)); - printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%04d\n", + printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d ", *dwid, *dwid, *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ @@ -136,11 +142,9 @@ show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid) mt->mt_lookup, mt->mt_readdir, mt->mt_readlink, - mt->mt_statfs, - - tp->tm_mon + 1, tp->tm_mday, - tp->tm_year < 1900 ? tp->tm_year + 1900 : tp->tm_year, - tp->tm_hour, tp->tm_min, tp->tm_sec); + mt->mt_statfs); + time_print(mt->mt_mounttime); + printf("\n"); } break; @@ -229,7 +233,7 @@ show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twi { for (i = 0; i < ml->amq_mount_info_list_len; i++) { amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; - printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s", + printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s ", *mwid, *mwid, mi->mi_mountinfo, *dwid, *dwid, mi->mi_mountpt, *twid, *twid, mi->mi_type, @@ -251,6 +255,55 @@ show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twi } } +static void +show_map(amq_map_info *mi) +{ +} + +static void +show_mapinfo(amq_map_info_list *ml, enum show_opt e, int *nwid, int *wwid) +{ + u_int i; + + switch (e) { + + case Calc: + { + for (i = 0; i < ml->amq_map_info_list_len; i++) { + amq_map_info *mi = &ml->amq_map_info_list_val[i]; + int nw = strlen(mi->mi_name); + int ww = strlen(mi->mi_wildcard ? mi->mi_wildcard : "(null"); + if (nw > *nwid) + *nwid = nw; + if (ww > *wwid) + *wwid = ww; + } + } + break; + + case Full: + { + printf("%-*.*s %-*.*s %-8.8s %-7.7s %-7.7s %-7.7s %-s Modified\n", + *nwid, *nwid, "Name", + *wwid, *wwid, "Wild", + "Flags", "Refcnt", "Entries", "Reloads", "Stat"); + for (i = 0; i < ml->amq_map_info_list_len; i++) { + amq_map_info *mi = &ml->amq_map_info_list_val[i]; + printf("%-*.*s %*.*s %-8x %-7d %-7d %-7d %s ", + *nwid, *nwid, mi->mi_name, + *wwid, *wwid, mi->mi_wildcard, + mi->mi_flags, mi->mi_refc, mi->mi_nentries, mi->mi_reloads, + mi->mi_up == -1 ? "root" : (mi->mi_up ? " up" : "down")); + time_print(mi->mi_modify); + fputc('\n', stdout); + } + } + break; + + default: + break; + } +} /* * Display general mount statistics @@ -287,6 +340,72 @@ cluster_server(void) #endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */ +static void +print_umnt_error(amq_sync_umnt *rv, const char *fs) +{ + + switch (rv->au_etype) { + case AMQ_UMNT_OK: + break; + case AMQ_UMNT_FAILED: + printf("unmount failed: %s\n", strerror(rv->au_errno)); + break; + case AMQ_UMNT_FORK: + if (rv->au_errno == 0) + printf("%s is not mounted\n", fs); + else + printf("falling back to asynchronous unmount: %s\n", + strerror(rv->au_errno)); + break; + case AMQ_UMNT_READ: + printf("pipe read error: %s\n", strerror(rv->au_errno)); + break; + case AMQ_UMNT_SERVER: + printf("amd server down\n"); + break; + case AMQ_UMNT_SIGNAL: + printf("got signal: %d\n", rv->au_signal); + break; + /* + * Omit default so the compiler can check for missing cases. + * + default: + break; + */ + } +} + + +static int +amu_sync_umnt_to_retval(amq_sync_umnt *rv) +{ + switch (rv->au_etype) { + case AMQ_UMNT_FORK: + if (rv->au_errno == 0) { + /* + * We allow this error so that things like: + * amq -uu /l/cd0d && eject cd0 + * will work when /l/cd0d is not mounted. + * XXX - We still print an error message. + */ + return 0; + } + /*FALLTHROUGH*/ + default: + return rv->au_etype; + } +} + + +static int +clnt_failed(CLIENT *clnt, char *server) +{ + fprintf(stderr, "%s: ", am_get_progname()); + clnt_perror(clnt, server); + return 1; +} + + /* * MAIN */ @@ -320,7 +439,7 @@ main(int argc, char *argv[]) /* * Parse arguments */ - while ((opt_ch = getopt(argc, argv, "Hfh:l:msuvx:D:pP:TUw")) != -1) + while ((opt_ch = getopt(argc, argv, "Hfh:il:mqsuvx:D:pP:TUw")) != -1) switch (opt_ch) { case 'H': goto show_usage; @@ -335,6 +454,11 @@ main(int argc, char *argv[]) def_server = optarg; break; + case 'i': + mapinfo_flag = 1; + nodefault = 1; + break; + case 'l': amq_logfile = optarg; nodefault = 1; @@ -350,13 +474,18 @@ main(int argc, char *argv[]) nodefault = 1; break; + case 'q': + quiet_flag = 1; + nodefault = 1; + break; + case 's': stats_flag = 1; nodefault = 1; break; case 'u': - unmount_flag = 1; + unmount_flag++; nodefault = 1; break; @@ -403,9 +532,9 @@ main(int argc, char *argv[]) if (errs) { show_usage: fprintf(stderr, "\ -Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ +Usage: %s [-fimpqsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ \t[-x log_options] [-D debug_options]\n\ -\t[-P program_number] [[-u] directory ...]\n", +\t[-P program_number] [[-u[u]] directory ...]\n", am_get_progname() ); exit(1); @@ -538,16 +667,19 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ */ if (getpwd_flag) { char path[MAXPATHLEN+1]; - char *wd = getcwd(path, MAXPATHLEN+1); - amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt); + char *wd; + amq_mount_tree_list *mlp; amq_mount_tree_p mt; u_int i; int flag; + wd = getcwd(path, MAXPATHLEN+1); if (!wd) { - perror("getcwd"); + fprintf(stderr, "%s: getcwd failed (%s)", am_get_progname(), + strerror(errno)); exit(1); } + mlp = amqproc_export_1((voidp) 0, clnt); for (i = 0; mlp && i < mlp->amq_mount_tree_list_len; i++) { mt = mlp->amq_mount_tree_list_val[i]; while (1) { @@ -582,6 +714,26 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ } } + + /* + * Map + */ + if (mapinfo_flag) { + int dummy; + amq_map_info_list *ml = amqproc_getmapinfo_1(&dummy, clnt); + if (ml) { + int mwid = 0, wwid = 0; + show_mapinfo(ml, Calc, &mwid, &wwid); + mwid++; + if (wwid) + wwid++; + show_mapinfo(ml, Full, &mwid, &wwid); + } else { + fprintf(stderr, "%s: amd on %s cannot provide map info\n", + am_get_progname(), server); + } + } + /* * Get Version */ @@ -616,7 +768,20 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ if (optind < argc) { do { char *fs = argv[optind++]; - if (unmount_flag) { + if (unmount_flag > 1) { + amq_sync_umnt *sup; + /* + * Synchronous unmount request + */ + sup = amqproc_sync_umnt_1(&fs, clnt); + if (sup) { + if (quiet_flag == 0) + print_umnt_error(sup, fs); + errs = amu_sync_umnt_to_retval(sup); + } else { + errs = clnt_failed(clnt, server); + } + } else if (unmount_flag) { /* * Unmount request */ @@ -641,9 +806,7 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ } xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp); } else { - fprintf(stderr, "%s: ", am_get_progname()); - clnt_perror(clnt, server); - errs = 1; + errs = clnt_failed(clnt, server); } } } while (optind < argc); @@ -656,9 +819,7 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ if (ms) { show_ms(ms); } else { - fprintf(stderr, "%s: ", am_get_progname()); - clnt_perror(clnt, server); - errs = 1; + errs = clnt_failed(clnt, server); } } else if (!nodefault) { @@ -682,9 +843,7 @@ Usage: %s [-fmpsvwHTU] [-h hostname] [-l log_file|\"syslog\"]\n\ } } else { - fprintf(stderr, "%s: ", am_get_progname()); - clnt_perror(clnt, server); - errs = 1; + errs = clnt_failed(clnt, server); } } exit(errs); diff --git a/contrib/amd/amq/amq.h b/contrib/amd/amq/amq.h index 2f36b819445..3c894d687f5 100644 --- a/contrib/amd/amq/amq.h +++ b/contrib/amd/amq/amq.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -51,10 +47,12 @@ extern voidp amqproc_null_1(voidp argp, CLIENT *rqstp); extern amq_mount_tree_p *amqproc_mnttree_1(amq_string *argp, CLIENT *rqstp); extern voidp amqproc_umnt_1(amq_string *argp, CLIENT *rqstp); +extern amq_sync_umnt *amqproc_sync_umnt_1(amq_string *argp, CLIENT *rqstp); extern amq_mount_stats *amqproc_stats_1(voidp argp, CLIENT *rqstp); extern amq_mount_tree_list *amqproc_export_1(voidp argp, CLIENT *rqstp); extern int *amqproc_setopt_1(amq_setopt *argp, CLIENT *rqstp); extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp); +extern amq_map_info_list *amqproc_getmapinfo_1(voidp argp, CLIENT *rqstp); extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp); extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp); extern int *amqproc_getpid_1(voidp argp, CLIENT *rqstp); diff --git a/contrib/amd/amq/amq_clnt.c b/contrib/amd/amq/amq_clnt.c index ddfeb675c99..c5f1e87d97f 100644 --- a/contrib/amd/amq/amq_clnt.c +++ b/contrib/amd/amq/amq_clnt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -99,6 +95,23 @@ amqproc_umnt_1(amq_string *argp, CLIENT *clnt) } +amq_sync_umnt * +amqproc_sync_umnt_1(amq_string *argp, CLIENT *clnt) +{ + static amq_sync_umnt res; + enum clnt_stat rv; + + memset((char *) &res, 0, sizeof(res)); + if ((rv = clnt_call(clnt, AMQPROC_SYNC_UMNT, + (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp, + (XDRPROC_T_TYPE) xdr_amq_sync_umnt, (SVC_IN_ARG_TYPE) &res, + TIMEOUT)) != RPC_SUCCESS) { + return (NULL); + } + return &res; +} + + amq_mount_stats * amqproc_stats_1(voidp argp, CLIENT *clnt) { @@ -161,6 +174,20 @@ amqproc_getmntfs_1(voidp argp, CLIENT *clnt) return (&res); } +amq_map_info_list * +amqproc_getmapinfo_1(voidp argp, CLIENT *clnt) +{ + static amq_map_info_list res; + + memset((char *) &res, 0, sizeof(res)); + if (clnt_call(clnt, AMQPROC_GETMAPINFO, (XDRPROC_T_TYPE) xdr_void, argp, + (XDRPROC_T_TYPE) xdr_amq_map_info_list, + (SVC_IN_ARG_TYPE) &res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&res); +} + int * amqproc_mount_1(voidp argp, CLIENT *clnt) diff --git a/contrib/amd/amq/amq_xdr.c b/contrib/amd/amq/amq_xdr.c index 692a0a40860..b9a1c20fbf1 100644 --- a/contrib/amd/amq/amq_xdr.c +++ b/contrib/amd/amq/amq_xdr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -187,6 +183,59 @@ xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp) return (TRUE); } +bool_t +xdr_amq_map_info(XDR *xdrs, amq_map_info *objp) +{ + if (!xdr_amq_string(xdrs, &objp->mi_name)) { + return (FALSE); + } + + if (!xdr_amq_string(xdrs, &objp->mi_wildcard)) { + return (FALSE); + } + + if (!xdr_time_type(xdrs, &objp->mi_modify)) { + return (FALSE); + } + + if (!xdr_int(xdrs, &objp->mi_flags)) { + return (FALSE); + } + + if (!xdr_int(xdrs, &objp->mi_nentries)) { + return (FALSE); + } + + if (!xdr_int(xdrs, &objp->mi_reloads)) { + return (FALSE); + } + + if (!xdr_int(xdrs, &objp->mi_refc)) { + return (FALSE); + } + + if (!xdr_int(xdrs, &objp->mi_up)) { + return (FALSE); + } + + return (TRUE); +} + + +bool_t +xdr_amq_map_info_list(XDR *xdrs, amq_map_info_list *objp) +{ + if (!xdr_array(xdrs, + (char **) ((voidp) &objp->amq_map_info_list_val), + (u_int *) &objp->amq_map_info_list_len, + ~0, + sizeof(amq_map_info), + (XDRPROC_T_TYPE) xdr_amq_map_info)) { + return (FALSE); + } + return (TRUE); +} + bool_t xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp) diff --git a/contrib/amd/amq/pawd.1 b/contrib/amd/amq/pawd.1 index 8549434b219..5e5e84bc091 100644 --- a/contrib/amd/amq/pawd.1 +++ b/contrib/amd/amq/pawd.1 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1990 Jan-Simon Pendry .\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,9 +32,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" %W% (Berkeley) %G% .\" -.\" $Id: pawd.1,v 1.9.2.1 2006/01/02 18:48:24 ezk Exp $ +.\" File: am-utils/amq/pawd.1 .\" $FreeBSD$ .\" .Dd February 26, 2016 diff --git a/contrib/amd/amq/pawd.c b/contrib/amd/amq/pawd.c index c9a32b16189..bab6657521b 100644 --- a/contrib/amd/amq/pawd.c +++ b/contrib/amd/amq/pawd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/bootstrap b/contrib/amd/bootstrap index 6c351382caa..000b01670ab 100755 --- a/contrib/amd/bootstrap +++ b/contrib/amd/bootstrap @@ -5,6 +5,16 @@ # this is not meant to go into the distributions # Erez Zadok +validateversion() { + local v="$(autoreconf --version 2>&1 | head -1)" + case "$v" in + *2.69) ;; + *) echo "am-utils requires autoconf 2.69, you have:" + echo " $v" + exit 1;; + esac +} + # test cwd test -f ../amd/amd.c && cd .. if [ ! -f amd/amd.c ]; then @@ -37,67 +47,13 @@ test -f acinclude.m4 && mv -f acinclude.m4 acinclude.m4.old cat TRAILER ) > acinclude.m4 -# generate aclocal.m4 file -echo "AMU: aclocal..." -test -f aclocal.m4 && mv -f aclocal.m4 aclocal.m4.old -# show version -aclocal --version 2>&1 | head -1 -if aclocal ; then +# generate the rest of the scripts +echo "AMU: autoreconf..." +validateversion +if autoreconf -f -i; then : else - echo "aclocal command failed. fix errors and rerun $0." - exit 2 -fi - -# produce new configure.in (temp) script -echo "AMU: autoconf..." -# show version -autoconf --version 2>&1 | head -1 -LOG=/tmp/amu-$$.log -rm -f ${LOG} -autoconf configure.in > configure.new 2> ${LOG} -# until Automake requires Autoconf 2.50, manual says to ignore this -CUTWARNMSG1="warning: AC_PROG_LEX invoked multiple times|do not use m4_(patsubst|regexp):" -egrep -v "${CUTWARNMSG1}" ${LOG} > ${LOG}.new -mv ${LOG}.new ${LOG} -if test -s ${LOG}; then - echo "AUTOCONF ERRORS (MUST FIX):" - cat ${LOG} - rm -f ${LOG} - exit 2 -fi -# now prepare the real configure script -test -f configure && mv -f configure configure.old -mv -f configure.new configure -chmod a+rx configure -rm -f configure.old - -# run autoheader to produce C header .in files -echo "AMU: autoheader..." -# show version -autoheader --version 2>&1 | head -1 -autoheader configure.in > config.h.in 2> ${LOG} -CUTWARNMSG2="autoheader: \`config.h.in' is updated" -egrep -v "${CUTWARNMSG2}" ${LOG} > ${LOG}.new -mv ${LOG}.new ${LOG} -if test -s ${LOG}; then - echo "AUTOHEADER ERRORS (MUST FIX):" - cat ${LOG} - rm -f ${LOG} - exit 2 -fi -rm -f ${LOG} - -# generate makefiles -cmd="automake --add-missing --copy --ignore-deps" -#cmd="automake --add-missing" -echo "AMU: $cmd..." -# show version -automake --version 2>&1 | head -1 -if ${cmd} ; then - : -else - echo "automake command failed. fix errors and rerun $0." + echo "autoreconf command failed. fix errors and rerun $0." exit 2 fi diff --git a/contrib/amd/conf/checkmount/checkmount_bsd44.c b/contrib/amd/conf/checkmount/checkmount_bsd44.c index a6ec2438da8..6c6b21dcb4a 100644 --- a/contrib/amd/conf/checkmount/checkmount_bsd44.c +++ b/contrib/amd/conf/checkmount/checkmount_bsd44.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -45,6 +41,9 @@ # include #endif /* HAVE_CONFIG_H */ #include +#if __NetBSD_Version__ > 200030000 +#define statfs statvfs +#endif extern int is_same_host(char *name1, char *name2, struct in_addr addr2); int fixmount_check_mount(char *host, struct in_addr hostaddr, char *path); diff --git a/contrib/amd/conf/mtab/mtab_bsd.c b/contrib/amd/conf/mtab/mtab_bsd.c index fe3991aa575..203a265e13a 100644 --- a/contrib/amd/conf/mtab/mtab_bsd.c +++ b/contrib/amd/conf/mtab/mtab_bsd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -53,6 +49,9 @@ #include #include +#if __NetBSD_Version__ > 200030000 +#define statfs statvfs +#endif static mntent_t * mnt_dup(struct statfs *mp) @@ -60,8 +59,8 @@ mnt_dup(struct statfs *mp) mntent_t *new_mp = ALLOC(mntent_t); char *ty; - new_mp->mnt_fsname = strdup(mp->f_mntfromname); - new_mp->mnt_dir = strdup(mp->f_mntonname); + new_mp->mnt_fsname = xstrdup(mp->f_mntfromname); + new_mp->mnt_dir = xstrdup(mp->f_mntonname); #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME ty = mp->f_fstypename; @@ -93,8 +92,8 @@ mnt_dup(struct statfs *mp) } #endif /* not HAVE_STRUCT_STATFS_F_FSTYPENAME */ - new_mp->mnt_type = strdup(ty); - new_mp->mnt_opts = strdup("unset"); + new_mp->mnt_type = xstrdup(ty); + new_mp->mnt_opts = xstrdup("unset"); new_mp->mnt_freq = 0; new_mp->mnt_passno = 0; @@ -138,7 +137,7 @@ read_mtab(char *fs, const char *mnttabname) /* * Terminate the list */ - *mpp = 0; + *mpp = NULL; return mhp; } diff --git a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h index cf7ba33ee47..73661c9da3d 100644 --- a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h +++ b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -139,7 +135,7 @@ typedef writeargs nfswriteargs; */ #if 0 #define MOUNT_NFS3 MOUNT_NFS -#endif +#endif /* 0 */ #endif /* not _AMU_NFS_PROT_H */ diff --git a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h index 4e1e84a42f8..a415b8bab8f 100644 --- a/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h +++ b/contrib/amd/conf/nfs_prot/nfs_prot_freebsd3.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -103,9 +99,11 @@ struct ufs_extattr_per_mount; #define na_ctime ctime #define na_fileid fileid #define na_fsid fsid +#define na_gid gid #define na_mode mode #define na_mtime mtime #define na_nlink nlink +#define na_rdev rdev #define na_size size #define na_type type #define na_uid uid diff --git a/contrib/amd/conf/transp/transp_sockets.c b/contrib/amd/conf/transp/transp_sockets.c index 025e1f3e3cf..b3ad5fc5cbd 100644 --- a/contrib/amd/conf/transp/transp_sockets.c +++ b/contrib/amd/conf/transp/transp_sockets.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -171,7 +167,7 @@ get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, /* * Bind to a privileged port */ - if (bind_resv_port(*sock, (u_short *) 0) < 0) + if (bind_resv_port(*sock, (u_short *) NULL) < 0) plog(XLOG_ERROR, "can't bind privileged port (socket)"); /* @@ -198,7 +194,7 @@ get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, /* * Bind to a privileged port */ - if (bind_resv_port(*sock, (u_short *) 0) < 0) + if (bind_resv_port(*sock, (u_short *) NULL) < 0) plog(XLOG_ERROR, "can't bind privileged port"); /* @@ -231,13 +227,15 @@ amu_svc_getcaller(SVCXPRT *xprt) /* - * register an RPC server + * Register an RPC server: + * return 1 on success, 0 otherwise. */ int amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, void (*dispatch)(struct svc_req *rqstp, SVCXPRT *transp), u_long protocol, struct netconfig *dummy) { + /* on Sockets: svc_register returns 1 on success, 0 otherwise */ return svc_register(xprt, prognum, versnum, dispatch, protocol); } @@ -246,9 +244,8 @@ amu_svc_register(SVCXPRT *xprt, u_long prognum, u_long versnum, * Create the nfs service for amd */ int -create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp)) +create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version) { - *soNFSp = socket(AF_INET, SOCK_DGRAM, 0); if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) { @@ -268,9 +265,9 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (* close(*soNFSp); return 1; } - if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) { - plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)", - (u_long) NFS_PROGRAM, (u_long) NFS_VERSION); + if (!svc_register(*nfs_xprtp, NFS_PROGRAM, nfs_version, dispatch_fxn, 0)) { + plog(XLOG_FATAL, "unable to register (%lu, %lu, 0)", + (u_long) NFS_PROGRAM, nfs_version); svc_destroy(*nfs_xprtp); close(*soNFSp); return 3; @@ -386,8 +383,8 @@ int check_pmap_up(char *host, struct sockaddr_in* sin) if (client == (CLIENT *) NULL) { plog(XLOG_ERROR, - "check_pmap_up: cannot create connection to contact portmapper on host \"%s\"%s", - host, clnt_spcreateerror("")); + "%s: cannot create connection to contact portmapper on host \"%s\"%s", + __func__, host, clnt_spcreateerror("")); return 0; } @@ -406,8 +403,8 @@ int check_pmap_up(char *host, struct sockaddr_in* sin) if (clnt_stat == RPC_TIMEDOUT) { plog(XLOG_ERROR, - "check_pmap_up: failed to contact portmapper on host \"%s\": %s", - host, clnt_sperrno(clnt_stat)); + "%s: failed to contact portmapper on host \"%s\": %s", + __func__, host, clnt_sperrno(clnt_stat)); return 0; } return 1; @@ -418,7 +415,7 @@ int check_pmap_up(char *host, struct sockaddr_in* sin) * Find the best NFS version for a host and protocol. */ u_long -get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto) +get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto, u_long def) { CLIENT *clnt; int again = 0; @@ -431,68 +428,64 @@ get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const c * If not set or set wrong, then try from NFS_VERS_MAX on down. If * set, then try from nfs_version on down. */ - if (nfs_version <= 0 || nfs_version > NFS_VERS_MAX) { - nfs_version = NFS_VERS_MAX; + if (!nfs_valid_version(nfs_version)) { + if (nfs_valid_version(def)) + nfs_version = def; + else + nfs_version = NFS_VERS_MAX; again = 1; } tv.tv_sec = 2; /* retry every 2 seconds, but also timeout */ tv.tv_usec = 0; -#ifdef HAVE_FS_NFS3 -try_again: -#endif /* HAVE_FS_NFS3 */ + for (; nfs_version >= NFS_VERS_MIN; nfs_version--) { - sock = RPC_ANYSOCK; - errstr = NULL; - if (STREQ(proto, "tcp")) - clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0); - else if (STREQ(proto, "udp")) - clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock); - else - clnt = NULL; + sock = RPC_ANYSOCK; + errstr = NULL; + if (STREQ(proto, "tcp")) + clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0); + else if (STREQ(proto, "udp")) + clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock); + else + clnt = NULL; - if (clnt != NULL) { - /* Try three times (6/2=3) to verify the CLIENT handle. */ - tv.tv_sec = 6; - clnt_stat = clnt_call(clnt, - NFSPROC_NULL, - (XDRPROC_T_TYPE) xdr_void, - 0, - (XDRPROC_T_TYPE) xdr_void, - 0, - tv); + if (clnt != NULL) { + /* Try three times (6/2=3) to verify the CLIENT handle. */ + tv.tv_sec = 6; + clnt_stat = clnt_call(clnt, + NFSPROC_NULL, + (XDRPROC_T_TYPE) xdr_void, + 0, + (XDRPROC_T_TYPE) xdr_void, + 0, + tv); - if (clnt_stat != RPC_SUCCESS) - errstr = clnt_sperrno(clnt_stat); + if (clnt_stat != RPC_SUCCESS) + errstr = clnt_sperrno(clnt_stat); - close(sock); - clnt_destroy(clnt); - } else { -#ifdef HAVE_CLNT_SPCREATEERROR - errstr = clnt_spcreateerror(""); -#else /* not HAVE_CLNT_SPCREATEERROR */ - errstr = ""; -#endif /* not HAVE_CLNT_SPCREATEERROR */ - } - - if (errstr) { - plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s%s", - (int) nfs_version, proto, host, errstr); - if (again) { -#ifdef HAVE_FS_NFS3 - if (nfs_version == NFS_VERSION3) { - nfs_version = NFS_VERSION; - again = 0; - plog(XLOG_INFO, "get_nfs_version trying a lower version: NFS(%d,%s)", (int) nfs_version, proto); - } - goto try_again; -#endif /* HAVE_FS_NFS3 */ + close(sock); + clnt_destroy(clnt); + if (clnt_stat == RPC_SUCCESS) + break; + } else { + #ifdef HAVE_CLNT_SPCREATEERROR + errstr = clnt_spcreateerror(""); + #else /* not HAVE_CLNT_SPCREATEERROR */ + errstr = ""; + #endif /* not HAVE_CLNT_SPCREATEERROR */ + } + + if (errstr) { + plog(XLOG_INFO, "%s: NFS(%lu,%s) failed for %s: %s", __func__, + nfs_version, proto, host, errstr); } - return 0; } - plog(XLOG_INFO, "get_nfs_version: returning NFS(%d,%s) on host %s", - (int) nfs_version, proto, host); + if (nfs_version < NFS_VERS_MIN) + nfs_version = 0; + + plog(XLOG_INFO, "%s: returning NFS(%lu,%s) on host %s", __func__, + nfs_version, proto, host); return nfs_version; } diff --git a/contrib/amd/conf/umount/umount_bsd44.c b/contrib/amd/conf/umount/umount_bsd44.c index d05944d8f78..da441297798 100644 --- a/contrib/amd/conf/umount/umount_bsd44.c +++ b/contrib/amd/conf/umount/umount_bsd44.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -105,6 +101,7 @@ int umount2_fs(const char *mntdir, u_int unmount_flags) { int error = 0; + if (unmount_flags & AMU_UMOUNT_FORCE) { plog(XLOG_INFO, "umount2_fs: trying unmount/forced on %s", mntdir); error = unmount(mntdir, MNT2_GEN_OPT_FORCE); diff --git a/contrib/amd/doc/am-utils.texi b/contrib/amd/doc/am-utils.texi index 1cc46b608ba..2430bafa482 100644 --- a/contrib/amd/doc/am-utils.texi +++ b/contrib/amd/doc/am-utils.texi @@ -1,6 +1,6 @@ \input texinfo @c -*-texinfo-*- @c -@c Copyright (c) 1997-2006 Erez Zadok +@c Copyright (c) 1997-2014 Erez Zadok @c Copyright (c) 1989 Jan-Simon Pendry @c Copyright (c) 1989 Imperial College of Science, Technology & Medicine @c Copyright (c) 1989 The Regents of the University of California. @@ -17,11 +17,7 @@ @c 2. Redistributions in binary form must reproduce the above copyright @c notice, this list of conditions and the following disclaimer in the @c documentation and/or other materials provided with the distribution. -@c 3. All advertising materials mentioning features or use of this software -@c must display the following acknowledgment: -@c This product includes software developed by the University of -@c California, Berkeley and its contributors. -@c 4. Neither the name of the University nor the names of its contributors +@c 3. Neither the name of the University nor the names of its contributors @c may be used to endorse or promote products derived from this software @c without specific prior written permission. @c @@ -60,14 +56,14 @@ (Originally by Jan-Simon Pendry and Nick Williams) @page -Copyright @copyright{} 1997-2006 Erez Zadok +Copyright @copyright{} 1997-2014 Erez Zadok @* Copyright @copyright{} 1989 Jan-Simon Pendry @* Copyright @copyright{} 1989 Imperial College of Science, Technology & Medicine @* Copyright @copyright{} 1989 The Regents of the University of California. -@sp +@sp 1 All Rights Reserved. @vskip 1ex Permission to copy this document, or any portion of it, as @@ -93,7 +89,7 @@ For version @value{VERSION}, @value{UPDATED} @* (Originally by Jan-Simon Pendry and Nick Williams) -Copyright @copyright{} 1997-2006 Erez Zadok +Copyright @copyright{} 1997-2014 Erez Zadok @* Copyright @copyright{} 1989 Jan-Simon Pendry @* @@ -178,16 +174,6 @@ 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. -@item -All advertising materials mentioning features or use of this software -must display the following acknowledgment: - -@cartouche -``This product includes software developed by the University of -California, Berkeley and its contributors, as well as the Trustees of -Columbia University.'' -@end cartouche - @item Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software @@ -234,7 +220,7 @@ Revision 5.3bsdnet, a late alpha version of 5.3, was part of the BSD network version 2 distribution Revision 6.0 was made independently by -@email{ezk@@cs.columbia.edu,Erez Zadok} at the Computer Science +Erez Zadok at the Computer Science Department of @uref{http://www.cs.columbia.edu/,Columbia University}, as part of his @uref{http://www.fsl.cs.sunysb.edu/docs/zadok-thesis-proposal/,PhD @@ -262,7 +248,8 @@ If you find a problem and hopefully you can reproduce it, please describe it in detail and @uref{https://bugzilla.filesystems.org/,submit a bug report} via @uref{http://www.bugzilla.org/,Bugzilla}. Alternatively, you can send -your bug report to @email{am-utils@@am-utils.org} quoting the details +your bug report to the ``am-utils'' list (see +@url{http://www.am-utils.org/} under ``Mailing Lists'') quoting the details of the release and your configuration. These details can be obtained by running the command @samp{amd -v}. It would greatly help if you could provide a reproducible procedure for detecting the bug you are @@ -297,11 +284,10 @@ discussions of new features for am-utils implementation and porting issues @end itemize -To subscribe, visit -@url{http://lists.am-utils.org/mailman/listinfo/am-utils}. After -subscribing, you can post a message to this list at -@email{am-utils@@am-utils.org}. To avoid as much spam as -possible, only subscribers to this list may post to it. +To subscribe, visit @url{http://www.am-utils.org/} under ``Mailing +Lists.'' After subscribing, you can post a message to this list. To +avoid as much spam as possible, only subscribers to this list may post +to it. Subscribers of @samp{am-utils} are most helpful if they have the time and resources to test new and development versions of amd, on as many @@ -318,7 +304,7 @@ before January 1st, 2004. Please use the new name, @samp{am-utils}. @item The announcements mailing list, @samp{am-utils-announce} is for announcements only (mostly new releases). To subscribe, visit -@url{http://lists.am-utils.org/mailman/listinfo/am-utils-announce}. +@url{http://www.am-utils.org/} under ``Mailing Lists.'' This list is read-only: only am-utils developers may post to it. @item @@ -326,17 +312,18 @@ We distribute nightly CVS snapshots in @url{ftp://ftp.am-utils.org/pub/am-utils/snapshots/daily/}. If you like to get email notices of commits to the am-utils CVS repository, subscribe to the CVS logs mailing list, @samp{am-utils-cvs} at -@url{http://lists.am-utils.org/mailman/listinfo/am-utils-cvs}. +@url{http://www.am-utils.org/} under ``Mailing Lists.'' @item The older list which was used to user discussions, @samp{amd-workers}, is defunct as of January 2004. (Its last address was -@email{amd-workers@@majordomo.glue.umd.edu}.) Don't use +@email{amd-workers AT majordomo.glue.umd.edu}.) Don't use @samp{amd-workers}: use the newer, more active @samp{am-utils} list. @item For completeness, there's a developers-only closed list called -@samp{am-utils-developers@@am-utils.org}. +@samp{am-utils-developers} (see @url{http://www.am-utils.org/} under +``Mailing Lists''). @end enumerate @@ -346,7 +333,7 @@ For completeness, there's a developers-only closed list called @cindex Automounter book @cindex book -@email{ezk@@cs.sunysb.edu,Erez Zadok} wrote a +@uref{http://www.cs.sunysb.edu/~ezk,Erez Zadok} wrote a @uref{http://www.fsl.cs.sunysb.edu/docs/amd-book/,book}, titled @i{Linux NFS and Automounter Administration}, ISBN 0-7821-2739-8, (Sybex, 2001). The book is full of details and examples that go beyond what this manual @@ -389,7 +376,7 @@ numerous flavors of Unix. The @i{Amd} package has been without an official maintainer since 1992. Several people have stepped in to maintain it unofficially. Most notable were the `upl' (Unofficial Patch Level) releases of @i{Amd}, -created by me (@email{ezk@@cs.sunysb.edu,Erez Zadok}), and available from +created by me (@uref{http://www.cs.sunysb.edu/~ezk,Erez Zadok}), and available from @url{ftp://ftp.am-utils.org/pub/amd/}. The last such unofficial release was `upl102'. @@ -428,7 +415,7 @@ end-user, aside from the fact that @code{/bin/pwd} now always returns the correct amd-ified path. The administrator can easily switch between NFS and autofs mounts by changing one parameter in @code{amd.conf}. Autofs support and maintenance was developed in -conjunction with @email{ionut@@badula.org,Ion Badulescu}. +conjunction with @email{ionut AT badula.org,Ion Badulescu}. @c ################################################################ @node Overview, Supported Platforms, History, Top @@ -1040,7 +1027,7 @@ Similarly, if the password file entry was the map entry used by @i{Amd} would be @example -rfs:=/home/sugar;rhost:=sugar.cc;sublink:=jsp +rfs:=/home/sugar;rhost:=sugar.cc;sublink:=mhj @end example @c ---------------------------------------------------------------- @@ -1795,8 +1782,8 @@ Always evaluates to false. @i{ARG} is ignored. The argument @i{ARG} of this selector is a netgroup name followed optionally by a comma and a host name. If the host name is not specified, it defaults to @code{$@{host@}}. If the host name (short -name) is a member of the netgroup, this selector evaluates to -true. Otherwise it evaluates to false. +name) is a member of the netgroup, this selector evaluates to true. +Otherwise it evaluates to false. For example, suppose you have a netgroup @samp{ppp-hosts}, and for reasons of performance, these have a local @file{/home} partition, @@ -2098,6 +2085,10 @@ Ignore this mount by @b{df}(1). @cindex Mount flags; cache Allow data to be cached from a remote server for this mount. +@item closesession +@cindex Mount flags; closesession +For UDF mounts, close the session when unmounting. + @item compress @cindex Mount flags; compress Use NFS compression protocol. @@ -2137,10 +2128,16 @@ Set ID of filesystem. Enable generations in ISO-9660 file systems. Generations allow you to see all versions of a given file. +@item gmtoff=@var{n} +@cindex Mount flags; gmtoff +For UDF mounts, set the time zone offset from UTC to @var{n} seconds, +with positive values indicating east of the Prime Meridian. If not +set, the user's current time zone will be used. + @item group=@var{n} @cindex Mount flags; group -For PCFS mounts, set the group of the files in the file system to -@var{n} (which can either be a group name or a GID number). The +For PCFS and UDF mounts, set the group of the files in the file system +to @var{n} (which can either be a group name or a GID number). The default group is the group of the directory on which the file system is being mounted. @@ -2199,6 +2196,11 @@ is used. Do not allow data to be cached from a remote server for this mount. +@item nocasetrans +@cindex Mount flags; nocasetrans +Don't do case translation. Useful for CD-ROMS formatted as +ISO-9660. + @item noconn @cindex Mount flags; noconn Don't make a connection on datagram transports. @@ -2226,6 +2228,10 @@ Don't allow program execution. @cindex Mount flags; noint Do not allow keyboard interrupts for this mount +@item nojoliet +@cindex Mount flags; nojoliet +Turn off the Joliet extensions. Useful for CD-ROMS formatted as ISO-9660. + @item nolock @cindex Mount flags; nolock Do not use the NFS locking protocol @@ -2320,6 +2326,11 @@ trying}. @cindex Mount flags; retry Set the NFS retry counter. +@item rrcaseins +@cindex Mount flags; rrcaseins +Enable the Rock Ridge Interchange Protocol (RRIP) case insensitive extensions. +Useful for CD-ROMS formatted as ISO-9660. + @item rrip @cindex Mount flags; rrip Uses the Rock Ridge Interchange Protocol (RRIP) extensions to ISO-9660. @@ -2333,6 +2344,10 @@ NFS/UDP through a gateway or a slow link. @cindex Mount flags; rw Allow reads and writes on this filesystem. +@item sessionnr=@var{n} +@cindex Mount Flags; sessionnr +For multisession UDF mounts, use session number @var{n} when mounting. + @item shortname @cindex Mount Flags; longname For PCFS mounts, force old DOS short names only. @@ -2368,8 +2383,8 @@ The NFS timeout, in tenth-seconds, before a request is retransmitted. @item user=@var{n} @cindex Mount flags; user -For PCFS mounts, set the owner of the files in the file system to -@var{n} (which can either be a user name or a UID number). The +For PCFS and UDF mounts, set the owner of the files in the file system +to @var{n} (which can either be a user name or a UID number). The default owner is the owner of the directory on which the file system is being mounted. @@ -2824,13 +2839,13 @@ Copyright (c) 1990 Jan-Simon Pendry Copyright (c) 1990 Imperial College of Science, Technology & Medicine Copyright (c) 1990 The Regents of the University of California. am-utils version 6.0a15 (build 61). -Built by ezk@@cs.columbia.edu on date Wed Oct 22 15:21:03 EDT 1997. +Built by ezk@@example.com on date Wed Oct 22 15:21:03 EDT 1997. cpu=sparc (big-endian), arch=sun4, karch=sun4u. full_os=solaris2.5.1, os=sos5, osver=5.5.1, vendor=sun. Map support for: root, passwd, union, nisplus, nis, ndbm, file, error. AMFS: nfs, link, nfsx, nfsl, host, linkx, program, union, inherit, ufs, lofs, hsfs, pcfs, auto, direct, toplvl, error. -FS: autofs, cachefs, cdfs, lofs, nfs, nfs3, pcfs, tfs, tmpfs, ufs. +FS: autofs, cachefs, cdfs, lofs, nfs, nfs3, pcfs, tfs, tmpfs, udf, ufs. Network 1: wire="mcl-lab-net.cs.columbia.edu" (netnumber=128.59.13). Network 2: wire="14-net.cs.columbia.edu" (netnumber=128.59.14). Network 3: wire="old-net.cs.columbia.edu" (netnumber=128.59.16). @@ -2879,9 +2894,9 @@ a comma separated list selected from the following options: @table @code @item fatal -Fatal errors +Fatal errors (cannot be turned off) @item error -Non-fatal errors +Non-fatal errors (cannot be turned off) @item user Non-fatal user errors @item warn @@ -2896,10 +2911,15 @@ Mount map usage Additional statistics @item all All of the above +@item defaults +An alias for "fatal,error,user,warning,info". @end table Initially a set of default logging flags is enabled. This is as if -@samp{-x all,nomap,nostats} had been selected. The command line is +@samp{-x defaults} +or +@samp{-x fatal,error,user,warning,info} +had been selected. The command line is parsed and logging is controlled by the @code{-x} option. The very first set of logging flags is saved and can not be subsequently disabled using @i{Amq}. This default set of options is useful for general production @@ -2932,7 +2952,6 @@ of the message types.@refill @samp{LOG_INFO} @end table - The options can be prefixed by the string @samp{no} to indicate that this option should be turned off. For example, to obtain all but @samp{info} messages the option @samp{-x all,noinfo} would be used. @@ -3011,13 +3030,17 @@ can be prefixed with @samp{no} to turn it off. @table @code @item all -all ``reasonable'' options (currently trace|str|full|mem|info|readdir) +all options (excluding hrtime and mtab) +@item defaults +``sensible'' default options (all--excluding hrtime, mtab, and xdrtrace) +@item test +full debug options plus mtab,nodaemon,nofork,noamq @item amq -do not register for amq +register @i{Amd} with the RPC portmapper, for @i{Amq} @item daemon -do not enter daemon mode +enter daemon mode @item fork -do not fork child worker (hlfsd only) +fork child worker (hlfsd only) @item full program trace @item hrtime @@ -3028,16 +3051,14 @@ print high resolution time stamps (only if @b{syslog}(3) is not used) info service specific debugging (hesiod, nis, etc.) In the case of hesiod maps, turns on the hesiod RES_DEBUG internal debugging option. @item mem -trace memory allocations. Needs to be explicitly enabled at compile +trace memory allocations. Needs to be explicitly enabled at compile time with --enable-debug=mem. @item mtab -use local @file{./mtab} file +use local mount-table file (defaults to @file{/tmp/mtab}, @pxref{debug_mtab_file Parameter}) @item readdir show readdir progress @item str debug string munging -@item test -full debug but no daemon @item trace trace RPC protocol and NFS mount arguments @item xdrtrace @@ -3150,6 +3171,7 @@ effect visible to the user.@refill * Unix Filesystem:: Native disk filesystem. * Caching Filesystem:: Caching from remote server filesystem. * CD-ROM Filesystem:: ISO9660 CD ROM. +* UDF Filesystem:: Universal Disk Format filesystem. * Loopback Filesystem:: Local loopback-mount filesystem. * Memory/RAM Filesystem:: A memory or RAM-based filesystem. * Null Filesystem:: 4.4BSD's loopback-mount filesystem. @@ -3475,7 +3497,7 @@ inconsistent, requiring running the command @file{fsck -F cachefs @end enumerate @c ---------------------------------------------------------------- -@node CD-ROM Filesystem, Loopback Filesystem, Caching Filesystem, Filesystem Types +@node CD-ROM Filesystem, UDF Filesystem, Caching Filesystem, Filesystem Types @comment node-name, next, previous, up @section CD-ROM Filesystem (@samp{cdfs}) @cindex CD-ROM Filesystem @@ -3504,7 +3526,36 @@ cdfs os==sunos4;type:=cdfs;dev:=/dev/sr0 \ @end example @c ---------------------------------------------------------------- -@node Loopback Filesystem, Memory/RAM Filesystem, CD-ROM Filesystem, Filesystem Types +@node UDF Filesystem, Loopback Filesystem, CD-ROM Filesystem, Filesystem Types +@comment node-name, next, previous, up +@section CD-ROM Filesystem (@samp{udf}) +@cindex CD-ROM Filesystem +@cindex udf, filesystem type +@cindex Filesystem type; udf + +The @dfn{udf} (@samp{type:=udf}) filesystem mounts media with a +Universal Disk Format (UDF) filesystem on it, e.g., a video DVD. + +@noindent +The following option must be specified: + +@table @code +@cindex dev, mount option +@cindex Mount option; dev +@item dev +the block special device to be mounted. +@end table + +Some operating systems will fail to mount read-only media unless the +@samp{ro} option is specified. A udf entry might be: + +@example +udf os==sunos4;type:=udf;dev:=/dev/sr0 \ + os==sunos5;addopts:=ro;type:=udf;dev:=/dev/dsk/c0t6d0s2 +@end example + +@c ---------------------------------------------------------------- +@node Loopback Filesystem, Memory/RAM Filesystem, UDF Filesystem, Filesystem Types @comment node-name, next, previous, up @section Loopback Filesystem (@samp{lofs}) @cindex Loopback Filesystem @@ -4203,6 +4254,7 @@ sections that follow. * mount_type Parameter:: * search_path Parameter:: * selectors_in_defaults Parameter:: +* sun_map_syntax Parameter:: @end menu @c ---------------------------------------------------------------- @@ -4326,7 +4378,7 @@ sites can allow for local map customizations and overrides, and can distributed maps in several locations as needed. @c ---------------------------------------------------------------- -@node selectors_in_defaults Parameter, , search_path Parameter, Common Parameters +@node selectors_in_defaults Parameter, sun_map_syntax Parameter, search_path Parameter, Common Parameters @comment node-name, next, previous, up @subsection @t{selectors_in_defaults} Parameter @cindex selectors_in_defaults Parameter @@ -4346,6 +4398,15 @@ performance over slow slip-based networks as follows: Deprecated form: selectors_on_default. +@c ---------------------------------------------------------------- +@node sun_map_syntax Parameter, , selectors_in_defaults Parameter, Common Parameters +@comment node-name, next, previous, up +@subsection @t{sun_map_syntax} Parameter +@cindex sun_map_syntax Parameter + +(type=boolean, default=@samp{no}). If @samp{yes}, then @i{Amd} will +parse the map according to the Sun Automount syntax. + @c ================================================================ @node Global Parameters, Regular Map Parameters, Common Parameters, Amd Configuration File @@ -4527,14 +4588,14 @@ remain in the cache. (type=string, default no cluster). Same as the @code{-C} option to @i{Amd}. Specifies the alternate HP-UX cluster to use. -@c ---------------------------------------------------------------- -@node debug_mtab_file Parameter, debug_options Parameter, cluster Parameter, Global Parameters -@comment node-name, next, previous, up -@subsection @t{debug_mtab_file} Parameter -@cindex debug_mtab_file Parameter +@c ---------------------------------------------------------------- +@node debug_mtab_file Parameter, debug_options Parameter, cluster Parameter, Global Parameters +@comment node-name, next, previous, up +@subsection @t{debug_mtab_file} Parameter +@cindex debug_mtab_file Parameter -(type=string, default="/tmp/mnttab"). Path to mtab file that is used -by @i{Amd} to store a list of mounted file systems during debug-mtab mode. +(type=string, default="/tmp/mtab"). Path to mtab file that is used +by @i{Amd} to store a list of mounted file systems during debug-mtab mode. This option only applies to systems that store mtab information on disk. @c ---------------------------------------------------------------- @@ -4774,7 +4835,7 @@ is generally a bad idea to use those reserved for other services such as @subsection @t{log_options} Parameter @cindex log_options Parameter -(type=string, default no logging options). Same as the @code{-x} +(type=string, default=``defaults''). Same as the @code{-x} option to @i{Amd}. Specify any logging options for @i{Amd}. Options are comma delimited, and can be preceded by the string @samp{no} to negate their meaning. The @samp{debug} logging option is only available @@ -4785,12 +4846,14 @@ values are: @table @samp @item all all messages +@item defaults +an alias for "fatal,error,user,warning,info" @item debug debug messages @item error -non-fatal system errors +non-fatal system errors (cannot be turned off) @item fatal -fatal errors +fatal errors (cannot be turned off) @item info information @item map @@ -5271,7 +5334,7 @@ restart_mounts = yes auto_dir = /n log_file = /var/log/amd log_options = all -#debug_options = all +#debug_options = defaults plock = no selectors_in_defaults = yes # config.guess picks up "sunos5" and I don't want to edit my maps yet @@ -5436,6 +5499,7 @@ mount point. * Amq -m option:: Obtaining mount statistics. * Amq -p option:: Getting Amd's process ID. * Amq -P option:: Contacting alternate Amd processes. +* Amq -q option:: Suppress synchronous unmounting errors. * Amq -s option:: Obtaining global statistics. * Amq -T option:: Use TCP transport. * Amq -U option:: Use UDP transport. @@ -5641,7 +5705,7 @@ rather not have to search through the process table. This option is used in the @file{ctl-amd} script. @c ---------------------------------------------------------------- -@node Amq -P option, Amq -s option, Amq -p option, Controlling Amd +@node Amq -P option, Amq -q option, Amq -p option, Controlling Amd @comment node-name, next, previous, up @subsection @i{Amq} @code{-P} option @cindex Multiple Amd processes @@ -5664,7 +5728,16 @@ kill `amq -p -P 300020` @end example @c ---------------------------------------------------------------- -@node Amq -s option, Amq -T option, Amq -P option, Controlling Amd +@node Amq -q option, Amq -s option, Amq -P option, Controlling Amd +@comment node-name, next, previous, up +@subsection @i{Amq} @code{-q} option +@cindex Unmounting a filesystem + +Suppress any error messages produced when a synchronous unmount fails. +See @ref{Amq -u option}. + +@c ---------------------------------------------------------------- +@node Amq -s option, Amq -T option, Amq -q option, Controlling Amd @comment node-name, next, previous, up @subsection @i{Amq} @code{-s} option @cindex Global statistics @@ -5729,11 +5802,19 @@ and if that failed, will try UDP. @cindex Forcing filesystem to time out @cindex Unmounting a filesystem -The @code{-u} option causes the time-to-live interval of the named mount -points to be expired, thus causing an unmount attempt. This is the only -safe way to unmount an automounted filesystem. It is not possible to -unmount a filesystem which has been mounted with the @samp{nounmount} -flag. +The @code{-u} option causes the time-to-live interval of the named +mount points to be expired, thus causing an unmount attempt. This is +the only safe way to unmount an automounted filesystem. If @code{-u} +is repeated, then @i{Amd} will attempt to unmount the filesystem +synchronously. This makes things like + +@example +amq -uu /t/cd0d && eject cd0 +@end example + +@noindent +work as expected. Any error messages this might produce can be +suppressed with the @code{-q} option. See @ref{Amq -q option}. @c The @code{-H} option informs @i{Amd} that the specified mount point @c has hung - as if its keepalive timer had expired. @@ -5769,11 +5850,10 @@ as a whole, rather than any particular filesystem. The @code{-x} and @code{-D} options have exactly the same effect as @i{Amd}'s corresponding command line options. -When @i{Amd} receives a @code{-x} flag it limits the log options being -modified to those which were not enabled at startup. This prevents a -user turning @emph{off} any logging option which was specified at -startup, though any which have been turned on since then can still be -turned off. The @code{-D} option has a similar behavior. +When @i{Amd} receives the @code{-x} flag, it disallows turning off the +@samp{fatal} or @samp{error} flags. Both are on by default. They are +mandatory so that @i{Amd} could report important errors, including +errors relating to turning flags on/off. @c ################################################################ @node FSinfo, Hlfsd, Run-time Administration, Top @@ -6904,8 +6984,8 @@ symbolic link to subdirectory within a user's home directory, depending on the user which accessed that link. It was primarily designed to redirect incoming mail to users' home directories, so that it can be read from anywhere. It was designed and implemented by -@email{ezk@@cs.columbia.edu,Erez Zadok} and -@email{dupuy@@cs.columbia.edu,Alexander Dupuy}, at the +@uref{http://www.cs.sunysb.edu/~ezk,Erez Zadok} and +@email{dupuy AT cs.columbia.edu,Alexander Dupuy}, at the @uref{http://www.cs.columbia.edu/,Computer Science Department} of @uref{http://www.columbia.edu/,Columbia University}. A @uref{http://www.fsl.cs.sunysb.edu/docs/hlfsd/hlfsd.html,paper} @@ -7522,7 +7602,6 @@ am-utils, and get installed. * automount2amd:: * ctl-amd:: * ctl-hlfsd:: -* expn:: * fix-amd-map:: * fixmount:: * fixrmtab:: @@ -7649,7 +7728,7 @@ then start a new process --- only if the previous one died cleanly. @xref{Run-time Administration}, for more details. @c ---------------------------------------------------------------- -@node ctl-hlfsd, expn, ctl-amd, Assorted Tools +@node ctl-hlfsd, fix-amd-map, ctl-amd, Assorted Tools @comment node-name, next, previous, up @section ctl-hlfsd @pindex ctl-hlfsd @@ -7671,27 +7750,7 @@ died cleanly. @xref{Hlfsd}, for more details. @c ---------------------------------------------------------------- -@node expn, fix-amd-map, ctl-hlfsd, Assorted Tools -@comment node-name, next, previous, up -@section expn -@pindex expn - -A script to expand email addresses into their full name. It is -generally useful when using with the @file{lostaltmail} script, but is a -useful tools otherwise. - -@example -$ expn -v ezk@@cs.columbia.edu -ezk@@cs.columbia.edu -> - ezk@@shekel.mcl.cs.columbia.edu -ezk@@shekel.mcl.cs.columbia.edu -> - Erez Zadok <"| /usr/local/mh/lib/slocal -user ezk || exit 75> - Erez Zadok <\ezk> - Erez Zadok -@end example - -@c ---------------------------------------------------------------- -@node fix-amd-map, fixmount, expn, Assorted Tools +@node fix-amd-map, fixmount, ctl-hlfsd, Assorted Tools @comment node-name, next, previous, up @section fix-amd-map @pindex fix-amd-map @@ -8581,7 +8640,7 @@ XXX: This section needs to be updated @comment node-name, next, previous, up @unnumbered Acknowledgments & Trademarks -Many thanks to the @email{am-utils@@am-utils.org,Am-Utils Users} +Many thanks to the Am-Utils Users mailing list through the months developing am-utils. These members have contributed to the discussions, ideas, code and documentation, and subjected their systems to alpha quality code. Special thanks go @@ -8589,10 +8648,10 @@ to those @uref{http://www.am-utils.org/docs/am-utils/AUTHORS.txt,authors} who ha submitted patches, and especially to the maintainers: @itemize @bullet -@item @email{ezk@@cs.sunysb.edu,Erez Zadok} -@item @email{ib42@@cs.columbia.edu,Ion Badulescu} -@item @email{ro@@techfak.uni-bielefeld.de,Rainer Orth} -@item @email{nick.williams@@morganstanley.com,Nick Williams} +@item @uref{http://www.cs.sunysb.edu/~ezk,Erez Zadok} +@item @email{ionut AT badula.org,Ion Badulescu} +@item @email{ro AT techfak.uni-bielefeld.de,Rainer Orth} +@item @email{nick.williams AT morganstanley.com,Nick Williams} @end itemize Thanks to the Formal Methods Group at Imperial College for suffering @@ -8602,7 +8661,7 @@ Thanks to the many people who have helped with the development of @i{Amd}, especially Piete Brooks at the Cambridge University Computing Lab for many hours of testing, experimentation and discussion. -Thanks to the older @email{amd-workers@@majordomo.glue.umd.edu,Amd +Thanks to the older @email{amd-workers AT majordomo.glue.umd.edu,Amd Workers} mailing list (now defunct) members for many suggestions and bug reports to @i{Amd}. diff --git a/contrib/amd/doc/stamp-vti b/contrib/amd/doc/stamp-vti index 41b19a30d5c..9a4feda60f5 100644 --- a/contrib/amd/doc/stamp-vti +++ b/contrib/amd/doc/stamp-vti @@ -1,4 +1,4 @@ -@set UPDATED 20 April 2006 -@set UPDATED-MONTH April 2006 -@set EDITION 6.1.5 -@set VERSION 6.1.5 +@set UPDATED 28 October 2014 +@set UPDATED-MONTH October 2014 +@set EDITION 6.2 +@set VERSION 6.2 diff --git a/contrib/amd/doc/texinfo.tex b/contrib/amd/doc/texinfo.tex index e758cedae7e..85f184cc4cb 100644 --- a/contrib/amd/doc/texinfo.tex +++ b/contrib/amd/doc/texinfo.tex @@ -1,18 +1,18 @@ % texinfo.tex -- TeX macros to handle Texinfo files. -% +% % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2004-09-06.16} +\def\texinfoversion{2013-02-01.11} % -% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, -% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software -% Foundation, Inc. +% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +% 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. % -% This texinfo.tex file is free software; you can redistribute it and/or +% This texinfo.tex file is free software: you can redistribute it and/or % modify it under the terms of the GNU General Public License as -% published by the Free Software Foundation; either version 2, or (at -% your option) any later version. +% published by the Free Software Foundation, either version 3 of the +% License, or (at your option) any later version. % % This texinfo.tex file is distributed in the hope that it will be % useful, but WITHOUT ANY WARRANTY; without even the implied warranty @@ -20,19 +20,18 @@ % General Public License for more details. % % You should have received a copy of the GNU General Public License -% along with this texinfo.tex file; see the file COPYING. If not, write -% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -% Boston, MA 02111-1307, USA. +% along with this program. If not, see . % % As a special exception, when this file is read by TeX when processing % a Texinfo source document, you may use the result without -% restriction. (This has been our intent since Texinfo was invented.) +% restriction. This Exception is an additional permission under section 7 +% of the GNU General Public License, version 3 ("GPLv3"). % % Please try the latest version of texinfo.tex before submitting bug % reports; you can get the latest version from: -% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or -% ftp://tug.org/tex/texinfo.tex -% (and all CTAN mirrors, see http://www.ctan.org). +% http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or +% http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or +% http://www.gnu.org/software/texinfo/ (the Texinfo home page) % The texinfo.tex in any given distribution could well be out % of date, so if that's what you're using, please check. % @@ -67,7 +66,6 @@ \everyjob{\message{[Texinfo version \texinfoversion]}% \catcode`+=\active \catcode`\_=\active} -\message{Basics,} \chardef\other=12 % We never want plain's \outer definition of \+ in Texinfo. @@ -89,15 +87,19 @@ \let\ptexhat=^ \let\ptexi=\i \let\ptexindent=\indent -\let\ptexnoindent=\noindent \let\ptexinsert=\insert \let\ptexlbrace=\{ \let\ptexless=< +\let\ptexnewwrite\newwrite +\let\ptexnoindent=\noindent \let\ptexplus=+ +\let\ptexraggedright=\raggedright \let\ptexrbrace=\} \let\ptexslash=\/ \let\ptexstar=\* \let\ptext=\t +\let\ptextop=\top +{\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode % If this character appears in an error message or help string, it % starts a new line in the output. @@ -115,10 +117,11 @@ % Set up fixed words for English if not already set. \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putworderror\undefined \gdef\putworderror{error}\fi \ifx\putwordfile\undefined \gdef\putwordfile{file}\fi \ifx\putwordin\undefined \gdef\putwordin{in}\fi -\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi -\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi \ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi \ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi \ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi @@ -152,20 +155,25 @@ \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi -% In some macros, we cannot use the `\? notation---the left quote is -% in some cases the escape char. +% Since the category of space is not known, we have to be careful. +\chardef\spacecat = 10 +\def\spaceisspace{\catcode`\ =\spacecat} + +% sometimes characters are active, so we need control sequences. +\chardef\ampChar = `\& \chardef\colonChar = `\: \chardef\commaChar = `\, +\chardef\dashChar = `\- \chardef\dotChar = `\. \chardef\exclamChar= `\! +\chardef\hashChar = `\# +\chardef\lquoteChar= `\` \chardef\questChar = `\? +\chardef\rquoteChar= `\' \chardef\semiChar = `\; +\chardef\slashChar = `\/ \chardef\underChar = `\_ -\chardef\spaceChar = `\ % -\chardef\spacecat = 10 -\def\spaceisspace{\catcode\spaceChar=\spacecat} - % Ignore a token. % \def\gobble#1{} @@ -194,36 +202,7 @@ % that mark overfull boxes (in case you have decided % that the text looks ok even though it passes the margin). % -\def\finalout{\overfullrule=0pt} - -% @| inserts a changebar to the left of the current line. It should -% surround any changed text. This approach does *not* work if the -% change spans more than two lines of output. To handle that, we would -% have adopt a much more difficult approach (putting marks into the main -% vertical list for the beginning and end of each change). -% -\def\|{% - % \vadjust can only be used in horizontal mode. - \leavevmode - % - % Append this vertical mode material after the current line in the output. - \vadjust{% - % We want to insert a rule with the height and depth of the current - % leading; that is exactly what \strutbox is supposed to record. - \vskip-\baselineskip - % - % \vadjust-items are inserted at the left edge of the type. So - % the \llap here moves out into the left-hand margin. - \llap{% - % - % For a thicker or thinner bar, change the `1pt'. - \vrule height\baselineskip width1pt - % - % This is the space between the bar and the text. - \hskip 12pt - }% - }% -} +\def\finalout{\overfullrule=0pt } % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, @@ -241,7 +220,7 @@ \tracingmacros2 \tracingrestores1 \showboxbreadth\maxdimen \showboxdepth\maxdimen - \ifx\eTeXversion\undefined\else % etex gives us more logging + \ifx\eTeXversion\thisisundefined\else % etex gives us more logging \tracingscantokens1 \tracingifs1 \tracinggroups1 @@ -252,6 +231,13 @@ \errorcontextlines16 }% +% @errormsg{MSG}. Do the index-like expansions on MSG, but if things +% aren't perfect, it's not the end of the world, being an error message, +% after all. +% +\def\errormsg{\begingroup \indexnofonts \doerrormsg} +\def\doerrormsg#1{\errmessage{#1}} + % add check for \lastpenalty to plain's definitions. If the last thing % we did was a \nobreak, we don't want to insert more space. % @@ -262,7 +248,6 @@ \def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount \removelastskip\penalty-200\bigskip\fi\fi} -% For @cropmarks command. % Do @cropmarks to get crop marks. % \newif\ifcropmarks @@ -276,6 +261,50 @@ \newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in +% Output a mark which sets \thischapter, \thissection and \thiscolor. +% We dump everything together because we only have one kind of mark. +% This works because we only use \botmark / \topmark, not \firstmark. +% +% A mark contains a subexpression of the \ifcase ... \fi construct. +% \get*marks macros below extract the needed part using \ifcase. +% +% Another complication is to let the user choose whether \thischapter +% (\thissection) refers to the chapter (section) in effect at the top +% of a page, or that at the bottom of a page. The solution is +% described on page 260 of The TeXbook. It involves outputting two +% marks for the sectioning macros, one before the section break, and +% one after. I won't pretend I can describe this better than DEK... +\def\domark{% + \toks0=\expandafter{\lastchapterdefs}% + \toks2=\expandafter{\lastsectiondefs}% + \toks4=\expandafter{\prevchapterdefs}% + \toks6=\expandafter{\prevsectiondefs}% + \toks8=\expandafter{\lastcolordefs}% + \mark{% + \the\toks0 \the\toks2 + \noexpand\or \the\toks4 \the\toks6 + \noexpand\else \the\toks8 + }% +} +% \topmark doesn't work for the very first chapter (after the title +% page or the contents), so we use \firstmark there -- this gets us +% the mark with the chapter defs, unless the user sneaks in, e.g., +% @setcolor (or @url, or @link, etc.) between @contents and the very +% first @chapter. +\def\gettopheadingmarks{% + \ifcase0\topmark\fi + \ifx\thischapter\empty \ifcase0\firstmark\fi \fi +} +\def\getbottomheadingmarks{\ifcase1\botmark\fi} +\def\getcolormarks{\ifcase2\topmark\fi} + +% Avoid "undefined control sequence" errors. +\def\lastchapterdefs{} +\def\lastsectiondefs{} +\def\prevchapterdefs{} +\def\prevsectiondefs{} +\def\lastcolordefs{} + % Main output routine. \chardef\PAGE = 255 \output = {\onepageout{\pagecontents\PAGE}} @@ -293,7 +322,9 @@ % % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). + \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% % {% @@ -301,10 +332,14 @@ % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % - \escapechar = `\\ % use backslash in output files. \indexdummies % don't expand commands in the output. \normalturnoffactive % \ in index entries must not stay \, e.g., if - % the page break happens to be in the middle of an example. + % the page break happens to be in the middle of an example. + % We don't want .vr (or whatever) entries like this: + % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} + % "\acronym" won't work when it's read back in; + % it needs to be + % {\code {{\tt \backslashcurfont }acronym} \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi @@ -332,9 +367,9 @@ \pagebody{#1}% \ifdim\ht\footlinebox > 0pt % Only leave this space if the footline is nonempty. - % (We lessened \vsize for it in \oddfootingxxx.) + % (We lessened \vsize for it in \oddfootingyyy.) % The \baselineskip=24pt in plain's \makefootline has no effect. - \vskip 2\baselineskip + \vskip 24pt \unvbox\footlinebox \fi % @@ -355,7 +390,7 @@ \egroup % \vbox from first cropmarks clause \fi }% end of \shipout\vbox - }% end of group with \normalturnoffactive + }% end of group with \indexdummies \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } @@ -368,7 +403,7 @@ % marginal hacks, juha@viisa.uucp (Juha Takala) \ifvoid\margin\else % marginal info is present \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi -\dimen@=\dp#1 \unvbox#1 +\dimen@=\dp#1\relax \unvbox#1\relax \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } @@ -390,7 +425,7 @@ % \def\parsearg{\parseargusing{}} \def\parseargusing#1#2{% - \def\next{#2}% + \def\argtorun{#2}% \begingroup \obeylines \spaceisspace @@ -409,7 +444,7 @@ \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} -% Each occurence of `\^^M' or `\^^M' is replaced by a single space. +% Each occurrence of `\^^M' or `\^^M' is replaced by a single space. % % \argremovec might leave us with trailing space, e.g., % @end itemize @c foo @@ -421,8 +456,7 @@ \def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% \def\temp{#3}% \ifx\temp\empty - % We cannot use \next here, as it holds the macro to run; - % thus we reuse \temp. + % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: \let\temp\finishparsearg \else \let\temp\argcheckspaces @@ -434,14 +468,14 @@ % If a _delimited_ argument is enclosed in braces, they get stripped; so % to get _exactly_ the rest of the line, we had to prevent such situation. % We prepended an \empty token at the very beginning and we expand it now, -% just before passing the control to \next. -% (Similarily, we have to think about #3 of \argcheckspacesY above: it is +% just before passing the control to \argtorun. +% (Similarly, we have to think about #3 of \argcheckspacesY above: it is % either the null string, or it ends with \^^M---thus there is no danger % that a pair of braces would be stripped. % % But first, we have to remove the trailing space token. % -\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}} +\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} % \parseargdef\foo{...} % is roughly equivalent to @@ -492,12 +526,12 @@ % used to check whether the current environment is the one expected. % % Non-false conditionals (@iftex, @ifset) don't fit into this, so they -% are not treated as enviroments; they don't open a group. (The +% are not treated as environments; they don't open a group. (The % implementation of @end takes care not to call \endgroup in this % special case.) -% At runtime, environments start with this: +% At run-time, environments start with this: \def\startenvironment#1{\begingroup\def\thisenv{#1}} % initialize \let\thisenv\empty @@ -515,7 +549,7 @@ \fi } -% Evironment mismatch, #1 expected: +% Environment mismatch, #1 expected: \def\badenverr{% \errhelp = \EMsimple \errmessage{This command can appear only \inenvironment\temp, @@ -523,7 +557,7 @@ } \def\inenvironment#1{% \ifx#1\empty - out of any environment% + outside of any environment% \else in environment \expandafter\string#1% \fi @@ -535,7 +569,7 @@ \parseargdef\end{% \if 1\csname iscond.#1\endcsname \else - % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 + % The general wording of \badenverr may not be ideal. \expandafter\checkenv\csname#1\endcsname \csname E#1\endcsname \endgroup @@ -545,85 +579,6 @@ \newhelp\EMsimple{Press RETURN to continue.} -%% Simple single-character @ commands - -% @@ prints an @ -% Kludge this until the fonts are right (grr). -\def\@{{\tt\char64}} - -% This is turned off because it was never documented -% and you can use @w{...} around a quote to suppress ligatures. -%% Define @` and @' to be the same as ` and ' -%% but suppressing ligatures. -%\def\`{{`}} -%\def\'{{'}} - -% Used to generate quoted braces. -\def\mylbrace {{\tt\char123}} -\def\myrbrace {{\tt\char125}} -\let\{=\mylbrace -\let\}=\myrbrace -\begingroup - % Definitions to produce \{ and \} commands for indices, - % and @{ and @} for the aux file. - \catcode`\{ = \other \catcode`\} = \other - \catcode`\[ = 1 \catcode`\] = 2 - \catcode`\! = 0 \catcode`\\ = \other - !gdef!lbracecmd[\{]% - !gdef!rbracecmd[\}]% - !gdef!lbraceatcmd[@{]% - !gdef!rbraceatcmd[@}]% -!endgroup - -% @comma{} to avoid , parsing problems. -\let\comma = , - -% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent -% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. -\let\, = \c -\let\dotaccent = \. -\def\ringaccent#1{{\accent23 #1}} -\let\tieaccent = \t -\let\ubaraccent = \b -\let\udotaccent = \d - -% Other special characters: @questiondown @exclamdown @ordf @ordm -% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. -\def\questiondown{?`} -\def\exclamdown{!`} -\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} -\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} - -% Dotless i and dotless j, used for accents. -\def\imacro{i} -\def\jmacro{j} -\def\dotless#1{% - \def\temp{#1}% - \ifx\temp\imacro \ptexi - \else\ifx\temp\jmacro \j - \else \errmessage{@dotless can be used only with i or j}% - \fi\fi -} - -% The \TeX{} logo, as in plain, but resetting the spacing so that a -% period following counts as ending a sentence. (Idea found in latex.) -% -\edef\TeX{\TeX \spacefactor=1000 } - -% @LaTeX{} logo. Not quite the same results as the definition in -% latex.ltx, since we use a different font for the raised A; it's most -% convenient for us to use an explicitly smaller font, rather than using -% the \scriptstyle font (since we don't reset \scriptstyle and -% \scriptscriptstyle). -% -\def\LaTeX{% - L\kern-.36em - {\setbox0=\hbox{T}% - \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% - \kern-.15em - \TeX -} - % Be sure we're in horizontal mode when doing a tie, since we make space % equivalent to this in @example-like environments. Otherwise, a space % at the beginning of a line will start with \penalty -- and @@ -640,19 +595,34 @@ \def\:{\spacefactor=1000 } % @* forces a line break. -\def\*{\hfil\break\hbox{}\ignorespaces} +\def\*{\unskip\hfil\break\hbox{}\ignorespaces} % @/ allows a line break. \let\/=\allowbreak % @. is an end-of-sentence period. -\def\.{.\spacefactor=3000 } +\def\.{.\spacefactor=\endofsentencespacefactor\space} % @! is an end-of-sentence bang. -\def\!{!\spacefactor=3000 } +\def\!{!\spacefactor=\endofsentencespacefactor\space} % @? is an end-of-sentence query. -\def\?{?\spacefactor=3000 } +\def\?{?\spacefactor=\endofsentencespacefactor\space} + +% @frenchspacing on|off says whether to put extra space after punctuation. +% +\def\onword{on} +\def\offword{off} +% +\parseargdef\frenchspacing{% + \def\temp{#1}% + \ifx\temp\onword \plainfrenchspacing + \else\ifx\temp\offword \plainnonfrenchspacing + \else + \errhelp = \EMsimple + \errmessage{Unknown @frenchspacing option `\temp', must be on|off}% + \fi\fi +} % @w prevents a word break. Without the \leavevmode, @w at the % beginning of a paragraph, when TeX is still in vertical mode, would @@ -732,15 +702,6 @@ where each line of input produces a line of output.} \newdimen\mil \mil=0.001in -% Old definition--didn't work. -%\parseargdef\need{\par % -%% This method tries to make TeX break the page naturally -%% if the depth of the box does not fit. -%{\baselineskip=0pt% -%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak -%\prevdepth=-1000pt -%}} - \parseargdef\need{% % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. @@ -804,7 +765,7 @@ where each line of input produces a line of output.} % @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current % paragraph. For more general purposes, use the \margin insertion -% class. WHICH is `l' or `r'. +% class. WHICH is `l' or `r'. Not documented, written for gawk manual. % \newskip\inmarginspacing \inmarginspacing=1cm \def\strutdepth{\dp\strutbox} @@ -851,15 +812,51 @@ where each line of input produces a line of output.} \temp } -% @include file insert text of that file as input. +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). This command +% is not documented, not supported, and doesn't work. +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% @include FILE -- \input text of FILE. % \def\include{\parseargusing\filenamecatcodes\includezzz} \def\includezzz#1{% \pushthisfilestack \def\thisfile{#1}% {% - \makevalueexpandable - \def\temp{\input #1 }% + \makevalueexpandable % we want to expand any @value in FILE. + \turnoffactive % and allow special characters in the expansion + \indexnofonts % Allow `@@' and other weird things in file names. + \wlog{texinfo.tex: doing @include of #1^^J}% + \edef\temp{\noexpand\input #1 }% + % + % This trickery is to read FILE outside of a group, in case it makes + % definitions, etc. \expandafter }\temp \popthisfilestack @@ -874,6 +871,8 @@ where each line of input produces a line of output.} \catcode`>=\other \catcode`+=\other \catcode`-=\other + \catcode`\`=\other + \catcode`\'=\other } \def\pushthisfilestack{% @@ -889,7 +888,7 @@ where each line of input produces a line of output.} \def\popthisfilestack{\errthisfilestackempty} \def\errthisfilestackempty{\errmessage{Internal error: the stack of filenames is empty.}} - +% \def\thisfile{} % @center line @@ -897,36 +896,46 @@ where each line of input produces a line of output.} % \parseargdef\center{% \ifhmode - \let\next\centerH + \let\centersub\centerH \else - \let\next\centerV + \let\centersub\centerV \fi - \next{\hfil \ignorespaces#1\unskip \hfil}% + \centersub{\hfil \ignorespaces#1\unskip \hfil}% + \let\centersub\relax % don't let the definition persist, just in case } -\def\centerH#1{% - {% - \hfil\break - \advance\hsize by -\leftskip - \advance\hsize by -\rightskip - \line{#1}% - \break - }% +\def\centerH#1{{% + \hfil\break + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{#1}% + \break +}} +% +\newcount\centerpenalty +\def\centerV#1{% + % The idea here is the same as in \startdefun, \cartouche, etc.: if + % @center is the first thing after a section heading, we need to wipe + % out the negative parskip inserted by \sectionheading, but still + % prevent a page break here. + \centerpenalty = \lastpenalty + \ifnum\centerpenalty>10000 \vskip\parskip \fi + \ifnum\centerpenalty>9999 \penalty\centerpenalty \fi + \line{\kern\leftskip #1\kern\rightskip}% } -\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} % @sp n outputs n lines of vertical space - +% \parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment - +% \def\comment{\begingroup \catcode`\^^M=\other% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% \commentxxx} {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} - +% \let\c=\comment % @paragraphindent NCHARS @@ -1019,86 +1028,6 @@ where each line of input produces a line of output.} } -% @asis just yields its argument. Used with @table, for example. -% -\def\asis#1{#1} - -% @math outputs its argument in math mode. -% -% One complication: _ usually means subscripts, but it could also mean -% an actual _ character, as in @math{@var{some_variable} + 1}. So make -% _ active, and distinguish by seeing if the current family is \slfam, -% which is what @var uses. -{ - \catcode\underChar = \active - \gdef\mathunderscore{% - \catcode\underChar=\active - \def_{\ifnum\fam=\slfam \_\else\sb\fi}% - } -} -% Another complication: we want \\ (and @\) to output a \ character. -% FYI, plain.tex uses \\ as a temporary control sequence (why?), but -% this is not advertised and we don't care. Texinfo does not -% otherwise define @\. -% -% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. -\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} -% -\def\math{% - \tex - \mathunderscore - \let\\ = \mathbackslash - \mathactive - $\finishmath -} -\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. - -% Some active characters (such as <) are spaced differently in math. -% We have to reset their definitions in case the @math was an argument -% to a command which sets the catcodes (such as @item or @section). -% -{ - \catcode`^ = \active - \catcode`< = \active - \catcode`> = \active - \catcode`+ = \active - \gdef\mathactive{% - \let^ = \ptexhat - \let< = \ptexless - \let> = \ptexgtr - \let+ = \ptexplus - } -} - -% @bullet and @minus need the same treatment as @math, just above. -\def\bullet{$\ptexbullet$} -\def\minus{$-$} - -% @dots{} outputs an ellipsis using the current font. -% We do .5em per period so that it has the same spacing in a typewriter -% font as three actual period characters. -% -\def\dots{% - \leavevmode - \hbox to 1.5em{% - \hskip 0pt plus 0.25fil - .\hfil.\hfil.% - \hskip 0pt plus 0.5fil - }% -} - -% @enddots{} is an end-of-sentence ellipsis. -% -\def\enddots{% - \dots - \spacefactor=3000 -} - -% @comma{} is so commas can be inserted into text without messing up -% Texinfo's parsing. -% -\let\comma = , - % @refill is a no-op. \let\refill=\relax @@ -1163,9 +1092,8 @@ where each line of input produces a line of output.} \newif\ifpdfmakepagedest % when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 -% can be set). So we test for \relax and 0 as well as \undefined, -% borrowed from ifpdf.sty. -\ifx\pdfoutput\undefined +% can be set). So we test for \relax and 0 as well as being undefined. +\ifx\pdfoutput\thisisundefined \else \ifx\pdfoutput\relax \else @@ -1175,40 +1103,157 @@ where each line of input produces a line of output.} \fi \fi \fi -% + +% PDF uses PostScript string constants for the names of xref targets, +% for display in the outlines, and in other places. Thus, we have to +% double any backslashes. Otherwise, a name like "\node" will be +% interpreted as a newline (\n), followed by o, d, e. Not good. +% +% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and +% related messages. The final outcome is that it is up to the TeX user +% to double the backslashes and otherwise make the string valid, so +% that's what we do. pdftex 1.30.0 (ca.2005) introduced a primitive to +% do this reliably, so we use it. + +% #1 is a control sequence in which to do the replacements, +% which we \xdef. +\def\txiescapepdf#1{% + \ifx\pdfescapestring\thisisundefined + % No primitive available; should we give a warning or log? + % Many times it won't matter. + \else + % The expandable \pdfescapestring primitive escapes parentheses, + % backslashes, and other special chars. + \xdef#1{\pdfescapestring{#1}}% + \fi +} + +\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images +with PDF output, and none of those formats could be found. (.eps cannot +be supported due to the design of the PDF format; use regular TeX (DVI +output) for that.)} + \ifpdf - \input pdfcolor - \pdfcatalog{/PageMode /UseOutlines}% + % + % Color manipulation macros based on pdfcolor.tex, + % except using rgb instead of cmyk; the latter is said to render as a + % very dark gray on-screen and a very dark halftone in print, instead + % of actual black. + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % + % k sets the color for filling (usual text, etc.); + % K sets the color for stroking (thin rules, e.g., normal _'s). + \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} + % + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\setcolor#1{% + \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + } + % + \def\maincolor{\rgbBlack} + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\lastcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % + \pdfcatalog{/PageMode /UseOutlines} + % + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). \def\dopdfimage#1#2#3{% - \def\imagewidth{#2}% - \def\imageheight{#3}% - % without \immediate, pdftex seg faults when the same image is + \def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% + \def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % + % pdftex (and the PDF format) support .pdf, .png, .jpg (among + % others). Let's try in that order, PDF first since if + % someone has a scalable image, presumably better to use that than a + % bitmap. + \let\pdfimgext=\empty + \begingroup + \openin 1 #1.pdf \ifeof 1 + \openin 1 #1.PDF \ifeof 1 + \openin 1 #1.png \ifeof 1 + \openin 1 #1.jpg \ifeof 1 + \openin 1 #1.jpeg \ifeof 1 + \openin 1 #1.JPG \ifeof 1 + \errhelp = \nopdfimagehelp + \errmessage{Could not find image file #1 for pdf}% + \else \gdef\pdfimgext{JPG}% + \fi + \else \gdef\pdfimgext{jpeg}% + \fi + \else \gdef\pdfimgext{jpg}% + \fi + \else \gdef\pdfimgext{png}% + \fi + \else \gdef\pdfimgext{PDF}% + \fi + \else \gdef\pdfimgext{pdf}% + \fi + \closein 1 + \endgroup + % + % without \immediate, ancient pdftex seg faults when the same image is % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) \ifnum\pdftexversion < 14 \immediate\pdfimage \else \immediate\pdfximage \fi - \ifx\empty\imagewidth\else width \imagewidth \fi - \ifx\empty\imageheight\else height \imageheight \fi + \ifdim \wd0 >0pt width \pdfimagewidth \fi + \ifdim \wd2 >0pt height \pdfimageheight \fi \ifnum\pdftexversion<13 - #1.pdf% + #1.\pdfimgext \else - {#1.pdf}% + {#1.\pdfimgext}% \fi \ifnum\pdftexversion < 14 \else \pdfrefximage \pdflastximage \fi} + % \def\pdfmkdest#1{{% - % We have to set dummies so commands such as @code in a section title - % aren't expanded. - \atdummies - \normalturnoffactive - \pdfdest name{#1} xyz% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \indexnofonts + \turnoffactive + \makevalueexpandable + \def\pdfdestname{#1}% + \txiescapepdf\pdfdestname + \safewhatsit{\pdfdest name{\pdfdestname} xyz}% }} + % + % used to mark target names; must be expandable. \def\pdfmkpgn#1{#1} - \let\linkcolor = \Blue % was Cyan, but that seems light? - \def\endlink{\Black\pdfendlink} + % + % by default, use a color that is dark enough to print on paper as + % nearly black, but still distinguishable for online viewing. + \def\urlcolor{\rgbDarkRed} + \def\linkcolor{\rgbDarkRed} + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% @@ -1217,38 +1262,44 @@ where each line of input produces a line of output.} \advance\tempnum by 1 \expandafter\xdef\csname#1\endcsname{\the\tempnum}} % - % #1 is the section text. #2 is the pdf expression for the number - % of subentries (or empty, for subsubsections). #3 is the node - % text, which might be empty if this toc entry had no - % corresponding node. #4 is the page number. + % #1 is the section text, which is what will be displayed in the + % outline by the pdf viewer. #2 is the pdf expression for the number + % of subentries (or empty, for subsubsections). #3 is the node text, + % which might be empty if this toc entry had no corresponding node. + % #4 is the page number % \def\dopdfoutline#1#2#3#4{% % Generate a link to the node text if that exists; else, use the % page number. We could generate a destination for the section % text in the case where a section has no node, but it doesn't - % seem worthwhile, since most documents are normally structured. - \def\pdfoutlinedest{#3}% - \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}\fi + % seem worth the trouble, since most documents are normally structured. + \edef\pdfoutlinedest{#3}% + \ifx\pdfoutlinedest\empty + \def\pdfoutlinedest{#4}% + \else + \txiescapepdf\pdfoutlinedest + \fi % - \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}% + % Also escape PDF chars in the display string. + \edef\pdfoutlinetext{#1}% + \txiescapepdf\pdfoutlinetext + % + \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% } % \def\pdfmakeoutlines{% \begingroup - % Thanh's hack / proper braces in bookmarks - \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace - \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace - % % Read toc silently, to get counts of subentries for \pdfoutline. + \def\partentry##1##2##3##4{}% ignore parts in the outlines \def\numchapentry##1##2##3##4{% \def\thischapnum{##2}% - \let\thissecnum\empty - \let\thissubsecnum\empty + \def\thissecnum{0}% + \def\thissubsecnum{0}% }% \def\numsecentry##1##2##3##4{% \advancenumber{chap\thischapnum}% \def\thissecnum{##2}% - \let\thissubsecnum\empty + \def\thissubsecnum{0}% }% \def\numsubsecentry##1##2##3##4{% \advancenumber{sec\thissecnum}% @@ -1257,9 +1308,9 @@ where each line of input produces a line of output.} \def\numsubsubsecentry##1##2##3##4{% \advancenumber{subsec\thissubsecnum}% }% - \let\thischapnum\empty - \let\thissecnum\empty - \let\thissubsecnum\empty + \def\thischapnum{0}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% % % use \def rather than \let here because we redefine \chapentry et % al. a second time, below. @@ -1271,7 +1322,7 @@ where each line of input produces a line of output.} \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% - \input \jobname.toc + \readdatafile{toc}% % % Read toc second time, this time actually producing the outlines. % The `-' means take the \expnumber as the absolute number of @@ -1293,64 +1344,63 @@ where each line of input produces a line of output.} % Latin 2 (0xea) gets translated to a | character. Info from % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. % - % xx to do this right, we have to translate 8-bit characters to - % their "best" equivalent, based on the @documentencoding. Right - % now, I guess we'll just let the pdf reader have its way. + % TODO this right, we have to translate 8-bit characters to + % their "best" equivalent, based on the @documentencoding. Too + % much work for too little return. Just use the ASCII equivalents + % we use for the index sort strings. + % \indexnofonts - \turnoffactive - \input \jobname.toc + \setupdatafile + % We can have normal brace characters in the PDF outlines, unlike + % Texinfo index files. So set that up. + \def\{{\lbracecharliteral}% + \def\}{\rbracecharliteral}% + \catcode`\\=\active \otherbackslash + \input \tocreadfilename \endgroup } + {\catcode`[=1 \catcode`]=2 + \catcode`{=\other \catcode`}=\other + \gdef\lbracecharliteral[{]% + \gdef\rbracecharliteral[}]% + ] % - \def\makelinks #1,{% - \def\params{#1}\def\E{END}% - \ifx\params\E - \let\nextmakelinks=\relax - \else - \let\nextmakelinks=\makelinks - \ifnum\lnkcount>0,\fi - \picknum{#1}% - \startlink attr{/Border [0 0 0]} - goto name{\pdfmkpgn{\the\pgn}}% - \linkcolor #1% - \advance\lnkcount by 1% - \endlink - \fi - \nextmakelinks - } - \def\picknum#1{\expandafter\pn#1} - \def\pn#1{% - \def\p{#1}% - \ifx\p\lbrace - \let\nextpn=\ppn - \else - \let\nextpn=\ppnn - \def\first{#1} - \fi - \nextpn - } - \def\ppn#1{\pgn=#1\gobble} - \def\ppnn{\pgn=\first} - \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,} \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces - \ifx\p\space\else\addtokens{\filename}{\PP}% - \advance\filenamelength by 1 - \fi + \addtokens{\filename}{\PP}% + \advance\filenamelength by 1 \fi \nextsp} - \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \def\getfilename#1{% + \filenamelength=0 + % If we don't expand the argument now, \skipspaces will get + % snagged on things like "@value{foo}". + \edef\temp{#1}% + \expandafter\skipspaces\temp|\relax + } \ifnum\pdftexversion < 14 \let \startlink \pdfannotlink \else \let \startlink \pdfstartlink \fi + % make a live url in pdf output. \def\pdfurl#1{% \begingroup - \normalturnoffactive\def\@{@}% + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty \makevalueexpandable - \leavevmode\Red + % do we want to go so far as to use \indexnofonts instead of just + % special-casing \var here? + \def\var##1{##1}% + % + \leavevmode\setcolor{\urlcolor}% \startlink attr{/Border [0 0 0]}% user{/Subtype /Link /A << /S /URI /URI (#1) >>}% \endgroup} @@ -1377,13 +1427,15 @@ where each line of input produces a line of output.} {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} - \linkcolor #1\endlink} + \setcolor{\linkcolor}#1\endlink} \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else + % non-pdf mode \let\pdfmkdest = \gobble \let\pdfurl = \gobble \let\endlink = \relax - \let\linkcolor = \relax + \let\setcolor = \gobble + \let\pdfsetcolor = \gobble \let\pdfmakeoutlines = \relax \fi % \ifx\pdfoutput @@ -1406,9 +1458,13 @@ where each line of input produces a line of output.} \def\rm{\fam=0 \setfontstyle{rm}} \def\it{\fam=\itfam \setfontstyle{it}} \def\sl{\fam=\slfam \setfontstyle{sl}} -\def\bf{\fam=\bffam \setfontstyle{bf}} +\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} \def\tt{\fam=\ttfam \setfontstyle{tt}} +% Unfortunately, we have to override this for titles and the like, since +% in those cases "rm" is bold. Sigh. +\def\rmisbold{\rm\def\curfontstyle{bf}} + % Texinfo sort of supports the sans serif font style, which plain TeX does not. % So we set up a \sf. \newfam\sffam @@ -1418,8 +1474,6 @@ where each line of input produces a line of output.} % We don't need math for this font style. \def\ttsl{\setfontstyle{ttsl}} -% Default leading. -\newdimen\textleading \textleading = 13.2pt % Set the baselineskip to #1, and the lineskip and strut size % correspondingly. There is no deep meaning behind these magic numbers @@ -1429,8 +1483,13 @@ where each line of input produces a line of output.} \def\strutheightpercent{.70833} \def\strutdepthpercent {.29167} % +% can get a sort of poor man's double spacing by redefining this. +\def\baselinefactor{1} +% +\newdimen\textleading \def\setleading#1{% - \normalbaselineskip = #1\relax + \dimen0 = #1\relax + \normalbaselineskip = \baselinefactor\dimen0 \normallineskip = \lineskipfactor\normalbaselineskip \normalbaselines \setbox\strutbox =\hbox{% @@ -1439,20 +1498,295 @@ where each line of input produces a line of output.} }% } -% Set the font macro #1 to the font named #2, adding on the -% specified font prefix (normally `cm'). -% #3 is the font's design size, #4 is a scale factor -\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} +% PDF CMaps. See also LaTeX's t1.cmap. +% +% do nothing with this by default. +\expandafter\let\csname cmapOT1\endcsname\gobble +\expandafter\let\csname cmapOT1IT\endcsname\gobble +\expandafter\let\csname cmapOT1TT\endcsname\gobble + +% if we are producing pdf, and we have \pdffontattr, then define cmaps. +% (\pdffontattr was introduced many years ago, but people still run +% older pdftex's; it's easy to conditionalize, so we do.) +\ifpdf \ifx\pdffontattr\thisisundefined \else + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1-0) +%%Title: (TeX-OT1-0 TeX OT1 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1) +/Supplement 0 +>> def +/CMapName /TeX-OT1-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<23> <26> <0023> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +40 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1IT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1IT-0) +%%Title: (TeX-OT1IT-0 TeX OT1IT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1IT) +/Supplement 0 +>> def +/CMapName /TeX-OT1IT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +8 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<25> <26> <0025> +<28> <3B> <0028> +<3F> <5B> <003F> +<5D> <5E> <005D> +<61> <7A> <0061> +<7B> <7C> <2013> +endbfrange +42 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <00660066> +<0C> <00660069> +<0D> <0066006C> +<0E> <006600660069> +<0F> <00660066006C> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<21> <0021> +<22> <201D> +<23> <0023> +<24> <00A3> +<27> <2019> +<3C> <00A1> +<3D> <003D> +<3E> <00BF> +<5C> <201C> +<5F> <02D9> +<60> <2018> +<7D> <02DD> +<7E> <007E> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1IT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +% +% \cmapOT1TT + \begingroup + \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. + \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap +%%DocumentNeededResources: ProcSet (CIDInit) +%%IncludeResource: ProcSet (CIDInit) +%%BeginResource: CMap (TeX-OT1TT-0) +%%Title: (TeX-OT1TT-0 TeX OT1TT 0) +%%Version: 1.000 +%%EndComments +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (TeX) +/Ordering (OT1TT) +/Supplement 0 +>> def +/CMapName /TeX-OT1TT-0 def +/CMapType 2 def +1 begincodespacerange +<00> <7F> +endcodespacerange +5 beginbfrange +<00> <01> <0393> +<09> <0A> <03A8> +<21> <26> <0021> +<28> <5F> <0028> +<61> <7E> <0061> +endbfrange +32 beginbfchar +<02> <0398> +<03> <039B> +<04> <039E> +<05> <03A0> +<06> <03A3> +<07> <03D2> +<08> <03A6> +<0B> <2191> +<0C> <2193> +<0D> <0027> +<0E> <00A1> +<0F> <00BF> +<10> <0131> +<11> <0237> +<12> <0060> +<13> <00B4> +<14> <02C7> +<15> <02D8> +<16> <00AF> +<17> <02DA> +<18> <00B8> +<19> <00DF> +<1A> <00E6> +<1B> <0153> +<1C> <00F8> +<1D> <00C6> +<1E> <0152> +<1F> <00D8> +<20> <2423> +<27> <2019> +<60> <2018> +<7F> <00A8> +endbfchar +endcmap +CMapName currentdict /CMap defineresource pop +end +end +%%EndResource +%%EOF + }\endgroup + \expandafter\edef\csname cmapOT1TT\endcsname#1{% + \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% + }% +\fi\fi + + +% Set the font macro #1 to the font named \fontprefix#2. +% #3 is the font's design size, #4 is a scale factor, #5 is the CMap +% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit). +% Example: +% #1 = \textrm +% #2 = \rmshape +% #3 = 10 +% #4 = \mainmagstep +% #5 = OT1 +% +\def\setfont#1#2#3#4#5{% + \font#1=\fontprefix#2#3 scaled #4 + \csname cmap#5\endcsname#1% +} +% This is what gets called when #5 of \setfont is empty. +\let\cmap\gobble +% +% (end of cmaps) % Use cm as the default font prefix. % To specify the font prefix, you must define \fontprefix % before you read in texinfo.tex. -\ifx\fontprefix\undefined +\ifx\fontprefix\thisisundefined \def\fontprefix{cm} \fi % Support font families that don't use the same naming scheme as CM. \def\rmshape{r} -\def\rmbshape{bx} %where the normal face is bold +\def\rmbshape{bx} % where the normal face is bold \def\bfshape{b} \def\bxshape{bx} \def\ttshape{tt} @@ -1467,118 +1801,291 @@ where each line of input produces a line of output.} \def\scshape{csc} \def\scbshape{csc} +% Definitions for a main text size of 11pt. (The default in Texinfo.) +% +\def\definetextfontsizexi{% % Text fonts (11.2pt, magstep1). -\newcount\mainmagstep -\ifx\bigger\relax - % not really supported. - \mainmagstep=\magstep1 - \setfont\textrm\rmshape{12}{1000} - \setfont\texttt\ttshape{12}{1000} -\else - \mainmagstep=\magstephalf - \setfont\textrm\rmshape{10}{\mainmagstep} - \setfont\texttt\ttshape{10}{\mainmagstep} -\fi -\setfont\textbf\bfshape{10}{\mainmagstep} -\setfont\textit\itshape{10}{\mainmagstep} -\setfont\textsl\slshape{10}{\mainmagstep} -\setfont\textsf\sfshape{10}{\mainmagstep} -\setfont\textsc\scshape{10}{\mainmagstep} -\setfont\textttsl\ttslshape{10}{\mainmagstep} +\def\textnominalsize{11pt} +\edef\mainmagstep{\magstephalf} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1095} % A few fonts for @defun names and args. -\setfont\defbf\bfshape{10}{\magstep1} -\setfont\deftt\ttshape{10}{\magstep1} -\setfont\defttsl\ttslshape{10}{\magstep1} +\setfont\defbf\bfshape{10}{\magstep1}{OT1} +\setfont\deftt\ttshape{10}{\magstep1}{OT1TT} +\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). -\setfont\smallrm\rmshape{9}{1000} -\setfont\smalltt\ttshape{9}{1000} -\setfont\smallbf\bfshape{10}{900} -\setfont\smallit\itshape{9}{1000} -\setfont\smallsl\slshape{9}{1000} -\setfont\smallsf\sfshape{9}{1000} -\setfont\smallsc\scshape{10}{900} -\setfont\smallttsl\ttslshape{10}{900} +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} \font\smalli=cmmi9 \font\smallsy=cmsy9 +\def\smallecsize{0900} % Fonts for small examples (8pt). -\setfont\smallerrm\rmshape{8}{1000} -\setfont\smallertt\ttshape{8}{1000} -\setfont\smallerbf\bfshape{10}{800} -\setfont\smallerit\itshape{8}{1000} -\setfont\smallersl\slshape{8}{1000} -\setfont\smallersf\sfshape{8}{1000} -\setfont\smallersc\scshape{10}{800} -\setfont\smallerttsl\ttslshape{10}{800} +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} \font\smalleri=cmmi8 \font\smallersy=cmsy8 +\def\smallerecsize{0800} % Fonts for title page (20.4pt): -\setfont\titlerm\rmbshape{12}{\magstep3} -\setfont\titleit\itbshape{10}{\magstep4} -\setfont\titlesl\slbshape{10}{\magstep4} -\setfont\titlett\ttbshape{12}{\magstep3} -\setfont\titlettsl\ttslshape{10}{\magstep4} -\setfont\titlesf\sfbshape{17}{\magstep1} +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm -\setfont\titlesc\scbshape{10}{\magstep4} +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 -\def\authorrm{\secrm} -\def\authortt{\sectt} +\def\titleecsize{2074} % Chapter (and unnumbered) fonts (17.28pt). -\setfont\chaprm\rmbshape{12}{\magstep2} -\setfont\chapit\itbshape{10}{\magstep3} -\setfont\chapsl\slbshape{10}{\magstep3} -\setfont\chaptt\ttbshape{12}{\magstep2} -\setfont\chapttsl\ttslshape{10}{\magstep3} -\setfont\chapsf\sfbshape{17}{1000} +\def\chapnominalsize{17pt} +\setfont\chaprm\rmbshape{12}{\magstep2}{OT1} +\setfont\chapit\itbshape{10}{\magstep3}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep3}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} +\setfont\chapsf\sfbshape{17}{1000}{OT1} \let\chapbf=\chaprm -\setfont\chapsc\scbshape{10}{\magstep3} +\setfont\chapsc\scbshape{10}{\magstep3}{OT1} \font\chapi=cmmi12 scaled \magstep2 \font\chapsy=cmsy10 scaled \magstep3 +\def\chapecsize{1728} % Section fonts (14.4pt). -\setfont\secrm\rmbshape{12}{\magstep1} -\setfont\secit\itbshape{10}{\magstep2} -\setfont\secsl\slbshape{10}{\magstep2} -\setfont\sectt\ttbshape{12}{\magstep1} -\setfont\secttsl\ttslshape{10}{\magstep2} -\setfont\secsf\sfbshape{12}{\magstep1} +\def\secnominalsize{14pt} +\setfont\secrm\rmbshape{12}{\magstep1}{OT1} +\setfont\secit\itbshape{10}{\magstep2}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep2}{OT1} +\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\secsf\sfbshape{12}{\magstep1}{OT1} \let\secbf\secrm -\setfont\secsc\scbshape{10}{\magstep2} +\setfont\secsc\scbshape{10}{\magstep2}{OT1} \font\seci=cmmi12 scaled \magstep1 \font\secsy=cmsy10 scaled \magstep2 +\def\sececsize{1440} % Subsection fonts (13.15pt). -\setfont\ssecrm\rmbshape{12}{\magstephalf} -\setfont\ssecit\itbshape{10}{1315} -\setfont\ssecsl\slbshape{10}{1315} -\setfont\ssectt\ttbshape{12}{\magstephalf} -\setfont\ssecttsl\ttslshape{10}{1315} -\setfont\ssecsf\sfbshape{12}{\magstephalf} +\def\ssecnominalsize{13pt} +\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} +\setfont\ssecit\itbshape{10}{1315}{OT1IT} +\setfont\ssecsl\slbshape{10}{1315}{OT1} +\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} +\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} \let\ssecbf\ssecrm -\setfont\ssecsc\scbshape{10}{1315} +\setfont\ssecsc\scbshape{10}{1315}{OT1} \font\sseci=cmmi12 scaled \magstephalf \font\ssecsy=cmsy10 scaled 1315 +\def\ssececsize{1200} % Reduced fonts for @acro in text (10pt). -\setfont\reducedrm\rmshape{10}{1000} -\setfont\reducedtt\ttshape{10}{1000} -\setfont\reducedbf\bfshape{10}{1000} -\setfont\reducedit\itshape{10}{1000} -\setfont\reducedsl\slshape{10}{1000} -\setfont\reducedsf\sfshape{10}{1000} -\setfont\reducedsc\scshape{10}{1000} -\setfont\reducedttsl\ttslshape{10}{1000} +\def\reducednominalsize{10pt} +\setfont\reducedrm\rmshape{10}{1000}{OT1} +\setfont\reducedtt\ttshape{10}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{1000}{OT1} +\setfont\reducedit\itshape{10}{1000}{OT1IT} +\setfont\reducedsl\slshape{10}{1000}{OT1} +\setfont\reducedsf\sfshape{10}{1000}{OT1} +\setfont\reducedsc\scshape{10}{1000}{OT1} +\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} \font\reducedi=cmmi10 \font\reducedsy=cmsy10 +\def\reducedecsize{1000} + +\textleading = 13.2pt % line spacing for 11pt CM +\textfonts % reset the current fonts +\rm +} % end of 11pt text font size definitions, \definetextfontsizexi + + +% Definitions to make the main text be 10pt Computer Modern, with +% section, chapter, etc., sizes following suit. This is for the GNU +% Press printing of the Emacs 22 manual. Maybe other manuals in the +% future. Used with @smallbook, which sets the leading to 12pt. +% +\def\definetextfontsizex{% +% Text fonts (10pt). +\def\textnominalsize{10pt} +\edef\mainmagstep{1000} +\setfont\textrm\rmshape{10}{\mainmagstep}{OT1} +\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} +\setfont\textbf\bfshape{10}{\mainmagstep}{OT1} +\setfont\textit\itshape{10}{\mainmagstep}{OT1IT} +\setfont\textsl\slshape{10}{\mainmagstep}{OT1} +\setfont\textsf\sfshape{10}{\mainmagstep}{OT1} +\setfont\textsc\scshape{10}{\mainmagstep}{OT1} +\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep +\def\textecsize{1000} + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstephalf}{OT1} +\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} +\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000}{OT1} +\setfont\smalltt\ttshape{9}{1000}{OT1TT} +\setfont\smallbf\bfshape{10}{900}{OT1} +\setfont\smallit\itshape{9}{1000}{OT1IT} +\setfont\smallsl\slshape{9}{1000}{OT1} +\setfont\smallsf\sfshape{9}{1000}{OT1} +\setfont\smallsc\scshape{10}{900}{OT1} +\setfont\smallttsl\ttslshape{10}{900}{OT1TT} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 +\def\smallecsize{0900} + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000}{OT1} +\setfont\smallertt\ttshape{8}{1000}{OT1TT} +\setfont\smallerbf\bfshape{10}{800}{OT1} +\setfont\smallerit\itshape{8}{1000}{OT1IT} +\setfont\smallersl\slshape{8}{1000}{OT1} +\setfont\smallersf\sfshape{8}{1000}{OT1} +\setfont\smallersc\scshape{10}{800}{OT1} +\setfont\smallerttsl\ttslshape{10}{800}{OT1TT} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 +\def\smallerecsize{0800} + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3}{OT1} +\setfont\titleit\itbshape{10}{\magstep4}{OT1IT} +\setfont\titlesl\slbshape{10}{\magstep4}{OT1} +\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} +\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} +\setfont\titlesf\sfbshape{17}{\magstep1}{OT1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4}{OT1} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\titleecsize{2074} + +% Chapter fonts (14.4pt). +\def\chapnominalsize{14pt} +\setfont\chaprm\rmbshape{12}{\magstep1}{OT1} +\setfont\chapit\itbshape{10}{\magstep2}{OT1IT} +\setfont\chapsl\slbshape{10}{\magstep2}{OT1} +\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} +\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} +\setfont\chapsf\sfbshape{12}{\magstep1}{OT1} +\let\chapbf\chaprm +\setfont\chapsc\scbshape{10}{\magstep2}{OT1} +\font\chapi=cmmi12 scaled \magstep1 +\font\chapsy=cmsy10 scaled \magstep2 +\def\chapecsize{1440} + +% Section fonts (12pt). +\def\secnominalsize{12pt} +\setfont\secrm\rmbshape{12}{1000}{OT1} +\setfont\secit\itbshape{10}{\magstep1}{OT1IT} +\setfont\secsl\slbshape{10}{\magstep1}{OT1} +\setfont\sectt\ttbshape{12}{1000}{OT1TT} +\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} +\setfont\secsf\sfbshape{12}{1000}{OT1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep1}{OT1} +\font\seci=cmmi12 +\font\secsy=cmsy10 scaled \magstep1 +\def\sececsize{1200} + +% Subsection fonts (10pt). +\def\ssecnominalsize{10pt} +\setfont\ssecrm\rmbshape{10}{1000}{OT1} +\setfont\ssecit\itbshape{10}{1000}{OT1IT} +\setfont\ssecsl\slbshape{10}{1000}{OT1} +\setfont\ssectt\ttbshape{10}{1000}{OT1TT} +\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} +\setfont\ssecsf\sfbshape{10}{1000}{OT1} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1000}{OT1} +\font\sseci=cmmi10 +\font\ssecsy=cmsy10 +\def\ssececsize{1000} + +% Reduced fonts for @acro in text (9pt). +\def\reducednominalsize{9pt} +\setfont\reducedrm\rmshape{9}{1000}{OT1} +\setfont\reducedtt\ttshape{9}{1000}{OT1TT} +\setfont\reducedbf\bfshape{10}{900}{OT1} +\setfont\reducedit\itshape{9}{1000}{OT1IT} +\setfont\reducedsl\slshape{9}{1000}{OT1} +\setfont\reducedsf\sfshape{9}{1000}{OT1} +\setfont\reducedsc\scshape{10}{900}{OT1} +\setfont\reducedttsl\ttslshape{10}{900}{OT1TT} +\font\reducedi=cmmi9 +\font\reducedsy=cmsy9 +\def\reducedecsize{0900} + +\divide\parskip by 2 % reduce space between paragraphs +\textleading = 12pt % line spacing for 10pt CM +\textfonts % reset the current fonts +\rm +} % end of 10pt text font size definitions, \definetextfontsizex + + +% We provide the user-level command +% @fonttextsize 10 +% (or 11) to redefine the text font size. pt is assumed. +% +\def\xiword{11} +\def\xword{10} +\def\xwordpt{10pt} +% +\parseargdef\fonttextsize{% + \def\textsizearg{#1}% + %\wlog{doing @fonttextsize \textsizearg}% + % + % Set \globaldefs so that documents can use this inside @tex, since + % makeinfo 4.8 does not support it, but we need it nonetheless. + % + \begingroup \globaldefs=1 + \ifx\textsizearg\xword \definetextfontsizex + \else \ifx\textsizearg\xiword \definetextfontsizexi + \else + \errhelp=\EMsimple + \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} + \fi\fi + \endgroup +} + % In order for the font changes to affect most math symbols and letters, % we have to define the \textfont of the standard families. Since @@ -1608,6 +2115,7 @@ where each line of input produces a line of output.} \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \def\curfontsize{text}% \def\lsize{reduced}\def\lllsize{smaller}% \resetmathfonts \setleading{\textleading}} \def\titlefonts{% @@ -1615,13 +2123,16 @@ where each line of input produces a line of output.} \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy \let\tenttsl=\titlettsl + \def\curfontsize{title}% \def\lsize{chap}\def\lllsize{subsec}% - \resetmathfonts \setleading{25pt}} -\def\titlefont#1{{\titlefonts\rm #1}} + \resetmathfonts \setleading{27pt}} +\def\titlefont#1{{\titlefonts\rmisbold #1}} \def\chapfonts{% \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc - \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy + \let\tenttsl=\chapttsl + \def\curfontsize{chap}% \def\lsize{sec}\def\lllsize{text}% \resetmathfonts \setleading{19pt}} \def\secfonts{% @@ -1629,6 +2140,7 @@ where each line of input produces a line of output.} \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \def\curfontsize{sec}% \def\lsize{subsec}\def\lllsize{reduced}% \resetmathfonts \setleading{16pt}} \def\subsecfonts{% @@ -1636,6 +2148,7 @@ where each line of input produces a line of output.} \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \def\curfontsize{ssec}% \def\lsize{text}\def\lllsize{small}% \resetmathfonts \setleading{15pt}} \let\subsubsecfonts = \subsecfonts @@ -1644,6 +2157,7 @@ where each line of input produces a line of output.} \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy \let\tenttsl=\reducedttsl + \def\curfontsize{reduced}% \def\lsize{small}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallfonts{% @@ -1651,6 +2165,7 @@ where each line of input produces a line of output.} \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy \let\tenttsl=\smallttsl + \def\curfontsize{small}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallerfonts{% @@ -1658,9 +2173,20 @@ where each line of input produces a line of output.} \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy \let\tenttsl=\smallerttsl + \def\curfontsize{smaller}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{9.5pt}} +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000}{OT1} +\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 +\setfont\shortcontsl\slshape{12}{1000}{OT1} +\setfont\shortconttt\ttshape{12}{1000}{OT1TT} + +% Define these just so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + % Set the fonts to use with the @small... environments. \let\smallexamplefonts = \smallfonts @@ -1674,55 +2200,219 @@ where each line of input produces a line of output.} % % By the way, for comparison, here's what fits with @example (10pt): % 8.5x11=71 smallbook=60 a4=75 a5=58 -% -% I wish the USA used A4 paper. % --karl, 24jan03. - % Set up the default fonts, so we can use them for creating boxes. % -\textfonts \rm +\definetextfontsizexi -% Define these so they can be easily changed for other fonts. -\def\angleleft{$\langle$} -\def\angleright{$\rangle$} + +\message{markup,} + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Markup style infrastructure. \defmarkupstylesetup\INITMACRO will +% define and register \INITMACRO to be called on markup style changes. +% \INITMACRO can check \currentmarkupstyle for the innermost +% style and the set of \ifmarkupSTYLE switches for all styles +% currently in effect. +\newif\ifmarkupvar +\newif\ifmarkupsamp +\newif\ifmarkupkey +%\newif\ifmarkupfile % @file == @samp. +%\newif\ifmarkupoption % @option == @samp. +\newif\ifmarkupcode +\newif\ifmarkupkbd +%\newif\ifmarkupenv % @env == @code. +%\newif\ifmarkupcommand % @command == @code. +\newif\ifmarkuptex % @tex (and part of @math, for now). +\newif\ifmarkupexample +\newif\ifmarkupverb +\newif\ifmarkupverbatim + +\let\currentmarkupstyle\empty + +\def\setupmarkupstyle#1{% + \csname markup#1true\endcsname + \def\currentmarkupstyle{#1}% + \markupstylesetup +} + +\let\markupstylesetup\empty + +\def\defmarkupstylesetup#1{% + \expandafter\def\expandafter\markupstylesetup + \expandafter{\markupstylesetup #1}% + \def#1% +} + +% Markup style setup for left and right quotes. +\defmarkupstylesetup\markupsetuplq{% + \expandafter\let\expandafter \temp + \csname markupsetuplq\currentmarkupstyle\endcsname + \ifx\temp\relax \markupsetuplqdefault \else \temp \fi +} + +\defmarkupstylesetup\markupsetuprq{% + \expandafter\let\expandafter \temp + \csname markupsetuprq\currentmarkupstyle\endcsname + \ifx\temp\relax \markupsetuprqdefault \else \temp \fi +} + +{ +\catcode`\'=\active +\catcode`\`=\active + +\gdef\markupsetuplqdefault{\let`\lq} +\gdef\markupsetuprqdefault{\let'\rq} + +\gdef\markupsetcodequoteleft{\let`\codequoteleft} +\gdef\markupsetcodequoteright{\let'\codequoteright} +} + +\let\markupsetuplqcode \markupsetcodequoteleft +\let\markupsetuprqcode \markupsetcodequoteright +% +\let\markupsetuplqexample \markupsetcodequoteleft +\let\markupsetuprqexample \markupsetcodequoteright +% +\let\markupsetuplqkbd \markupsetcodequoteleft +\let\markupsetuprqkbd \markupsetcodequoteright +% +\let\markupsetuplqsamp \markupsetcodequoteleft +\let\markupsetuprqsamp \markupsetcodequoteright +% +\let\markupsetuplqverb \markupsetcodequoteleft +\let\markupsetuprqverb \markupsetcodequoteright +% +\let\markupsetuplqverbatim \markupsetcodequoteleft +\let\markupsetuprqverbatim \markupsetcodequoteright + +% Allow an option to not use regular directed right quote/apostrophe +% (char 0x27), but instead the undirected quote from cmtt (char 0x0d). +% The undirected quote is ugly, so don't make it the default, but it +% works for pasting with more pdf viewers (at least evince), the +% lilypond developers report. xpdf does work with the regular 0x27. +% +\def\codequoteright{% + \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax + \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax + '% + \else \char'15 \fi + \else \char'15 \fi +} +% +% and a similar option for the left quote char vs. a grave accent. +% Modern fonts display ASCII 0x60 as a grave accent, so some people like +% the code environments to do likewise. +% +\def\codequoteleft{% + \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax + \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax + % [Knuth] pp. 380,381,391 + % \relax disables Spanish ligatures ?` and !` of \tt font. + \relax`% + \else \char'22 \fi + \else \char'22 \fi +} + +% Commands to set the quote options. +% +\parseargdef\codequoteundirected{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxicodequoteundirected\endcsname + = t% + \else\ifx\temp\offword + \expandafter\let\csname SETtxicodequoteundirected\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @codequoteundirected value `\temp', must be on|off}% + \fi\fi +} +% +\parseargdef\codequotebacktick{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxicodequotebacktick\endcsname + = t% + \else\ifx\temp\offword + \expandafter\let\csname SETtxicodequotebacktick\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @codequotebacktick value `\temp', must be on|off}% + \fi\fi +} + +% [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font. +\def\noligaturesquoteleft{\relax\lq} % Count depth in font-changes, for error checks \newcount\fontdepth \fontdepth=0 -% Fonts for short table of contents. -\setfont\shortcontrm\rmshape{12}{1000} -\setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12 -\setfont\shortcontsl\slshape{12}{1000} -\setfont\shortconttt\ttshape{12}{1000} +% Font commands. -%% Add scribe-like font environments, plus @l for inline lisp (usually sans -%% serif) and @ii for TeX italic +% #1 is the font command (\sl or \it), #2 is the text to slant. +% If we are in a monospaced environment, however, 1) always use \ttsl, +% and 2) do not add an italic correction. +\def\dosmartslant#1#2{% + \ifusingtt + {{\ttsl #2}\let\next=\relax}% + {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}% + \next +} +\def\smartslanted{\dosmartslant\sl} +\def\smartitalic{\dosmartslant\it} -% \smartitalic{ARG} outputs arg in italics, followed by an italic correction -% unless the following character is such as not to need one. -\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else - \ptexslash\fi\fi\fi} -\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} -\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} +% Output an italic correction unless \next (presumed to be the following +% character) is such as not to need one. +\def\smartitaliccorrection{% + \ifx\next,% + \else\ifx\next-% + \else\ifx\next.% + \else\ptexslash + \fi\fi\fi + \aftersmartic +} -% like \smartslanted except unconditionally uses \ttsl. -% @var is set to this for defun arguments. -\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} +% Unconditional use \ttsl, and no ic. @var is set to this for defuns. +\def\ttslanted#1{{\ttsl #1}} -% like \smartslanted except unconditionally use \sl. We never want +% @cite is like \smartslanted except unconditionally use \sl. We never want % ttsl for book titles, do we? -\def\cite#1{{\sl #1}\futurelet\next\smartitalicx} +\def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection} + +\def\aftersmartic{} +\def\var#1{% + \let\saveaftersmartic = \aftersmartic + \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% + \smartslanted{#1}% +} \let\i=\smartitalic \let\slanted=\smartslanted -\let\var=\smartslanted \let\dfn=\smartslanted \let\emph=\smartitalic +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @b, explicit bold. Also @strong. \def\b#1{{\bf #1}} \let\strong=\b +% @sansserif, explicit sans. +\def\sansserif#1{{\sf #1}} + % We can't just use \exhyphenpenalty, because that only has effect at % the end of a paragraph. Restore normal hyphenation at the end of the % group within which \nohyphenation is presumably called. @@ -1735,35 +2425,34 @@ where each line of input produces a line of output.} % sometimes \x has an active definition that messes things up. % \catcode`@=11 - \def\frenchspacing{% + \def\plainfrenchspacing{% \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + \def\endofsentencespacefactor{1000}% for @. and friends + } + \def\plainnonfrenchspacing{% + \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 + \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 + \def\endofsentencespacefactor{3000}% for @. and friends } \catcode`@=\other +\def\endofsentencespacefactor{3000}% default +% @t, explicit typewriter. \def\t#1{% - {\tt \rawbackslash \frenchspacing #1}% + {\tt \rawbackslash \plainfrenchspacing #1}% \null } -\def\samp#1{`\tclose{#1}'\null} -\setfont\keyrm\rmshape{8}{1000} -\font\keysy=cmsy9 -\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% - \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% - \vbox{\hrule\kern-0.4pt - \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% - \kern-0.4pt\hrule}% - \kern-.06em\raise0.4pt\hbox{\angleright}}}} -% The old definition, with no lozenge: -%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} -\def\ctrl #1{{\tt \rawbackslash \hat}#1} -% @file, @option are the same as @samp. -\let\file=\samp -\let\option=\samp +% @samp. +\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}} -% @code is a modification of @t, -% which makes spaces the same size as normal in the surrounding text. +% @indicateurl is \samp, that is, with quotes. +\let\indicateurl=\samp + +% @code (and similar) prints in typewriter, but with spaces the same +% size as normal in the surrounding text, without hyphenation, etc. +% This is a subroutine for that. \def\tclose#1{% {% % Change normal interword space to be same as for the current font. @@ -1779,33 +2468,44 @@ where each line of input produces a line of output.} \nohyphenation % \rawbackslash - \frenchspacing + \plainfrenchspacing #1% }% - \null + \null % reset spacefactor to 1000 } % We *must* turn on hyphenation at `-' and `_' in @code. % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. - +% % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) % and arrange explicitly to hyphenate at a dash. % -- rms. { - \catcode`\-=\active - \catcode`\_=\active + \catcode`\-=\active \catcode`\_=\active + \catcode`\'=\active \catcode`\`=\active + \global\let'=\rq \global\let`=\lq % default definitions % \global\def\code{\begingroup - \catcode`\-=\active \let-\codedash - \catcode`\_=\active \let_\codeunder + \setupmarkupstyle{code}% + % The following should really be moved into \setupmarkupstyle handlers. + \catcode\dashChar=\active \catcode\underChar=\active + \ifallowcodebreaks + \let-\codedash + \let_\codeunder + \else + \let-\normaldash + \let_\realunder + \fi \codex } } -\def\realdash{-} +\def\codex #1{\tclose{#1}\endgroup} + +\def\normaldash{-} \def\codedash{-\discretionary{}{}{}} \def\codeunder{% % this is all so @math{@code{var_name}+1} can work. In math mode, _ @@ -1818,53 +2518,44 @@ where each line of input produces a line of output.} \discretionary{}{}{}}% {\_}% } -\def\codex #1{\tclose{#1}\endgroup} -% @kbd is like @code, except that if the argument is just one @key command, -% then @kbd has no effect. +% An additional complication: the above will allow breaks after, e.g., +% each of the four underscores in __typeof__. This is bad. +% @allowcodebreaks provides a document-level way to turn breaking at - +% and _ on and off. +% +\newif\ifallowcodebreaks \allowcodebreakstrue -% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), -% `example' (@kbd uses ttsl only inside of @example and friends), -% or `code' (@kbd uses normal tty font always). -\parseargdef\kbdinputstyle{% - \def\arg{#1}% - \ifx\arg\worddistinct - \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% - \else\ifx\arg\wordexample - \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% - \else\ifx\arg\wordcode - \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% +\def\keywordtrue{true} +\def\keywordfalse{false} + +\parseargdef\allowcodebreaks{% + \def\txiarg{#1}% + \ifx\txiarg\keywordtrue + \allowcodebreakstrue + \else\ifx\txiarg\keywordfalse + \allowcodebreaksfalse \else \errhelp = \EMsimple - \errmessage{Unknown @kbdinputstyle option `\arg'}% - \fi\fi\fi + \errmessage{Unknown @allowcodebreaks option `\txiarg', must be true|false}% + \fi\fi } -\def\worddistinct{distinct} -\def\wordexample{example} -\def\wordcode{code} -% Default is `distinct.' -\kbdinputstyle distinct - -\def\xkey{\key} -\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% -\ifx\one\xkey\ifx\threex\three \key{#2}% -\else{\tclose{\kbdfont\look}}\fi -\else{\tclose{\kbdfont\look}}\fi} - -% For @indicateurl, @env, @command quotes seem unnecessary, so use \code. -\let\indicateurl=\code -\let\env=\code +% For @command, @env, @file, @option quotes seem unnecessary, +% so use \code rather than \samp. \let\command=\code +\let\env=\code +\let\file=\code +\let\option=\code % @uref (abbreviation for `urlref') takes an optional (comma-separated) % second argument specifying the text to display and an optional third % arg as text to display instead of (rather than in addition to) the url -% itself. First (mandatory) arg is the url. Perhaps eventually put in -% a hypertex \special here. -% -\def\uref#1{\douref #1,,,\finish} -\def\douref#1,#2,#3,#4\finish{\begingroup +% itself. First (mandatory) arg is the url. +% (This \urefnobreak definition isn't used now, leaving it for a while +% for comparison.) +\def\urefnobreak#1{\dourefnobreak #1,,,\finish} +\def\dourefnobreak#1,#2,#3,#4\finish{\begingroup \unsepspaces \pdfurl{#1}% \setbox0 = \hbox{\ignorespaces #3}% @@ -1885,6 +2576,103 @@ where each line of input produces a line of output.} \endlink \endgroup} +% This \urefbreak definition is the active one. +\def\urefbreak{\begingroup \urefcatcodes \dourefbreak} +\let\uref=\urefbreak +\def\dourefbreak#1{\urefbreakfinish #1,,,\finish} +\def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\urefcode{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \urefcode{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% Allow line breaks around only a few characters (only). +\def\urefcatcodes{% + \catcode\ampChar=\active \catcode\dotChar=\active + \catcode\hashChar=\active \catcode\questChar=\active + \catcode\slashChar=\active +} +{ + \urefcatcodes + % + \global\def\urefcode{\begingroup + \setupmarkupstyle{code}% + \urefcatcodes + \let&\urefcodeamp + \let.\urefcodedot + \let#\urefcodehash + \let?\urefcodequest + \let/\urefcodeslash + \codex + } + % + % By default, they are just regular characters. + \global\def&{\normalamp} + \global\def.{\normaldot} + \global\def#{\normalhash} + \global\def?{\normalquest} + \global\def/{\normalslash} +} + +% we put a little stretch before and after the breakable chars, to help +% line breaking of long url's. The unequal skips make look better in +% cmtt at least, especially for dots. +\def\urefprestretch{\urefprebreak \hskip0pt plus.13em } +\def\urefpoststretch{\urefpostbreak \hskip0pt plus.1em } +% +\def\urefcodeamp{\urefprestretch \&\urefpoststretch} +\def\urefcodedot{\urefprestretch .\urefpoststretch} +\def\urefcodehash{\urefprestretch \#\urefpoststretch} +\def\urefcodequest{\urefprestretch ?\urefpoststretch} +\def\urefcodeslash{\futurelet\next\urefcodeslashfinish} +{ + \catcode`\/=\active + \global\def\urefcodeslashfinish{% + \urefprestretch \slashChar + % Allow line break only after the final / in a sequence of + % slashes, to avoid line break between the slashes in http://. + \ifx\next/\else \urefpoststretch \fi + } +} + +% One more complication: by default we'll break after the special +% characters, but some people like to break before the special chars, so +% allow that. Also allow no breaking at all, for manual control. +% +\parseargdef\urefbreakstyle{% + \def\txiarg{#1}% + \ifx\txiarg\wordnone + \def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak} + \else\ifx\txiarg\wordbefore + \def\urefprebreak{\allowbreak}\def\urefpostbreak{\nobreak} + \else\ifx\txiarg\wordafter + \def\urefprebreak{\nobreak}\def\urefpostbreak{\allowbreak} + \else + \errhelp = \EMsimple + \errmessage{Unknown @urefbreakstyle setting `\txiarg'}% + \fi\fi\fi +} +\def\wordafter{after} +\def\wordbefore{before} +\def\wordnone{none} + +\urefbreakstyle after + % @url synonym for @uref, since that's how everyone uses it. % \let\url=\uref @@ -1906,34 +2694,81 @@ where each line of input produces a line of output.} \let\email=\uref \fi -% Check if we are currently using a typewriter font. Since all the -% Computer Modern typewriter fonts have zero interword stretch (and -% shrink), and it is reasonable to expect all typewriter fonts to have -% this property, we can check that font parameter. +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\parseargdef\kbdinputstyle{% + \def\txiarg{#1}% + \ifx\txiarg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\txiarg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\txiarg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle setting `\txiarg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct'. +\kbdinputstyle distinct + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. +\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}} + +\def\xkey{\key} +\def\kbdsub#1#2#3\par{% + \def\one{#1}\def\three{#3}\def\threex{??}% + \ifx\one\xkey\ifx\threex\three \key{#2}% + \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi + \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi +} + +% definition of @key that produces a lozenge. Doesn't adjust to text size. +%\setfont\keyrm\rmshape{8}{1000}{OT1} +%\font\keysy=cmsy9 +%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% +% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% +% \vbox{\hrule\kern-0.4pt +% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% +% \kern-0.4pt\hrule}% +% \kern-.06em\raise0.4pt\hbox{\angleright}}}} + +% definition of @key with no lozenge. If the current font is already +% monospace, don't change it; that way, we respect @kbdinputstyle. But +% if it isn't monospace, then use \tt. % -\def\ifmonospace{\ifdim\fontdimen3\font=0pt } +\def\key#1{{\setupmarkupstyle{key}% + \nohyphenation + \ifmonospace\else\tt\fi + #1}\null} + +% @clicksequence{File @click{} Open ...} +\def\clicksequence#1{\begingroup #1\endgroup} + +% @clickstyle @arrow (by default) +\parseargdef\clickstyle{\def\click{#1}} +\def\click{\arrow} % Typeset a dimension, e.g., `in' or `pt'. The only reason for the % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. % \def\dmn#1{\thinspace #1} -\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} - % @l was never documented to mean ``switch to the Lisp font'', % and it is not used as such in any manual I can find. We need it for % Polish suppressed-l. --karl, 22sep96. %\def\l#1{{\li #1}\null} -% Explicit font changes: @r, @sc, undocumented @ii. -\def\r#1{{\rm #1}} % roman font -\def\sc#1{{\smallcaps#1}} % smallcaps font -\def\ii#1{{\it #1}} % italic font - % @acronym for "FBI", "NATO", and the like. % We print this one point size smaller, since it's intended for % all-uppercase. -% +% \def\acronym#1{\doacronym #1,,\finish} \def\doacronym#1,#2,#3\finish{% {\selectfonts\lsize #1}% @@ -1941,24 +2776,392 @@ where each line of input produces a line of output.} \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi + \null % reset \spacefactor=1000 } % @abbr for "Comput. J." and the like. % No font change, but don't do end-of-sentence spacing. -% +% \def\abbr#1{\doabbr #1,,\finish} \def\doabbr#1,#2,#3\finish{% - {\frenchspacing #1}% + {\plainfrenchspacing #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi + \null % reset \spacefactor=1000 } +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ active, and distinguish by seeing if the current family is \slfam, +% which is what @var uses. +{ + \catcode`\_ = \active + \gdef\mathunderscore{% + \catcode`\_=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% + } +} +% Another complication: we want \\ (and @\) to output a math (or tt) \. +% FYI, plain.tex uses \\ as a temporary control sequence (for no +% particular reason), but this is not advertised and we don't care. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathunderscore + \let\\ = \mathbackslash + \mathactive + % make the texinfo accent commands work in math mode + \let\"=\ddot + \let\'=\acute + \let\==\bar + \let\^=\hat + \let\`=\grave + \let\u=\breve + \let\v=\check + \let\~=\tilde + \let\dotaccent=\dot + $\finishmath +} +\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an argument +% to a command which sets the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \catcode`' = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + \let' = \ptexquoteright + } +} + +% ctrl is no longer a Texinfo command, but leave this definition for fun. +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. +% Ignore unless FMTNAME == tex; then it is like @iftex and @tex, +% except specified as a normal braced arg, so no newlines to worry about. +% +\def\outfmtnametex{tex} +% +\long\def\inlinefmt#1{\doinlinefmt #1,\finish} +\long\def\doinlinefmt#1,#2,\finish{% + \def\inlinefmtname{#1}% + \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi +} +% For raw, must switch into @tex before parsing the argument, to avoid +% setting catcodes prematurely. Doing it this way means that, for +% example, @inlineraw{html, foo{bar} gets a parse error instead of being +% ignored. But this isn't important because if people want a literal +% *right* brace they would have to use a command anyway, so they may as +% well use a command to get a left brace too. We could re-use the +% delimiter character idea from \verb, but it seems like overkill. +% +\long\def\inlineraw{\tex \doinlineraw} +\long\def\doinlineraw#1{\doinlinerawtwo #1,\finish} +\def\doinlinerawtwo#1,#2,\finish{% + \def\inlinerawname{#1}% + \ifx\inlinerawname\outfmtnametex \ignorespaces #2\fi + \endgroup % close group opened by \tex. +} + + +\message{glyphs,} +% and logos. + +% @@ prints an @, as does @atchar{}. +\def\@{\char64 } +\let\atchar=\@ + +% @{ @} @lbracechar{} @rbracechar{} all generate brace characters. +% Unless we're in typewriter, use \ecfont because the CM text fonts do +% not have braces, and we don't want to switch into math. +\def\mylbrace{{\ifmonospace\else\ecfont\fi \char123}} +\def\myrbrace{{\ifmonospace\else\ecfont\fi \char125}} +\let\{=\mylbrace \let\lbracechar=\{ +\let\}=\myrbrace \let\rbracechar=\} +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux/toc files. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% @comma{} to avoid , parsing problems. +\let\comma = , + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \ptexc +\let\dotaccent = \ptexdot +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \ptext +\let\ubaraccent = \ptexb +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown @ordf @ordm +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} +\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi + \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% The \TeX{} logo, as in plain, but resetting the spacing so that a +% period following counts as ending a sentence. (Idea found in latex.) +% +\edef\TeX{\TeX \spacefactor=1000 } + +% @LaTeX{} logo. Not quite the same results as the definition in +% latex.ltx, since we use a different font for the raised A; it's most +% convenient for us to use an explicitly smaller font, rather than using +% the \scriptstyle font (since we don't reset \scriptstyle and +% \scriptscriptstyle). +% +\def\LaTeX{% + L\kern-.36em + {\setbox0=\hbox{T}% + \vbox to \ht0{\hbox{% + \ifx\textnominalsize\xwordpt + % for 10pt running text, \lllsize (8pt) is too small for the A in LaTeX. + % Revert to plain's \scriptsize, which is 7pt. + \count255=\the\fam $\fam\count255 \scriptstyle A$% + \else + % For 11pt, we can use our lllsize. + \selectfonts\lllsize A% + \fi + }% + \vss + }}% + \kern-.15em + \TeX +} + +% Some math mode symbols. +\def\bullet{$\ptexbullet$} +\def\geq{\ifmmode \ge\else $\ge$\fi} +\def\leq{\ifmmode \le\else $\le$\fi} +\def\minus{\ifmmode -\else $-$\fi} + +% @dots{} outputs an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in the cm +% typewriter fonts as three actual period characters; on the other hand, +% in other typewriter fonts three periods are wider than 1.5em. So do +% whichever is larger. +% +\def\dots{% + \leavevmode + \setbox0=\hbox{...}% get width of three periods + \ifdim\wd0 > 1.5em + \dimen0 = \wd0 + \else + \dimen0 = 1.5em + \fi + \hbox to \dimen0{% + \hskip 0pt plus.25fil + .\hskip 0pt plus1fil + .\hskip 0pt plus1fil + .\hskip 0pt plus.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \dots + \spacefactor=\endofsentencespacefactor +} + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, they should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}} +\def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \reducedsf \putworderror\kern-1.5pt} +% +\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{% + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + % @pounds{} is a sterling sign, which Knuth put in the CM italic font. % \def\pounds{{\it\$}} +% @euro{} comes from a separate font, depending on the current style. +% We use the free feym* fonts from the eurosym package by Henrik +% Theiling, which support regular, slanted, bold and bold slanted (and +% "outlined" (blackboard board, sort of) versions, which we don't need). +% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. +% +% Although only regular is the truly official Euro symbol, we ignore +% that. The Euro is designed to be slightly taller than the regular +% font height. +% +% feymr - regular +% feymo - slanted +% feybr - bold +% feybo - bold slanted +% +% There is no good (free) typewriter version, to my knowledge. +% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. +% Hmm. +% +% Also doesn't work in math. Do we need to do math with euro symbols? +% Hope not. +% +% +\def\euro{{\eurofont e}} +\def\eurofont{% + % We set the font at each command, rather than predefining it in + % \textfonts and the other font-switching commands, so that + % installations which never need the symbol don't have to have the + % font installed. + % + % There is only one designed size (nominal 10pt), so we always scale + % that to the current nominal size. + % + % By the way, simply using "at 1em" works for cmr10 and the like, but + % does not work for cmbx10 and other extended/shrunken fonts. + % + \def\eurosize{\csname\curfontsize nominalsize\endcsname}% + % + \ifx\curfontstyle\bfstylename + % bold: + \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize + \else + % regular: + \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize + \fi + \thiseurofont +} + +% Glyphs from the EC fonts. We don't use \let for the aliases, because +% sometimes we redefine the original macro, and the alias should reflect +% the redefinition. +% +% Use LaTeX names for the Icelandic letters. +\def\DH{{\ecfont \char"D0}} % Eth +\def\dh{{\ecfont \char"F0}} % eth +\def\TH{{\ecfont \char"DE}} % Thorn +\def\th{{\ecfont \char"FE}} % thorn +% +\def\guillemetleft{{\ecfont \char"13}} +\def\guillemotleft{\guillemetleft} +\def\guillemetright{{\ecfont \char"14}} +\def\guillemotright{\guillemetright} +\def\guilsinglleft{{\ecfont \char"0E}} +\def\guilsinglright{{\ecfont \char"0F}} +\def\quotedblbase{{\ecfont \char"12}} +\def\quotesinglbase{{\ecfont \char"0D}} +% +% This positioning is not perfect (see the ogonek LaTeX package), but +% we have the precomposed glyphs for the most common cases. We put the +% tests to use those glyphs in the single \ogonek macro so we have fewer +% dummy definitions to worry about for index entries, etc. +% +% ogonek is also used with other letters in Lithuanian (IOU), but using +% the precomposed glyphs for those is not so easy since they aren't in +% the same EC font. +\def\ogonek#1{{% + \def\temp{#1}% + \ifx\temp\macrocharA\Aogonek + \else\ifx\temp\macrochara\aogonek + \else\ifx\temp\macrocharE\Eogonek + \else\ifx\temp\macrochare\eogonek + \else + \ecfont \setbox0=\hbox{#1}% + \ifdim\ht0=1ex\accent"0C #1% + \else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}% + \fi + \fi\fi\fi\fi + }% +} +\def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A} +\def\aogonek{{\ecfont \char"A1}}\def\macrochara{a} +\def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E} +\def\eogonek{{\ecfont \char"A6}}\def\macrochare{e} +% +% Use the ec* fonts (cm-super in outline format) for non-CM glyphs. +\def\ecfont{% + % We can't distinguish serif/sans and italic/slanted, but this + % is used for crude hacks anyway (like adding French and German + % quotes to documents typeset with CM, where we lose kerning), so + % hopefully nobody will notice/care. + \edef\ecsize{\csname\curfontsize ecsize\endcsname}% + \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% + \ifmonospace + % typewriter: + \font\thisecfont = ectt\ecsize \space at \nominalsize + \else + \ifx\curfontstyle\bfstylename + % bold: + \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize + \else + % regular: + \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize + \fi + \fi + \thisecfont +} + % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. @@ -1969,14 +3172,24 @@ where each line of input produces a line of output.} }$% } +% @textdegree - the normal degrees sign. +% +\def\textdegree{$^\circ$} + % Laurent Siebenmann reports \Orb undefined with: % Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 % so we'll define it if necessary. -% -\ifx\Orb\undefined +% +\ifx\Orb\thisisundefined \def\Orb{\mathhexbox20D} \fi +% Quotes. +\chardef\quotedblleft="5C +\chardef\quotedblright=`\" +\chardef\quoteleft=`\` +\chardef\quoteright=`\' + \message{page headings,} @@ -1995,8 +3208,9 @@ where each line of input produces a line of output.} \newif\ifsetshortcontentsaftertitlepage \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue -\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% - \endgroup\page\hbox{}\page} +\parseargdef\shorttitlepage{% + \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} \envdef\titlepage{% % Open one extra group, as we want to close it in the middle of \Etitlepage. @@ -2056,17 +3270,28 @@ where each line of input produces a line of output.} \finishedtitlepagetrue } -%%% Macros to be used within @titlepage: +% Settings used for typesetting titles: no hyphenation, no indentation, +% don't worry much about spacing, ragged right. This should be used +% inside a \vbox, and fonts need to be set appropriately first. Because +% it is always used for titles, nothing else, we call \rmisbold. \par +% should be specified before the end of the \vbox, since a vbox is a group. +% +\def\raggedtitlesettings{% + \rmisbold + \hyphenpenalty=10000 + \parindent=0pt + \tolerance=5000 + \ptexraggedright +} + +% Macros to be used within @titlepage: \let\subtitlerm=\tenrm \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} -\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines - \let\tt=\authortt} - \parseargdef\title{% \checkenv\titlepage - \leftline{\titlefonts\rm #1} + \vbox{\titlefonts \raggedtitlesettings #1\par}% % print a rule at the page bottom also. \finishedtitlepagefalse \vskip4pt \hrule height 4pt width \hsize \vskip4pt @@ -2087,12 +3312,12 @@ where each line of input produces a line of output.} \else \checkenv\titlepage \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi - {\authorfont \leftline{#1}}% + {\secfonts\rmisbold \leftline{#1}}% \fi } -%%% Set up page headings and footings. +% Set up page headings and footings. \let\thispage=\folio @@ -2140,12 +3365,39 @@ where each line of input produces a line of output.} % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. - \global\advance\pageheight by -\baselineskip - \global\advance\vsize by -\baselineskip + \global\advance\pageheight by -12pt + \global\advance\vsize by -12pt } \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% @evenheadingmarks top \thischapter <- chapter at the top of a page +% @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page +% +% The same set of arguments for: +% +% @oddheadingmarks +% @evenfootingmarks +% @oddfootingmarks +% @everyheadingmarks +% @everyfootingmarks + +\def\evenheadingmarks{\headingmarks{even}{heading}} +\def\oddheadingmarks{\headingmarks{odd}{heading}} +\def\evenfootingmarks{\headingmarks{even}{footing}} +\def\oddfootingmarks{\headingmarks{odd}{footing}} +\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} + \headingmarks{odd}{heading}{#1} } +\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} + \headingmarks{odd}{footing}{#1} } +% #1 = even/odd, #2 = heading/footing, #3 = top/bottom. +\def\headingmarks#1#2#3 {% + \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname + \global\expandafter\let\csname get#1#2marks\endcsname \temp +} + +\everyheadingmarks bottom +\everyfootingmarks bottom % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. @@ -2159,10 +3411,14 @@ where each line of input produces a line of output.} \def\headings #1 {\csname HEADINGS#1\endcsname} -\def\HEADINGSoff{% -\global\evenheadline={\hfil} \global\evenfootline={\hfil} -\global\oddheadline={\hfil} \global\oddfootline={\hfil}} -\HEADINGSoff +\def\headingsoff{% non-global headings elimination + \evenheadline={\hfil}\evenfootline={\hfil}% + \oddheadline={\hfil}\oddfootline={\hfil}% +} + +\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting +\HEADINGSoff % it's the default + % When we turn headings on, set the page number to 1. % For double-sided printing, put current file name in lower left corner, % chapter name on inside top of right hand pages, document @@ -2213,7 +3469,7 @@ where each line of input produces a line of output.} % This produces Day Month Year style of output. % Only define if not already defined, in case a txi-??.tex file has set % up a different format (e.g., txi-cs.tex does this). -\ifx\today\undefined +\ifx\today\thisisundefined \def\today{% \number\day\space \ifcase\month @@ -2274,7 +3530,7 @@ where each line of input produces a line of output.} \begingroup \advance\leftskip by-\tableindent \advance\hsize by\tableindent - \advance\rightskip by0pt plus1fil + \advance\rightskip by0pt plus1fil\relax \leavevmode\unhbox0\par \endgroup % @@ -2288,7 +3544,7 @@ where each line of input produces a line of output.} % cause the example and the item to crash together. So we use this % bizarre value of 10001 as a signal to \aboveenvbreak to insert % \parskip glue after all. Section titles are handled this way also. - % + % \penalty 10001 \endgroup \itemxneedsnegativevskipfalse @@ -2314,15 +3570,26 @@ where each line of input produces a line of output.} % @table, @ftable, @vtable. \envdef\table{% \let\itemindex\gobble - \tablex + \tablecheck{table}% } \envdef\ftable{% \def\itemindex ##1{\doind {fn}{\code{##1}}}% - \tablex + \tablecheck{ftable}% } \envdef\vtable{% \def\itemindex ##1{\doind {vr}{\code{##1}}}% - \tablex + \tablecheck{vtable}% +} +\def\tablecheck#1{% + \ifnum \the\catcode`\^^M=\active + \endgroup + \errmessage{This command won't work in this context; perhaps the problem is + that we are \inenvironment\thisenv}% + \def\next{\doignore{#1}}% + \else + \let\next\tablex + \fi + \next } \def\tablex#1{% \def\itemindicate{#1}% @@ -2371,9 +3638,18 @@ where each line of input produces a line of output.} \parindent=0pt \parskip=\smallskipamount \ifdim\parskip=0pt \parskip=2pt \fi + % + % Try typesetting the item mark that if the document erroneously says + % something like @itemize @samp (intending @table), there's an error + % right away at the @itemize. It's not the best error message in the + % world, but it's better than leaving it to the @item. This means if + % the user wants an empty mark, they have to say @w{} not just @w. \def\itemcontents{#1}% + \setbox0 = \hbox{\itemcontents}% + % % @itemize with no arg is equivalent to @itemize @bullet. \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + % \let\item=\itemizeitem } @@ -2394,6 +3670,7 @@ where each line of input produces a line of output.} \ifnum\lastpenalty<10000 \parskip=0in \fi \noindent \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% + % \vadjust{\penalty 1200}}% not good to break after first line of item. \flushcr } @@ -2615,12 +3892,19 @@ where each line of input produces a line of output.} % % @headitem starts a heading row, which we typeset in bold. % Assignments have to be global since we are inside the implicit group -% of an alignment entry. Note that \everycr resets \everytab. -\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% +% of an alignment entry. \everycr resets \everytab so we don't have to +% undo it ourselves. +\def\headitemfont{\b}% for people to use in the template row; not changeable +\def\headitem{% + \checkenv\multitable + \crcr + \global\everytab={\bf}% can't use \headitemfont since the parsing differs + \the\everytab % for the first item +}% % % A \tab used to include \hskip1sp. But then the space in a template % line is not enough. That is bad. So let's go back to just `&' until -% we encounter the problem it was intended to solve again. +% we again encounter the problem the 1sp was intended to solve. % --karl, nathan@acm.org, 20apr99. \def\tab{\checkenv\multitable &\the\everytab}% @@ -2721,31 +4005,29 @@ where each line of input produces a line of output.} \global\setpercentfalse } -\def\setmultitablespacing{% test to see if user has set \multitablelinespace. -% If so, do nothing. If not, give it an appropriate dimension based on -% current baselineskip. +\def\setmultitablespacing{% + \def\multistrut{\strut}% just use the standard line spacing + % + % Compute \multitablelinespace (if not defined by user) for use in + % \multitableparskip calculation. We used define \multistrut based on + % this, but (ironically) that caused the spacing to be off. + % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. \ifdim\multitablelinespace=0pt \setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip \global\advance\multitablelinespace by-\ht0 -%% strut to put in table in case some entry doesn't have descenders, -%% to keep lines equally spaced -\let\multistrut = \strut -\else -%% FIXME: what is \box0 supposed to be? -\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 -width0pt\relax} \fi -%% Test to see if parskip is larger than space between lines of -%% table. If not, do nothing. -%% If so, set to same dimension as multitablelinespace. +\fi +% Test to see if parskip is larger than space between lines of +% table. If not, do nothing. +% If so, set to same dimension as multitablelinespace. \ifdim\multitableparskip>\multitablelinespace \global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. +\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller + % than skip between lines in the table. \fi% \ifdim\multitableparskip=0pt \global\multitableparskip=\multitablelinespace -\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller - %% than skip between lines in the table. +\global\advance\multitableparskip-7pt % to keep parskip somewhat smaller + % than skip between lines in the table. \fi} @@ -2791,6 +4073,7 @@ width0pt\relax} \fi \def\doignore#1{\begingroup % Scan in ``verbatim'' mode: + \obeylines \catcode`\@ = \other \catcode`\{ = \other \catcode`\} = \other @@ -2811,16 +4094,16 @@ width0pt\relax} \fi \gdef\dodoignore#1{% % #1 contains the command name as a string, e.g., `ifinfo'. % - % Define a command to find the next `@end #1', which must be on a line - % by itself. - \long\def\doignoretext##1^^M@end #1{\doignoretextyyy##1^^M@#1\_STOP_}% + % Define a command to find the next `@end #1'. + \long\def\doignoretext##1^^M@end #1{% + \doignoretextyyy##1^^M@#1\_STOP_}% + % % And this command to find another #1 command, at the beginning of a % line. (Otherwise, we would consider a line `@c @ifset', for % example, to count as an @ifset for nesting.) \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% % % And now expand that command. - \obeylines % \doignoretext ^^M% }% } @@ -2850,7 +4133,12 @@ width0pt\relax} \fi } % Finish off ignored text. -\def\enddoignore{\endgroup\ignorespaces} +{ \obeylines% + % Ignore anything after the last `@end #1'; this matters in verbatim + % environments, where otherwise the newline after an ignored conditional + % would result in a blank line in the output. + \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% +} % @set VAR sets the variable VAR to an empty value. @@ -2900,7 +4188,7 @@ width0pt\relax} \fi % ..., but we might end up with active ones in the argument if % we're called from @code, as @code{@value{foo-bar_}}, though. % So \let them to their normal equivalents. - \let-\realdash \let_\normalunderscore + \let-\normaldash \let_\normalunderscore } } @@ -2940,7 +4228,7 @@ width0pt\relax} \fi } \def\ifsetfail{\doignore{ifset}} -% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% @ifclear VAR ... @end executes the `...' iff VAR has never been % defined with @set, or has been undefined with @clear. % % The `\else' inside the `\doifset' parameter is a trick to reuse the @@ -2951,6 +4239,35 @@ width0pt\relax} \fi \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} \def\ifclearfail{\doignore{ifclear}} +% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written +% without the @) is in fact defined. We can only feasibly check at the +% TeX level, so something like `mathcode' is going to considered +% defined even though it is not a Texinfo command. +% +\makecond{ifcommanddefined} +\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}} +% +\def\doifcmddefined#1#2{{% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname #2\endcsname\relax + #1% If not defined, \let\next as above. + \fi + \expandafter + }\next +} +\def\ifcmddefinedfail{\doignore{ifcommanddefined}} + +% @ifcommandnotdefined CMD ... handled similar to @ifclear above. +\makecond{ifcommandnotdefined} +\def\ifcommandnotdefined{% + \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}} +\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}} + +% Set the `txicommandconditionals' variable, so documents have a way to +% test if the @ifcommand...defined conditionals are available. +\set txicommandconditionals + % @dircategory CATEGORY -- specify a category of the dir file % which this file should belong to. Ignore this in TeX. \let\dircategory=\comment @@ -2963,9 +4280,8 @@ width0pt\relax} \fi % Index generation facilities % Define \newwrite to be identical to plain tex's \newwrite -% except not \outer, so it can be used within \newindex. -{\catcode`\@=11 -\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} +% except not \outer, so it can be used within macros and \if's. +\edef\newwrite{\makecsname{ptexnewwrite}} % \newindex {foo} defines an index named foo. % It automatically defines \fooindex such that @@ -3016,11 +4332,11 @@ width0pt\relax} \fi \def\dosynindex#1#2#3{% % Only do \closeout if we haven't already done it, else we'll end up % closing the target index. - \expandafter \ifx\csname donesynindex#2\endcsname \undefined + \expandafter \ifx\csname donesynindex#2\endcsname \relax % The \closeout helps reduce unnecessary open files; the limit on the % Acorn RISC OS is a mere 16 files. \expandafter\closeout\csname#2indfile\endcsname - \expandafter\let\csname\donesynindex#2\endcsname = 1 + \expandafter\let\csname donesynindex#2\endcsname = 1 \fi % redefine \fooindfile: \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname @@ -3051,18 +4367,73 @@ width0pt\relax} \fi % we have to laboriously prevent expansion for those that we don't. % \def\indexdummies{% + \escapechar = `\\ % use backslash in output files. \def\@{@}% change to @@ when we switch to @ as escape char in index files. \def\ {\realbackslash\space }% - % Need these in case \tex is in effect and \{ is a \delimiter again. - % But can't use \lbracecmd and \rbracecmd because texindex assumes - % braces and backslashes are used only as delimiters. - \let\{ = \mylbrace - \let\} = \myrbrace % - % \definedummyword defines \#1 as \realbackslash #1\space, thus - % effectively preventing its expansion. This is used only for control - % words, not control letters, because the \space would be incorrect - % for control characters, but is needed to separate the control word + % Need these unexpandable (because we define \tt as a dummy) + % definitions when @{ or @} appear in index entry text. Also, more + % complicated, when \tex is in effect and \{ is a \delimiter again. + % We can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. Perhaps we + % should define @lbrace and @rbrace commands a la @comma. + \def\{{{\tt\char123}}% + \def\}{{\tt\char125}}% + % + % I don't entirely understand this, but when an index entry is + % generated from a macro call, the \endinput which \scanmacro inserts + % causes processing to be prematurely terminated. This is, + % apparently, because \indexsorttmp is fully expanded, and \endinput + % is an expandable command. The redefinition below makes \endinput + % disappear altogether for that purpose -- although logging shows that + % processing continues to some further point. On the other hand, it + % seems \endinput does not hurt in the printed index arg, since that + % is still getting written without apparent harm. + % + % Sample source (mac-idx3.tex, reported by Graham Percival to + % help-texinfo, 22may06): + % @macro funindex {WORD} + % @findex xyz + % @end macro + % ... + % @funindex commtest + % + % The above is not enough to reproduce the bug, but it gives the flavor. + % + % Sample whatsit resulting: + % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} + % + % So: + \let\endinput = \empty + % + % Do the redefinitions. + \commondummies +} + +% For the aux and toc files, @ is the escape character. So we want to +% redefine everything using @ as the escape character (instead of +% \realbackslash, still used for index files). When everything uses @, +% this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % Do the redefinitions. + \commondummies + \otherbackslash +} + +% Called from \indexdummies and \atdummies. +% +\def\commondummies{% + % + % \definedummyword defines \#1 as \string\#1\space, thus effectively + % preventing its expansion. This is used only for control words, + % not control letters, because the \space would be incorrect for + % control characters, but is needed to separate the control word % from whatever follows. % % For control letters, we have \definedummyletter, which omits the @@ -3072,168 +4443,162 @@ width0pt\relax} \fi % those that do not. If it is followed by {arg} in the input, then % that will dutifully get written to the index (or wherever). % - \def\definedummyword##1{% - \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}% - }% - \def\definedummyletter##1{% - \expandafter\def\csname ##1\endcsname{\realbackslash ##1}% - }% + \def\definedummyword ##1{\def##1{\string##1\space}}% + \def\definedummyletter##1{\def##1{\string##1}}% \let\definedummyaccent\definedummyletter % - % Do the redefinitions. - \commondummies -} - -% For the aux file, @ is the escape character. So we want to redefine -% everything using @ instead of \realbackslash. When everything uses -% @, this will be simpler. -% -\def\atdummies{% - \def\@{@@}% - \def\ {@ }% - \let\{ = \lbraceatcmd - \let\} = \rbraceatcmd - % - % (See comments in \indexdummies.) - \def\definedummyword##1{% - \expandafter\def\csname ##1\endcsname{@##1\space}% - }% - \def\definedummyletter##1{% - \expandafter\def\csname ##1\endcsname{@##1}% - }% - \let\definedummyaccent\definedummyletter - % - % Do the redefinitions. - \commondummies -} - -% Called from \indexdummies and \atdummies. \definedummyword and -% \definedummyletter must be defined first. -% -\def\commondummies{% - % - \normalturnoffactive - % \commondummiesnofonts % - \definedummyletter{_}% + \definedummyletter\_% + \definedummyletter\-% % % Non-English letters. - \definedummyword{AA}% - \definedummyword{AE}% - \definedummyword{L}% - \definedummyword{OE}% - \definedummyword{O}% - \definedummyword{aa}% - \definedummyword{ae}% - \definedummyword{l}% - \definedummyword{oe}% - \definedummyword{o}% - \definedummyword{ss}% - \definedummyword{exclamdown}% - \definedummyword{questiondown}% - \definedummyword{ordf}% - \definedummyword{ordm}% + \definedummyword\AA + \definedummyword\AE + \definedummyword\DH + \definedummyword\L + \definedummyword\O + \definedummyword\OE + \definedummyword\TH + \definedummyword\aa + \definedummyword\ae + \definedummyword\dh + \definedummyword\exclamdown + \definedummyword\l + \definedummyword\o + \definedummyword\oe + \definedummyword\ordf + \definedummyword\ordm + \definedummyword\questiondown + \definedummyword\ss + \definedummyword\th % % Although these internal commands shouldn't show up, sometimes they do. - \definedummyword{bf}% - \definedummyword{gtr}% - \definedummyword{hat}% - \definedummyword{less}% - \definedummyword{sf}% - \definedummyword{sl}% - \definedummyword{tclose}% - \definedummyword{tt}% + \definedummyword\bf + \definedummyword\gtr + \definedummyword\hat + \definedummyword\less + \definedummyword\sf + \definedummyword\sl + \definedummyword\tclose + \definedummyword\tt % - \definedummyword{LaTeX}% - \definedummyword{TeX}% + \definedummyword\LaTeX + \definedummyword\TeX % % Assorted special characters. - \definedummyword{bullet}% - \definedummyword{comma}% - \definedummyword{copyright}% - \definedummyword{registeredsymbol}% - \definedummyword{dots}% - \definedummyword{enddots}% - \definedummyword{equiv}% - \definedummyword{error}% - \definedummyword{expansion}% - \definedummyword{minus}% - \definedummyword{pounds}% - \definedummyword{point}% - \definedummyword{print}% - \definedummyword{result}% + \definedummyword\arrow + \definedummyword\bullet + \definedummyword\comma + \definedummyword\copyright + \definedummyword\registeredsymbol + \definedummyword\dots + \definedummyword\enddots + \definedummyword\entrybreak + \definedummyword\equiv + \definedummyword\error + \definedummyword\euro + \definedummyword\expansion + \definedummyword\geq + \definedummyword\guillemetleft + \definedummyword\guillemetright + \definedummyword\guilsinglleft + \definedummyword\guilsinglright + \definedummyword\lbracechar + \definedummyword\leq + \definedummyword\minus + \definedummyword\ogonek + \definedummyword\pounds + \definedummyword\point + \definedummyword\print + \definedummyword\quotedblbase + \definedummyword\quotedblleft + \definedummyword\quotedblright + \definedummyword\quoteleft + \definedummyword\quoteright + \definedummyword\quotesinglbase + \definedummyword\rbracechar + \definedummyword\result + \definedummyword\textdegree + % + % We want to disable all macros so that they are not expanded by \write. + \macrolist + % + \normalturnoffactive % % Handle some cases of @value -- where it does not contain any % (non-fully-expandable) commands. \makevalueexpandable - % - % Normal spaces, not active ones. - \unsepspaces - % - % No macro expansion. - \turnoffmacros } % \commondummiesnofonts: common to \commondummies and \indexnofonts. % -% Better have this without active chars. -{ - \catcode`\~=\other - \gdef\commondummiesnofonts{% - % Control letters and accents. - \definedummyletter{!}% - \definedummyaccent{"}% - \definedummyaccent{'}% - \definedummyletter{*}% - \definedummyaccent{,}% - \definedummyletter{.}% - \definedummyletter{/}% - \definedummyletter{:}% - \definedummyaccent{=}% - \definedummyletter{?}% - \definedummyaccent{^}% - \definedummyaccent{`}% - \definedummyaccent{~}% - \definedummyword{u}% - \definedummyword{v}% - \definedummyword{H}% - \definedummyword{dotaccent}% - \definedummyword{ringaccent}% - \definedummyword{tieaccent}% - \definedummyword{ubaraccent}% - \definedummyword{udotaccent}% - \definedummyword{dotless}% - % - % Texinfo font commands. - \definedummyword{b}% - \definedummyword{i}% - \definedummyword{r}% - \definedummyword{sc}% - \definedummyword{t}% - % - % Commands that take arguments. - \definedummyword{acronym}% - \definedummyword{cite}% - \definedummyword{code}% - \definedummyword{command}% - \definedummyword{dfn}% - \definedummyword{emph}% - \definedummyword{env}% - \definedummyword{file}% - \definedummyword{kbd}% - \definedummyword{key}% - \definedummyword{math}% - \definedummyword{option}% - \definedummyword{samp}% - \definedummyword{strong}% - \definedummyword{tie}% - \definedummyword{uref}% - \definedummyword{url}% - \definedummyword{var}% - \definedummyword{verb}% - \definedummyword{w}% - } +\def\commondummiesnofonts{% + % Control letters and accents. + \definedummyletter\!% + \definedummyaccent\"% + \definedummyaccent\'% + \definedummyletter\*% + \definedummyaccent\,% + \definedummyletter\.% + \definedummyletter\/% + \definedummyletter\:% + \definedummyaccent\=% + \definedummyletter\?% + \definedummyaccent\^% + \definedummyaccent\`% + \definedummyaccent\~% + \definedummyword\u + \definedummyword\v + \definedummyword\H + \definedummyword\dotaccent + \definedummyword\ogonek + \definedummyword\ringaccent + \definedummyword\tieaccent + \definedummyword\ubaraccent + \definedummyword\udotaccent + \definedummyword\dotless + % + % Texinfo font commands. + \definedummyword\b + \definedummyword\i + \definedummyword\r + \definedummyword\sansserif + \definedummyword\sc + \definedummyword\slanted + \definedummyword\t + % + % Commands that take arguments. + \definedummyword\abbr + \definedummyword\acronym + \definedummyword\anchor + \definedummyword\cite + \definedummyword\code + \definedummyword\command + \definedummyword\dfn + \definedummyword\dmn + \definedummyword\email + \definedummyword\emph + \definedummyword\env + \definedummyword\file + \definedummyword\image + \definedummyword\indicateurl + \definedummyword\inforef + \definedummyword\kbd + \definedummyword\key + \definedummyword\math + \definedummyword\option + \definedummyword\pxref + \definedummyword\ref + \definedummyword\samp + \definedummyword\strong + \definedummyword\tie + \definedummyword\uref + \definedummyword\url + \definedummyword\var + \definedummyword\verb + \definedummyword\w + \definedummyword\xref } % \indexnofonts is used when outputting the strings to sort the index @@ -3243,14 +4608,10 @@ width0pt\relax} \fi % \def\indexnofonts{% % Accent commands should become @asis. - \def\definedummyaccent##1{% - \expandafter\let\csname ##1\endcsname\asis - }% + \def\definedummyaccent##1{\let##1\asis}% % We can just ignore other control letters. - \def\definedummyletter##1{% - \expandafter\def\csname ##1\endcsname{}% - }% - % Hopefully, all control words can become @asis. + \def\definedummyletter##1{\let##1\empty}% + % All control words become @asis by default; overrides below. \let\definedummyword\definedummyaccent % \commondummiesnofonts @@ -3262,50 +4623,95 @@ width0pt\relax} \fi % \def\ { }% \def\@{@}% - % how to handle braces? \def\_{\normalunderscore}% + \def\-{}% @- shouldn't affect sorting + % + % Unfortunately, texindex is not prepared to handle braces in the + % content at all. So for index sorting, we map @{ and @} to strings + % starting with |, since that ASCII character is between ASCII { and }. + \def\{{|a}% + \def\lbracechar{|a}% + % + \def\}{|b}% + \def\rbracechar{|b}% % % Non-English letters. \def\AA{AA}% \def\AE{AE}% + \def\DH{DZZ}% \def\L{L}% \def\OE{OE}% \def\O{O}% + \def\TH{ZZZ}% \def\aa{aa}% \def\ae{ae}% + \def\dh{dzz}% + \def\exclamdown{!}% \def\l{l}% \def\oe{oe}% - \def\o{o}% - \def\ss{ss}% - \def\exclamdown{!}% - \def\questiondown{?}% \def\ordf{a}% \def\ordm{o}% + \def\o{o}% + \def\questiondown{?}% + \def\ss{ss}% + \def\th{zzz}% % \def\LaTeX{LaTeX}% \def\TeX{TeX}% % % Assorted special characters. % (The following {} will end up in the sort string, but that's ok.) + \def\arrow{->}% \def\bullet{bullet}% \def\comma{,}% \def\copyright{copyright}% - \def\registeredsymbol{R}% \def\dots{...}% \def\enddots{...}% \def\equiv{==}% \def\error{error}% + \def\euro{euro}% \def\expansion{==>}% + \def\geq{>=}% + \def\guillemetleft{<<}% + \def\guillemetright{>>}% + \def\guilsinglleft{<}% + \def\guilsinglright{>}% + \def\leq{<=}% \def\minus{-}% - \def\pounds{pounds}% \def\point{.}% + \def\pounds{pounds}% \def\print{-|}% + \def\quotedblbase{"}% + \def\quotedblleft{"}% + \def\quotedblright{"}% + \def\quoteleft{`}% + \def\quoteright{'}% + \def\quotesinglbase{,}% + \def\registeredsymbol{R}% \def\result{=>}% + \def\textdegree{o}% % - % Don't write macro names. - \emptyusermacros + \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax + \else \indexlquoteignore \fi + % + % We need to get rid of all macros, leaving only the arguments (if present). + % Of course this is not nearly correct, but it is the best we can do for now. + % makeinfo does not expand macros in the argument to @deffn, which ends up + % writing an index entry, and texindex isn't prepared for an index sort entry + % that starts with \. + % + % Since macro invocations are followed by braces, we can just redefine them + % to take a single TeX argument. The case of a macro invocation that + % goes to end-of-line is not handled. + % + \macrolist } +% Undocumented (for FSFS 2nd ed.): @set txiindexlquoteignore makes us +% ignore left quotes in the sort term. +{\catcode`\`=\active + \gdef\indexlquoteignore{\let`=\empty}} + \let\indexbackslash=0 %overridden during \printindex. \let\SETmarginindex=\relax % put index entries in margin (undocumented)? @@ -3331,11 +4737,7 @@ width0pt\relax} \fi % \edef\writeto{\csname#1indfile\endcsname}% % - \ifvmode - \dosubindsanitize - \else - \dosubindwrite - \fi + \safewhatsit\dosubindwrite }% \fi } @@ -3350,7 +4752,6 @@ width0pt\relax} \fi % % Remember, we are within a group. \indexdummies % Must do this here, since \bf, etc expand at this stage - \escapechar=`\\ \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now % so it will be output as is; and it will print as backslash. % @@ -3373,13 +4774,13 @@ width0pt\relax} \fi \temp } -% Take care of unwanted page breaks: +% Take care of unwanted page breaks/skips around a whatsit: % % If a skip is the last thing on the list now, preserve it % by backing up by \lastskip, doing the \write, then inserting % the skip again. Otherwise, the whatsit generated by the -% \write will make \lastskip zero. The result is that sequences -% like this: +% \write or \pdfdest will make \lastskip zero. The result is that +% sequences like this: % @end defun % @tindex whatever % @defun ... @@ -3403,25 +4804,30 @@ width0pt\relax} \fi % \edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} % +\newskip\whatsitskip +\newcount\whatsitpenalty +% % ..., ready, GO: % -\def\dosubindsanitize{% +\def\safewhatsit#1{\ifhmode + #1% + \else % \lastskip and \lastpenalty cannot both be nonzero simultaneously. - \skip0 = \lastskip + \whatsitskip = \lastskip \edef\lastskipmacro{\the\lastskip}% - \count255 = \lastpenalty + \whatsitpenalty = \lastpenalty % % If \lastskip is nonzero, that means the last item was a % skip. And since a skip is discardable, that means this - % -\skip0 glue we're inserting is preceded by a + % -\whatsitskip glue we're inserting is preceded by a % non-discardable item, therefore it is not a potential % breakpoint, therefore no \nobreak needed. \ifx\lastskipmacro\zeroskipmacro \else - \vskip-\skip0 + \vskip-\whatsitskip \fi % - \dosubindwrite + #1% % \ifx\lastskipmacro\zeroskipmacro % If \lastskip was zero, perhaps the last item was a penalty, and @@ -3429,20 +4835,19 @@ width0pt\relax} \fi % to re-insert the same penalty (values >10000 are used for various % signals); since we just inserted a non-discardable item, any % following glue (such as a \parskip) would be a breakpoint. For example: - % % @deffn deffn-whatever % @vindex index-whatever % Description. % would allow a break between the index-whatever whatsit % and the "Description." paragraph. - \ifnum\count255>9999 \penalty\count255 \fi + \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi \else % On the other hand, if we had a nonzero \lastskip, % this make-up glue would be preceded by a non-discardable item % (the whatsit from the \write), so we must insert a \nobreak. - \nobreak\vskip\skip0 + \nobreak\vskip\whatsitskip \fi -} +\fi} % The index entry written in the file actually looks like % \entry {sortstring}{page}{topic} @@ -3484,6 +4889,7 @@ width0pt\relax} \fi % \smallfonts \rm \tolerance = 9500 + \plainfrenchspacing \everypar = {}% don't want the \kern\-parindent from indentation suppression. % % See if the index file exists and is nonempty. @@ -3557,10 +4963,9 @@ width0pt\relax} \fi % % A straightforward implementation would start like this: % \def\entry#1#2{... -% But this frozes the catcodes in the argument, and can cause problems to +% But this freezes the catcodes in the argument, and can cause problems to % @code, which sets - active. This problem was fixed by a kludge--- % ``-'' was active throughout whole index, but this isn't really right. -% % The right solution is to prevent \entry from swallowing the whole text. % --kasal, 21nov03 \def\entry{% @@ -3597,10 +5002,17 @@ width0pt\relax} \fi % columns. \vskip 0pt plus1pt % + % When reading the text of entry, convert explicit line breaks + % from @* into spaces. The user might give these in long section + % titles, for instance. + \def\*{\unskip\space\ignorespaces}% + \def\entrybreak{\hfil\break}% + % % Swallow the left brace of the text (first parameter): \afterassignment\doentry \let\temp = } +\def\entrybreak{\unskip\space\ignorespaces}% \def\doentry{% \bgroup % Instead of the swallowed brace. \noindent @@ -3613,11 +5025,8 @@ width0pt\relax} \fi % The following is kludged to not output a line of dots in the index if % there are no page numbers. The next person who breaks this will be % cursed by a Unix daemon. - \def\tempa{{\rm }}% - \def\tempb{#1}% - \edef\tempc{\tempa}% - \edef\tempd{\tempb}% - \ifx\tempc\tempd + \setbox\boxA = \hbox{#1}% + \ifdim\wd\boxA = 0pt \ % \else % @@ -3641,9 +5050,9 @@ width0pt\relax} \fi \endgroup } -% Like \dotfill except takes at least 1 em. +% Like plain.tex's \dotfill, except uses up at least 1 em. \def\indexdotfill{\cleaders - \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} \def\primary #1{\line{#1\hfil}} @@ -3753,6 +5162,34 @@ width0pt\relax} \fi % % All done with double columns. \def\enddoublecolumns{% + % The following penalty ensures that the page builder is exercised + % _before_ we change the output routine. This is necessary in the + % following situation: + % + % The last section of the index consists only of a single entry. + % Before this section, \pagetotal is less than \pagegoal, so no + % break occurs before the last section starts. However, the last + % section, consisting of \initial and the single \entry, does not + % fit on the page and has to be broken off. Without the following + % penalty the page builder will not be exercised until \eject + % below, and by that time we'll already have changed the output + % routine to the \balancecolumns version, so the next-to-last + % double-column page will be processed with \balancecolumns, which + % is wrong: The two columns will go to the main vertical list, with + % the broken-off section in the recent contributions. As soon as + % the output routine finishes, TeX starts reconsidering the page + % break. The two columns and the broken-off section both fit on the + % page, because the two columns now take up only half of the page + % goal. When TeX sees \eject from below which follows the final + % section, it invokes the new output routine that we've set after + % \balancecolumns below; \onepageout will try to fit the two columns + % and the final section into the vbox of \pageheight (see + % \pagebody), causing an overfull box. + % + % Note that glue won't work here, because glue does not exercise the + % page builder, unlike penalties (see The TeXbook, pp. 280-281). + \penalty0 + % \output = {% % Split the last of the double-column material. Leave it on the % current page, no automatic page break. @@ -3808,7 +5245,22 @@ width0pt\relax} \fi \message{sectioning,} % Chapters, sections, etc. -% \unnumberedno is an oxymoron, of course. But we count the unnumbered +% Let's start with @part. +\outer\parseargdef\part{\partzzz{#1}} +\def\partzzz#1{% + \chapoddpage + \null + \vskip.3\vsize % move it down on the page a bit + \begingroup + \noindent \titlefonts\rmisbold #1\par % the text + \let\lastnode=\empty % no node to associate with + \writetocentry{part}{#1}{}% but put it in the toc + \headingsoff % no headline or footline on the part page + \chapoddpage + \endgroup +} + +% \unnumberedno is an oxymoron. But we count the unnumbered % sections so that we can refer to them unambiguously in the pdf % outlines by their "section number". We avoid collisions with chapter % numbers by starting them at 10000. (If a document ever has 10000 @@ -3862,11 +5314,15 @@ width0pt\relax} \fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} -% Each @chapter defines this as the name of the chapter. -% page headings and footings can use it. @section does likewise. -% However, they are not reliable, because we don't use marks. +% Each @chapter defines these (using marks) as the number+name, number +% and name of the chapter. Page headings and footings can use +% these. @section does likewise. \def\thischapter{} +\def\thischapternum{} +\def\thischaptername{} \def\thissection{} +\def\thissectionnum{} +\def\thissectionname{} \newcount\absseclevel % used to calculate proper heading level \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count @@ -3883,8 +5339,8 @@ width0pt\relax} \fi \chardef\maxseclevel = 3 % % A numbered section within an unnumbered changes to unnumbered too. -% To achive this, remember the "biggest" unnum. sec. we are currently in: -\chardef\unmlevel = \maxseclevel +% To achieve this, remember the "biggest" unnum. sec. we are currently in: +\chardef\unnlevel = \maxseclevel % % Trace whether the current chapter is an appendix or not: % \chapheadtype is "N" or "A", unnumbered chapters are ignored. @@ -3909,8 +5365,8 @@ width0pt\relax} \fi % The heading type: \def\headtype{#1}% \if \headtype U% - \ifnum \absseclevel < \unmlevel - \chardef\unmlevel = \absseclevel + \ifnum \absseclevel < \unnlevel + \chardef\unnlevel = \absseclevel \fi \else % Check for appendix sections: @@ -3922,10 +5378,10 @@ width0pt\relax} \fi \fi\fi \fi % Check for numbered within unnumbered: - \ifnum \absseclevel > \unmlevel + \ifnum \absseclevel > \unnlevel \def\headtype{U}% \else - \chardef\unmlevel = 3 + \chardef\unnlevel = 3 \fi \fi % Now print the heading: @@ -3979,7 +5435,9 @@ width0pt\relax} \fi \gdef\chaplevelprefix{\the\chapno.}% \resetallfloatnos % - \message{\putwordChapter\space \the\chapno}% + % \putwordChapter can contain complex things in translations. + \toks0=\expandafter{\putwordChapter}% + \message{\the\toks0 \space \the\chapno}% % % Write the actual heading. \chapmacro{#1}{Ynumbered}{\the\chapno}% @@ -3990,15 +5448,17 @@ width0pt\relax} \fi \global\let\subsubsection = \numberedsubsubsec } -\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz +\outer\parseargdef\appendix{\apphead0{#1}} % normally calls appendixzzz +% \def\appendixzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\appendixno by 1 \gdef\chaplevelprefix{\appendixletter.}% \resetallfloatnos % - \def\appendixnum{\putwordAppendix\space \appendixletter}% - \message{\appendixnum}% + % \putwordAppendix can contain complex things in translations. + \toks0=\expandafter{\putwordAppendix}% + \message{\the\toks0 \space \appendixletter}% % \chapmacro{#1}{Yappendix}{\appendixletter}% % @@ -4007,7 +5467,8 @@ width0pt\relax} \fi \global\let\subsubsection = \appendixsubsubsec } -\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +% normally unnmhead0 calls unnumberedzzz: +\outer\parseargdef\unnumbered{\unnmhead0{#1}} \def\unnumberedzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\unnumberedno by 1 @@ -4051,40 +5512,47 @@ width0pt\relax} \fi \let\top\unnumbered % Sections. +% \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz \def\seczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% } -\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz +% normally calls appendixsectionzzz: +\outer\parseargdef\appendixsection{\apphead1{#1}} \def\appendixsectionzzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% } \let\appendixsec\appendixsection -\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz +% normally calls unnumberedseczzz: +\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} \def\unnumberedseczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % Subsections. -\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz +% +% normally calls numberedsubseczzz: +\outer\parseargdef\numberedsubsec{\numhead2{#1}} \def\numberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% } -\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz +% normally calls appendixsubseczzz: +\outer\parseargdef\appendixsubsec{\apphead2{#1}} \def\appendixsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno}% } -\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +% normally calls unnumberedsubseczzz: +\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} \def\unnumberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynothing}% @@ -4092,21 +5560,25 @@ width0pt\relax} \fi } % Subsubsections. -\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz +% +% normally numberedsubsubseczzz: +\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} \def\numberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynumbered}% {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% } -\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz +% normally appendixsubsubseczzz: +\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} \def\appendixsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% } -\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +% normally unnumberedsubsubseczzz: +\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} \def\unnumberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynothing}% @@ -4122,15 +5594,6 @@ width0pt\relax} \fi % Define @majorheading, @heading and @subheading -% NOTE on use of \vbox for chapter headings, section headings, and such: -% 1) We use \vbox rather than the earlier \line to permit -% overlong headings to fold. -% 2) \hyphenpenalty is set to 10000 because hyphenation in a -% heading is obnoxious; this forbids it. -% 3) Likewise, headings look best if no \parindent is used, and -% if justification is not attempted. Hence \raggedright. - - \def\majorheading{% {\advance\chapheadingskip by 10pt \chapbreak }% \parsearg\chapheadingzzz @@ -4138,10 +5601,8 @@ width0pt\relax} \fi \def\chapheading{\chapbreak \parsearg\chapheadingzzz} \def\chapheadingzzz#1{% - {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}% - \bigskip \par\penalty 200\relax + \vbox{\chapfonts \raggedtitlesettings #1\par}% + \nobreak\bigskip \nobreak \suppressfirstparagraphindent } @@ -4157,17 +5618,28 @@ width0pt\relax} \fi % (including whitespace, linebreaking, etc. around it), % given all the information in convenient, parsed form. -%%% Args are the skip and penalty (usually negative) +% Args are the skip and penalty (usually negative) \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} -%%% Define plain chapter starts, and page on/off switching for it % Parameter controlling skip before chapter headings (if needed) - \newskip\chapheadingskip +% Define plain chapter starts, and page on/off switching for it. \def\chapbreak{\dobreak \chapheadingskip {-4000}} \def\chappager{\par\vfill\supereject} -\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} +% Because \domark is called before \chapoddpage, the filler page will +% get the headings for the next chapter, which is wrong. But we don't +% care -- we just disable all headings on the filler page. +\def\chapoddpage{% + \chappager + \ifodd\pageno \else + \begingroup + \headingsoff + \null + \chappager + \endgroup + \fi +} \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} @@ -4201,41 +5673,78 @@ width0pt\relax} \fi \def\Yappendixkeyword{Yappendix} % \def\chapmacro#1#2#3{% + % Insert the first mark before the heading break (see notes for \domark). + \let\prevchapterdefs=\lastchapterdefs + \let\prevsectiondefs=\lastsectiondefs + \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% + \gdef\thissection{}}% + % + \def\temptype{#2}% + \ifx\temptype\Ynothingkeyword + \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{\thischaptername}}% + \else\ifx\temptype\Yomitfromtockeyword + \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\thischapter{}}% + \else\ifx\temptype\Yappendixkeyword + \toks0={#1}% + \xdef\lastchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\appendixletter}% + % \noexpand\putwordAppendix avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thischapter{\noexpand\putwordAppendix{} + \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \else + \toks0={#1}% + \xdef\lastchapterdefs{% + \gdef\noexpand\thischaptername{\the\toks0}% + \gdef\noexpand\thischapternum{\the\chapno}% + % \noexpand\putwordChapter avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thischapter{\noexpand\putwordChapter{} + \noexpand\thischapternum: + \noexpand\thischaptername}% + }% + \fi\fi\fi + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark + % + % Insert the chapter heading break. \pchapsepmacro + % + % Now the second mark, after the heading break. No break points + % between here and the heading. + \let\prevchapterdefs=\lastchapterdefs + \let\prevsectiondefs=\lastsectiondefs + \domark + % {% - \chapfonts \rm + \chapfonts \rmisbold % - % Have to define \thissection before calling \donoderef, because the + % Have to define \lastsection before calling \donoderef, because the % xref code eventually uses it. On the other hand, it has to be called % after \pchapsepmacro, or the headline will change too soon. - \gdef\thissection{#1}% - \gdef\thischaptername{#1}% + \gdef\lastsection{#1}% % % Only insert the separating space if we have a chapter/appendix % number, and don't print the unnumbered ``number''. - \def\temptype{#2}% \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unnchap}% - \def\thischapter{#1}% \else\ifx\temptype\Yomitfromtockeyword \setbox0 = \hbox{}% contents like unnumbered, but no toc entry \def\toctype{omit}% - \xdef\thischapter{}% \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% \def\toctype{app}% - % We don't substitute the actual chapter name into \thischapter - % because we don't want its macros evaluated now. And we don't - % use \thissection because that changes with each section. - % - \xdef\thischapter{\putwordAppendix{} \appendixletter: - \noexpand\thischaptername}% \else \setbox0 = \hbox{#3\enspace}% \def\toctype{numchap}% - \xdef\thischapter{\putwordChapter{} \the\chapno: - \noexpand\thischaptername}% \fi\fi\fi % % Write the toc entry for this chapter. Must come before the @@ -4251,8 +5760,8 @@ width0pt\relax} \fi \donoderef{#2}% % % Typeset the actual heading. - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright - \hangindent=\wd0 \centerparametersmaybe + \nobreak % Avoid page breaks at the interline glue. + \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe \unhbox0 #1\par}% }% \nobreak\bigskip % no page break after a chapter title @@ -4274,18 +5783,18 @@ width0pt\relax} \fi \def\setchapterstyle #1 {\csname CHAPF#1\endcsname} % \def\unnchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt\raggedright - \rm #1\hfill}}\bigskip \par\nobreak + \chapoddpage + \vbox{\chapfonts \raggedtitlesettings #1\par}% + \nobreak\bigskip\nobreak } \def\chfopen #1#2{\chapoddpage {\chapfonts \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% \par\penalty 5000 % } \def\centerchfopen #1{% -\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 - \parindent=0pt - \hfill {\rm #1}\hfill}}\bigskip \par\nobreak + \chapoddpage + \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}% + \nobreak\bigskip \nobreak } \def\CHAPFopen{% \global\let\chapmacro=\chfopen @@ -4313,47 +5822,110 @@ width0pt\relax} \fi % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the % section number. % +\def\seckeyword{sec} +% \def\sectionheading#1#2#3#4{% {% + \checkenv{}% should not be in an environment. + % % Switch to the right set of fonts. - \csname #2fonts\endcsname \rm + \csname #2fonts\endcsname \rmisbold + % + \def\sectionlevel{#2}% + \def\temptype{#3}% + % + % Insert first mark before the heading break (see notes for \domark). + \let\prevsectiondefs=\lastsectiondefs + \ifx\temptype\Ynothingkeyword + \ifx\sectionlevel\seckeyword + \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% + \gdef\thissection{\thissectionname}}% + \fi + \else\ifx\temptype\Yomitfromtockeyword + % Don't redefine \thissection. + \else\ifx\temptype\Yappendixkeyword + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\lastsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + % \noexpand\putwordSection avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thissection{\noexpand\putwordSection{} + \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \else + \ifx\sectionlevel\seckeyword + \toks0={#1}% + \xdef\lastsectiondefs{% + \gdef\noexpand\thissectionname{\the\toks0}% + \gdef\noexpand\thissectionnum{#4}% + % \noexpand\putwordSection avoids expanding indigestible + % commands in some of the translations. + \gdef\noexpand\thissection{\noexpand\putwordSection{} + \noexpand\thissectionnum: + \noexpand\thissectionname}% + }% + \fi + \fi\fi\fi + % + % Go into vertical mode. Usually we'll already be there, but we + % don't want the following whatsit to end up in a preceding paragraph + % if the document didn't happen to have a blank line. + \par + % + % Output the mark. Pass it through \safewhatsit, to take care of + % the preceding space. + \safewhatsit\domark % % Insert space above the heading. \csname #2headingbreak\endcsname % - % Only insert the space after the number if we have a section number. - \def\sectionlevel{#2}% - \def\temptype{#3}% + % Now the second mark, after the heading break. No break points + % between here and the heading. + \let\prevsectiondefs=\lastsectiondefs + \domark % + % Only insert the space after the number if we have a section number. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unn}% - \gdef\thissection{#1}% + \gdef\lastsection{#1}% \else\ifx\temptype\Yomitfromtockeyword % for @headings -- no section number, don't include in toc, - % and don't redefine \thissection. + % and don't redefine \lastsection. \setbox0 = \hbox{}% \def\toctype{omit}% \let\sectionlevel=\empty \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{#4\enspace}% \def\toctype{app}% - \gdef\thissection{#1}% + \gdef\lastsection{#1}% \else \setbox0 = \hbox{#4\enspace}% \def\toctype{num}% - \gdef\thissection{#1}% + \gdef\lastsection{#1}% \fi\fi\fi % - % Write the toc entry (before \donoderef). See comments in \chfplain. + % Write the toc entry (before \donoderef). See comments in \chapmacro. \writetocentry{\toctype\sectionlevel}{#1}{#4}% % % Write the node reference (= pdf destination for pdftex). - % Again, see comments in \chfplain. + % Again, see comments in \chapmacro. \donoderef{#3}% % + % Interline glue will be inserted when the vbox is completed. + % That glue will be a valid breakpoint for the page, since it'll be + % preceded by a whatsit (usually from the \donoderef, or from the + % \writetocentry if there was no node). We don't want to allow that + % break, since then the whatsits could end up on page n while the + % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. + \nobreak + % % Output the actual section heading. - \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright \hangindent=\wd0 % zero if no section number \unhbox0 #1}% }% @@ -4367,15 +5939,15 @@ width0pt\relax} \fi % % We'll almost certainly start a paragraph next, so don't let that % glue accumulate. (Not a breakpoint because it's preceded by a - % discardable item.) + % discardable item.) However, when a paragraph is not started next + % (\startdefun, \cartouche, \center, etc.), this needs to be wiped out + % or the negative glue will cause weirdly wrong output, typically + % obscuring the section heading with something else. \vskip-\parskip - % - % This is purely so the last item on the list is a known \penalty > - % 10000. This is so \startdefun can avoid allowing breakpoints after - % section headings. Otherwise, it would insert a valid breakpoint between: - % - % @section sec-whatever - % @deffn def-whatever + % + % This is so the last item on the main vertical list is a known + % \penalty > 10000, so \startdefun, etc., can recognize the situation + % and do the needful. \penalty 10001 } @@ -4410,11 +5982,11 @@ width0pt\relax} \fi \fi % \iflinks - \toks0 = {#2}% - \toks2 = \expandafter{\lastnode}% - \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}% - {\the\toks2}{\noexpand\folio}}}% - \temp + {\atdummies + \edef\temp{% + \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% + \temp + }% \fi \fi % @@ -4427,6 +5999,31 @@ width0pt\relax} \fi \ifpdf \global\pdfmakepagedesttrue \fi } + +% These characters do not print properly in the Computer Modern roman +% fonts, so we must take special care. This is more or less redundant +% with the Texinfo input format setup at the end of this file. +% +\def\activecatcodes{% + \catcode`\"=\active + \catcode`\$=\active + \catcode`\<=\active + \catcode`\>=\active + \catcode`\\=\active + \catcode`\^=\active + \catcode`\_=\active + \catcode`\|=\active + \catcode`\~=\active +} + + +% Read the toc file, which is essentially Texinfo input. +\def\readtocfile{% + \setupdatafile + \activecatcodes + \input \tocreadfilename +} + \newskip\contentsrightmargin \contentsrightmargin=1in \newcount\savepageno \newcount\lastnegativepageno \lastnegativepageno = -1 @@ -4443,29 +6040,29 @@ width0pt\relax} \fi % % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. - \def\thischapter{}% \chapmacro{#1}{Yomitfromtoc}{}% % \savepageno = \pageno \begingroup % Set up to handle contents files properly. - \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 - % We can't do this, because then an actual ^ in a section - % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. - %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi - \raggedbottom % Worry more about breakpoints than the bottom. + \raggedbottom % Worry more about breakpoints than the bottom. \advance\hsize by -\contentsrightmargin % Don't use the full line length. % % Roman numerals for page numbers. \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi } +% redefined for the two-volume lispref. We always output on +% \jobname.toc even if this is redefined. +% +\def\tocreadfilename{\jobname.toc} % Normal (long) toc. +% \def\contents{% \startcontents{\putwordTOC}% - \openin 1 \jobname.toc + \openin 1 \tocreadfilename\space \ifeof 1 \else - \input \jobname.toc + \readtocfile \fi \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect @@ -4482,6 +6079,7 @@ width0pt\relax} \fi \def\summarycontents{% \startcontents{\putwordShortTOC}% % + \let\partentry = \shortpartentry \let\numchapentry = \shortchapentry \let\appentry = \shortchapentry \let\unnchapentry = \shortunnchapentry @@ -4501,9 +6099,9 @@ width0pt\relax} \fi \let\numsubsubsecentry = \numsecentry \let\appsubsubsecentry = \numsecentry \let\unnsubsubsecentry = \numsecentry - \openin 1 \jobname.toc + \openin 1 \tocreadfilename\space \ifeof 1 \else - \input \jobname.toc + \readtocfile \fi \closein 1 \vfill \eject @@ -4537,6 +6135,19 @@ width0pt\relax} \fi % The last argument is the page number. % The arguments in between are the chapter number, section number, ... +% Parts, in the main contents. Replace the part number, which doesn't +% exist, with an empty box. Let's hope all the numbers have the same width. +% Also ignore the page number, which is conventionally not printed. +\def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}} +\def\partentry#1#2#3#4{\dochapentry{\numeralbox\labelspace#1}{}} +% +% Parts, in the short toc. +\def\shortpartentry#1#2#3#4{% + \penalty-300 + \vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip + \shortchapentry{{\bf #1}}{\numeralbox}{}{}% +} + % Chapters, in the main contents. \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} % @@ -4626,45 +6237,12 @@ width0pt\relax} \fi \message{environments,} % @foo ... @end foo. -% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. -% -% Since these characters are used in examples, it should be an even number of -% \tt widths. Each \tt character is 1en, so two makes it 1em. -% -\def\point{$\star$} -\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} -\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} -\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} -\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} - -% The @error{} command. -% Adapted from the TeXbook's \boxit. -% -\newbox\errorbox -% -{\tentt \global\dimen0 = 3em}% Width of the box. -\dimen2 = .55pt % Thickness of rules -% The text. (`r' is open on the right, `e' somewhat less so on the left.) -\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} -% -\setbox\errorbox=\hbox to \dimen0{\hfil - \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. - \advance\hsize by -2\dimen2 % Rules. - \vbox{% - \hrule height\dimen2 - \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. - \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. - \kern3pt\vrule width\dimen2}% Space to right. - \hrule height\dimen2} - \hfil} -% -\def\error{\leavevmode\lower.7ex\copy\errorbox} - -% @tex ... @end tex escapes into raw Tex temporarily. +% @tex ... @end tex escapes into raw TeX temporarily. % One exception: @ is still an escape character, so that @end tex works. -% But \@ or @@ will get a plain tex @ character. +% But \@ or @@ will get a plain @ character. \envdef\tex{% + \setupmarkupstyle{tex}% \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie @@ -4674,8 +6252,14 @@ width0pt\relax} \fi \catcode `\|=\other \catcode `\<=\other \catcode `\>=\other + \catcode`\`=\other + \catcode`\'=\other \escapechar=`\\ % + % ' is active in math mode (mathcode"8000). So reset it, and all our + % other math active characters (just in case), to plain's definitions. + \mathactive + % \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc @@ -4693,6 +6277,8 @@ width0pt\relax} \fi \let\/=\ptexslash \let\*=\ptexstar \let\t=\ptext + \expandafter \let\csname top\endcsname=\ptextop % outer + \let\frenchspacing=\plainfrenchspacing % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% @@ -4738,7 +6324,8 @@ width0pt\relax} \fi \let\afterenvbreak = \aboveenvbreak -% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will +% also clear it, so that its embedded environments do the narrowing again. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around @@ -4775,7 +6362,13 @@ width0pt\relax} \fi % each corner char, and rule thickness \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip % Flag to tell @lisp, etc., not to narrow margin. - \let\nonarrowing=\comment + \let\nonarrowing = t% + % + % If this cartouche directly follows a sectioning command, we need the + % \parskip glue (backspaced over by default) or the cartouche can + % collide with the section heading. + \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi + % \vbox\bgroup \baselineskip=0pt\parskip=0pt\lineskip=0pt \carttop @@ -4789,7 +6382,7 @@ width0pt\relax} \fi \lineskip=\normlskip \parskip=\normpskip \vskip -\parskip - \comment % For explanation, see the end of \def\group. + \comment % For explanation, see the end of def\group. } \def\Ecartouche{% \ifhmode\par\fi @@ -4806,6 +6399,7 @@ width0pt\relax} \fi % This macro is called at the beginning of all the @example variants, % inside a group. +\newdimen\nonfillparindent \def\nonfillstart{% \aboveenvbreak \hfuzz = 12pt % Don't be fussy @@ -4813,17 +6407,40 @@ width0pt\relax} \fi \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output \parskip = 0pt + % Turn off paragraph indentation but redefine \indent to emulate + % the normal \indent. + \nonfillparindent=\parindent \parindent = 0pt + \let\indent\nonfillindent + % \emergencystretch = 0pt % don't try to avoid overfull boxes - % @cartouche defines \nonarrowing to inhibit narrowing - % at next level down. \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing + \else + \let\nonarrowing = \relax \fi \let\exdent=\nofillexdent } +\begingroup +\obeyspaces +% We want to swallow spaces (but not other tokens) after the fake +% @indent in our nonfill-environments, where spaces are normally +% active and set to @tie, resulting in them not being ignored after +% @indent. +\gdef\nonfillindent{\futurelet\temp\nonfillindentcheck}% +\gdef\nonfillindentcheck{% +\ifx\temp % +\expandafter\nonfillindentgobble% +\else% +\leavevmode\nonfillindentbox% +\fi% +}% +\endgroup +\def\nonfillindentgobble#1{\nonfillindent} +\def\nonfillindentbox{\hbox to \nonfillparindent{\hss}} + % If you want all examples etc. small: @set dispenvsize small. % If you want even small examples the full size: @set dispenvsize nosmall. % This affects the following displayed environments: @@ -4834,53 +6451,59 @@ width0pt\relax} \fi \let\SETdispenvsize\relax \def\setnormaldispenv{% \ifx\SETdispenvsize\smallword + % end paragraph for sake of leading, in case document has no blank + % line. This is redundant with what happens in \aboveenvbreak, but + % we need to do it before changing the fonts, and it's inconvenient + % to change the fonts afterward. + \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } \def\setsmalldispenv{% \ifx\SETdispenvsize\nosmallword \else + \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } % We often define two environments, @foo and @smallfoo. -% Let's do it by one command: -\def\makedispenv #1#2{ - \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} - \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} +% Let's do it in one command. #1 is the env name, #2 the definition. +\def\makedispenvdef#1#2{% + \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}% + \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}% \expandafter\let\csname E#1\endcsname \afterenvbreak \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } -% Define two synonyms: -\def\maketwodispenvs #1#2#3{ - \makedispenv{#1}{#3} - \makedispenv{#2}{#3} +% Define two environment synonyms (#1 and #2) for an environment. +\def\maketwodispenvdef#1#2#3{% + \makedispenvdef{#1}{#3}% + \makedispenvdef{#2}{#3}% } - -% @lisp: indented, narrowed, typewriter font; @example: same as @lisp. +% +% @lisp: indented, narrowed, typewriter font; +% @example: same as @lisp. % % @smallexample and @smalllisp: use smaller fonts. % Originally contributed by Pavel@xerox. % -\maketwodispenvs {lisp}{example}{% +\maketwodispenvdef{lisp}{example}{% \nonfillstart - \tt + \tt\setupmarkupstyle{example}% \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. - \gobble % eat return + \gobble % eat return } - % @display/@smalldisplay: same as @lisp except keep current font. % -\makedispenv {display}{% +\makedispenvdef{display}{% \nonfillstart \gobble } % @format/@smallformat: same as @display except don't narrow margins. % -\makedispenv{format}{% +\makedispenvdef{format}{% \let\nonarrowing = t% \nonfillstart \gobble @@ -4899,27 +6522,47 @@ width0pt\relax} \fi \envdef\flushright{% \let\nonarrowing = t% \nonfillstart - \advance\leftskip by 0pt plus 1fill + \advance\leftskip by 0pt plus 1fill\relax \gobble } \let\Eflushright = \afterenvbreak +% @raggedright does more-or-less normal line breaking but no right +% justification. From plain.tex. +\envdef\raggedright{% + \rightskip0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax +} +\let\Eraggedright\par + +\envdef\raggedleft{% + \parindent=0pt \leftskip0pt plus2em + \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt + \hbadness=10000 % Last line will usually be underfull, so turn off + % badness reporting. +} +\let\Eraggedleft\par + +\envdef\raggedcenter{% + \parindent=0pt \rightskip0pt plus1em \leftskip0pt plus1em + \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt + \hbadness=10000 % Last line will usually be underfull, so turn off + % badness reporting. +} +\let\Eraggedcenter\par + + % @quotation does normal linebreaking (hence we can't use \nonfillstart) % and narrows the margins. We keep \parskip nonzero in general, since % we're doing normal filling. So, when using \aboveenvbreak and % \afterenvbreak, temporarily make \parskip 0. % -\envdef\quotation{% - {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip - \parindent=0pt - % - % @cartouche defines \nonarrowing to inhibit narrowing at next level down. +\makedispenvdef{quotation}{\quotationstart} +% +\def\quotationstart{% + \indentedblockstart % same as \indentedblock, but increase right margin too. \ifx\nonarrowing\relax - \advance\leftskip by \lispnarrowing \advance\rightskip by \lispnarrowing - \exdentamount = \lispnarrowing - \let\nonarrowing = \relax \fi \parsearg\quotationlabel } @@ -4929,12 +6572,13 @@ width0pt\relax} \fi % \def\Equotation{% \par - \ifx\quotationauthor\undefined\else + \ifx\quotationauthor\thisisundefined\else % indent a bit. \leftline{\kern 2\leftskip \sl ---\quotationauthor}% \fi {\parskip=0pt \afterenvbreak}% } +\def\Esmallquotation{\Equotation} % If we're given an argument, typeset it in bold with a colon after. \def\quotationlabel#1{% @@ -4944,6 +6588,32 @@ width0pt\relax} \fi \fi } +% @indentedblock is like @quotation, but indents only on the left and +% has no optional argument. +% +\makedispenvdef{indentedblock}{\indentedblockstart} +% +\def\indentedblockstart{% + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \exdentamount = \lispnarrowing + \else + \let\nonarrowing = \relax + \fi +} + +% Keep a nonzero parskip for the environment, since we're doing normal filling. +% +\def\Eindentedblock{% + \par + {\parskip=0pt \afterenvbreak}% +} +\def\Esmallindentedblock{\Eindentedblock} + % LaTeX-like @verbatim...@end verbatim and @verb{...} % If we want to allow any as delimiter, @@ -4959,18 +6629,16 @@ width0pt\relax} \fi \do\ \do\\\do\{\do\}\do\$\do\&% \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% \do\<\do\>\do\|\do\@\do+\do\"% + % Don't do the quotes -- if we do, @set txicodequoteundirected and + % @set txicodequotebacktick will not have effect on @verb and + % @verbatim, and ?` and !` ligatures won't get disabled. + %\do\`\do\'% } % % [Knuth] p. 380 \def\uncatcodespecials{% \def\do##1{\catcode`##1=\other}\dospecials} % -% [Knuth] pp. 380,381,391 -% Disable Spanish ligatures ?` and !` of \tt font -\begingroup - \catcode`\`=\active\gdef`{\relax\lq} -\endgroup -% % Setup for the @verb command. % % Eight spaces for a tab @@ -4982,7 +6650,7 @@ width0pt\relax} \fi \def\setupverb{% \tt % easiest (and conventionally used) font for verbatim \def\par{\leavevmode\endgraf}% - \catcode`\`=\active + \setupmarkupstyle{verb}% \tabeightspaces % Respect line breaks, % print special symbols as themselves, and @@ -4993,35 +6661,46 @@ width0pt\relax} \fi % Setup for the @verbatim environment % -% Real tab expansion +% Real tab expansion. \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount % -\def\starttabbox{\setbox0=\hbox\bgroup} +% We typeset each line of the verbatim in an \hbox, so we can handle +% tabs. The \global is in case the verbatim line starts with an accent, +% or some other command that starts with a begin-group. Otherwise, the +% entire \verbbox would disappear at the corresponding end-group, before +% it is typeset. Meanwhile, we can't have nested verbatim commands +% (can we?), so the \global won't be overwriting itself. +\newbox\verbbox +\def\starttabbox{\global\setbox\verbbox=\hbox\bgroup} +% \begingroup \catcode`\^^I=\active \gdef\tabexpand{% \catcode`\^^I=\active \def^^I{\leavevmode\egroup - \dimen0=\wd0 % the width so far, or since the previous tab - \divide\dimen0 by\tabw - \multiply\dimen0 by\tabw % compute previous multiple of \tabw - \advance\dimen0 by\tabw % advance to next multiple of \tabw - \wd0=\dimen0 \box0 \starttabbox + \dimen\verbbox=\wd\verbbox % the width so far, or since the previous tab + \divide\dimen\verbbox by\tabw + \multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw + \advance\dimen\verbbox by\tabw % advance to next multiple of \tabw + \wd\verbbox=\dimen\verbbox \box\verbbox \starttabbox }% } \endgroup + +% start the verbatim environment. \def\setupverbatim{% + \let\nonarrowing = t% \nonfillstart - \advance\leftskip by -\defbodyindent - % Easiest (and conventionally used) font for verbatim - \tt - \def\par{\leavevmode\egroup\box0\endgraf}% - \catcode`\`=\active + \tt % easiest (and conventionally used) font for verbatim + % The \leavevmode here is for blank lines. Otherwise, we would + % never \starttabox and the \egroup would end verbatim mode. + \def\par{\leavevmode\egroup\box\verbbox\endgraf}% \tabexpand + \setupmarkupstyle{verbatim}% % Respect line breaks, % print special symbols as themselves, and - % make each space count - % must do in this order: + % make each space count. + % Must do in this order: \obeylines \uncatcodespecials \sepspaces \everypar{\starttabbox}% } @@ -5077,6 +6756,8 @@ width0pt\relax} \fi {% \makevalueexpandable \setupverbatim + \indexnofonts % Allow `@@' and other weird things in file names. + \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% \input #1 \afterenvbreak }% @@ -5102,27 +6783,35 @@ width0pt\relax} \fi \endgroup } + \message{defuns,} % @defun etc. \newskip\defbodyindent \defbodyindent=.4in \newskip\defargsindent \defargsindent=50pt \newskip\deflastargmargin \deflastargmargin=18pt +\newcount\defunpenalty % Start the processing of @deffn: \def\startdefun{% \ifnum\lastpenalty<10000 \medbreak + \defunpenalty=10003 % Will keep this @deffn together with the + % following @def command, see below. \else % If there are two @def commands in a row, we'll have a \nobreak, % which is there to keep the function description together with its % header. But if there's nothing but headers, we need to allow a % break somewhere. Check specifically for penalty 10002, inserted - % by \defargscommonending, instead of 10000, since the sectioning + % by \printdefunline, instead of 10000, since the sectioning % commands also insert a nobreak penalty, and we don't want to allow % a break between a section heading and a defun. - % - \ifnum\lastpenalty=10002 \penalty2000 \fi + % + % As a further refinement, we avoid "club" headers by signalling + % with penalty of 10003 after the very first @deffn in the + % sequence (see above), and penalty of 10002 after any following + % @def command. + \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi % % Similarly, after a section heading, do not allow a break. % But do insert the glue. @@ -5140,7 +6829,7 @@ width0pt\relax} \fi % % As above, allow line break if we have multiple x headers in a row. % It's not a great place, though. - \ifnum\lastpenalty=10002 \penalty3000 \fi + \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi % % And now, it's time to reuse the body of the original defun: \expandafter\gobbledefun#1% @@ -5155,10 +6844,10 @@ width0pt\relax} \fi #1#2 \endheader % common ending: \interlinepenalty = 10000 - \advance\rightskip by 0pt plus 1fil + \advance\rightskip by 0pt plus 1fil\relax \endgraf \nobreak\vskip -\parskip - \penalty 10002 % signal to \startdefun and \dodefunx + \penalty\defunpenalty % signal to \startdefun and \dodefunx % Some of the @defun-type tags do not enable magic parentheses, % rendering the following check redundant. But we don't optimize. \checkparencounts @@ -5168,7 +6857,7 @@ width0pt\relax} \fi \def\Edefun{\endgraf\medbreak} % \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; -% the only thing remainnig is to define \deffnheader. +% the only thing remaining is to define \deffnheader. % \def\makedefun#1{% \expandafter\let\csname E#1\endcsname = \Edefun @@ -5185,13 +6874,36 @@ width0pt\relax} \fi \def\domakedefun#1#2#3{% \envdef#1{% \startdefun + \doingtypefnfalse % distinguish typed functions from all else \parseargusing\activeparens{\printdefunline#3}% }% \def#2{\dodefunx#1}% \def#3% } -%%% Untyped functions: +\newif\ifdoingtypefn % doing typed function? +\newif\ifrettypeownline % typeset return type on its own line? + +% @deftypefnnewline on|off says whether the return type of typed functions +% are printed on their own line. This affects @deftypefn, @deftypefun, +% @deftypeop, and @deftypemethod. +% +\parseargdef\deftypefnnewline{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETtxideftypefnnl\endcsname + = \empty + \else\ifx\temp\offword + \expandafter\let\csname SETtxideftypefnnl\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @txideftypefnnl value `\temp', + must be on|off}% + \fi\fi +} + +% Untyped functions: % @deffn category name args \makedefun{deffn}{\deffngeneral{}} @@ -5210,7 +6922,7 @@ width0pt\relax} \fi \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } -%%% Typed functions: +% Typed functions: % @deftypefn category type name args \makedefun{deftypefn}{\deftypefngeneral{}} @@ -5225,10 +6937,11 @@ width0pt\relax} \fi % \def\deftypefngeneral#1#2 #3 #4 #5\endheader{% \dosubind{fn}{\code{#4}}{#1}% + \doingtypefntrue \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } -%%% Typed variables: +% Typed variables: % @deftypevr category type var args \makedefun{deftypevr}{\deftypecvgeneral{}} @@ -5246,7 +6959,7 @@ width0pt\relax} \fi \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } -%%% Untyped variables: +% Untyped variables: % @defvr category var args \makedefun{defvr}#1 {\deftypevrheader{#1} {} } @@ -5257,7 +6970,8 @@ width0pt\relax} \fi % \defcvof {category of}class var args \def\defcvof#1#2 {\deftypecvof{#1}#2 {} } -%%% Type: +% Types: + % @deftp category name args \makedefun{deftp}#1 #2 #3\endheader{% \doind{tp}{\code{#2}}% @@ -5285,25 +6999,49 @@ width0pt\relax} \fi % We are followed by (but not passed) the arguments, if any. % \def\defname#1#2#3{% + \par % Get the values of \leftskip and \rightskip as they were outside the @def... \advance\leftskip by -\defbodyindent % - % How we'll format the type name. Putting it in brackets helps + % Determine if we are typesetting the return type of a typed function + % on a line by itself. + \rettypeownlinefalse + \ifdoingtypefn % doing a typed function specifically? + % then check user option for putting return type on its own line: + \expandafter\ifx\csname SETtxideftypefnnl\endcsname\relax \else + \rettypeownlinetrue + \fi + \fi + % + % How we'll format the category name. Putting it in brackets helps % distinguish it from the body text that may end up on the next line % just below it. \def\temp{#1}% \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} % - % Figure out line sizes for the paragraph shape. + % Figure out line sizes for the paragraph shape. We'll always have at + % least two. + \tempnum = 2 + % % The first line needs space for \box0; but if \rightskip is nonzero, % we need only space for the part of \box0 which exceeds it: \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip + % + % If doing a return type on its own line, we'll have another line. + \ifrettypeownline + \advance\tempnum by 1 + \def\maybeshapeline{0in \hsize}% + \else + \def\maybeshapeline{}% + \fi + % % The continuations: \dimen2=\hsize \advance\dimen2 by -\defargsindent - % (plain.tex says that \dimen1 should be used only as global.) - \parshape 2 0in \dimen0 \defargsindent \dimen2 % - % Put the type name to the right margin. + % The final paragraph shape: + \parshape \tempnum 0in \dimen0 \maybeshapeline \defargsindent \dimen2 + % + % Put the category name at the right margin. \noindent \hbox to 0pt{% \hfil\box0 \kern-\hsize @@ -5325,8 +7063,16 @@ width0pt\relax} \fi % . this still does not fix the ?` and !` ligatures, but so far no % one has made identifiers using them :). \df \tt - \def\temp{#2}% return value type - \ifx\temp\empty\else \tclose{\temp} \fi + \def\temp{#2}% text of the return type + \ifx\temp\empty\else + \tclose{\temp}% typeset the return type + \ifrettypeownline + % put return type on its own line; prohibit line break following: + \hfil\vadjust{\nobreak}\break + \else + \space % type on same line, so just followed by a space + \fi + \fi % no return type #3% output function name }% {\rm\enskip}% hskip 0.5 em of \tenrm @@ -5346,8 +7092,11 @@ width0pt\relax} \fi \df \sl \hyphenchar\font=0 % % On the other hand, if an argument has two dashes (for instance), we - % want a way to get ttsl. Let's try @var for that. - \let\var=\ttslanted + % want a way to get ttsl. We used to recommend @var for that, so + % leave the code in, but it's strange for @var to lead to typewriter. + % Nowadays we recommend @code, since the difference between a ttsl hyphen + % and a tt hyphen is pretty tiny. @code also disables ?` !`. + \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}% #1% \sl\hyphenchar\font=45 } @@ -5427,12 +7176,14 @@ width0pt\relax} \fi \ifnum\parencount=0 \else \badparencount \fi \ifnum\brackcount=0 \else \badbrackcount \fi } +% these should not use \errmessage; the glibc manual, at least, actually +% has such constructs (when documenting function pointers). \def\badparencount{% - \errmessage{Unbalanced parentheses in @def}% + \message{Warning: unbalanced parentheses in @def...}% \global\parencount=0 } \def\badbrackcount{% - \errmessage{Unbalanced square braces in @def}% + \message{Warning: unbalanced square brackets in @def...}% \global\brackcount=0 } @@ -5442,7 +7193,7 @@ width0pt\relax} \fi % To do this right we need a feature of e-TeX, \scantokens, % which we arrange to emulate with a temporary file in ordinary TeX. -\ifx\eTeXversion\undefined +\ifx\eTeXversion\thisisundefined \newwrite\macscribble \def\scantokens#1{% \toks0={#1}% @@ -5453,26 +7204,30 @@ width0pt\relax} \fi } \fi -\def\scanmacro#1{% - \begingroup - \newlinechar`\^^M - \let\xeatspaces\eatspaces - % Undo catcode changes of \startcontents and \doprintindex - % When called from @insertcopying or (short)caption, we need active - % backslash to get it printed correctly. Previously, we had - % \catcode`\\=\other instead. We'll see whether a problem appears - % with macro expansion. --kasal, 19aug04 - \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ - % ... and \example - \spaceisspace - % - % Append \endinput to make sure that TeX does not see the ending newline. - % - % I've verified that it is necessary both for e-TeX and for ordinary TeX - % --kasal, 29nov03 - \scantokens{#1\endinput}% - \endgroup -} +\def\scanmacro#1{\begingroup + \newlinechar`\^^M + \let\xeatspaces\eatspaces + % + % Undo catcode changes of \startcontents and \doprintindex + % When called from @insertcopying or (short)caption, we need active + % backslash to get it printed correctly. Previously, we had + % \catcode`\\=\other instead. We'll see whether a problem appears + % with macro expansion. --kasal, 19aug04 + \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ + % + % ... and for \example: + \spaceisspace + % + % The \empty here causes a following catcode 5 newline to be eaten as + % part of reading whitespace after a control sequence. It does not + % eat a catcode 13 newline. There's no good way to handle the two + % cases (untried: maybe e-TeX's \everyeof could help, though plain TeX + % would then have different behavior). See the Macro Details node in + % the manual for the workaround we recommend for macros and + % line-oriented commands. + % + \scantokens{#1\empty}% +\endgroup} \def\scanexp#1{% \edef\temp{\noexpand\scanmacro{#1}}% @@ -5482,14 +7237,25 @@ width0pt\relax} \fi \newcount\paramno % Count of parameters \newtoks\macname % Macro name \newif\ifrecursive % Is it recursive? -\def\macrolist{} % List of all defined macros in the form - % \do\macro1\do\macro2... + +% List of all defined macros in the form +% \definedummyword\macro1\definedummyword\macro2... +% Currently is also contains all @aliases; the list can be split +% if there is a need. +\def\macrolist{} + +% Add the macro to \macrolist +\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} +\def\addtomacrolistxxx#1{% + \toks0 = \expandafter{\macrolist\definedummyword#1}% + \xdef\macrolist{\the\toks0}% +} % Utility routines. % This does \let #1 = #2, with \csnames; that is, % \let \csname#1\endcsname = \csname#2\endcsname % (except of course we have to play expansion games). -% +% \def\cslet#1#2{% \expandafter\let \csname#1\expandafter\endcsname @@ -5515,13 +7281,18 @@ width0pt\relax} \fi % Macro bodies are absorbed as an argument in a context where % all characters are catcode 10, 11 or 12, except \ which is active -% (as in normal texinfo). It is necessary to change the definition of \. - +% (as in normal texinfo). It is necessary to change the definition of \ +% to recognize macro arguments; this is the job of \mbodybackslash. +% +% Non-ASCII encodings make 8-bit characters active, so un-activate +% them to avoid their expansion. Must do this non-globally, to +% confine the change to the current group. +% % It's necessary to have hard CRs when the macro is executed. This is -% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. - -\def\scanctxt{% +% +\def\scanctxt{% used as subroutine \catcode`\"=\other \catcode`\+=\other \catcode`\<=\other @@ -5531,15 +7302,16 @@ width0pt\relax} \fi \catcode`\_=\other \catcode`\|=\other \catcode`\~=\other + \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi } -\def\scanargctxt{% +\def\scanargctxt{% used for copying and captions, not macros. \scanctxt \catcode`\\=\other \catcode`\^^M=\other } -\def\macrobodyctxt{% +\def\macrobodyctxt{% used for @macro definitions \scanctxt \catcode`\{=\other \catcode`\}=\other @@ -5547,32 +7319,56 @@ width0pt\relax} \fi \usembodybackslash } -\def\macroargctxt{% +\def\macroargctxt{% used when scanning invocations \scanctxt - \catcode`\\=\other + \catcode`\\=0 } +% why catcode 0 for \ in the above? To recognize \\ \{ \} as "escapes" +% for the single characters \ { }. Thus, we end up with the "commands" +% that would be written @\ @{ @} in a Texinfo document. +% +% We already have @{ and @}. For @\, we define it here, and only for +% this purpose, to produce a typewriter backslash (so, the @\ that we +% define for @math can't be used with @macro calls): +% +\def\\{\normalbackslash}% +% +% We would like to do this for \, too, since that is what makeinfo does. +% But it is not possible, because Texinfo already has a command @, for a +% cedilla accent. Documents must use @comma{} instead. +% +% \anythingelse will almost certainly be an error of some kind. + % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N % where N is the macro parameter number. % We define \csname macarg.\endcsname to be \realbackslash, so % \\ in macro replacement text gets you a backslash. - +% {\catcode`@=0 @catcode`@\=@active @gdef@usembodybackslash{@let\=@mbodybackslash} @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} } \expandafter\def\csname macarg.\endcsname{\realbackslash} +\def\margbackslash#1{\char`\#1 } + \def\macro{\recursivefalse\parsearg\macroxxx} \def\rmacro{\recursivetrue\parsearg\macroxxx} \def\macroxxx#1{% - \getargs{#1}% now \macname is the macname and \argl the arglist + \getargs{#1}% now \macname is the macname and \argl the arglist \ifx\argl\empty % no arguments - \paramno=0% + \paramno=0\relax \else \expandafter\parsemargdef \argl;% + \if\paramno>256\relax + \ifx\eTeXversion\thisisundefined + \errhelp = \EMsimple + \errmessage{You need eTeX to compile a file with macros with more than 256 arguments} + \fi + \fi \fi \if1\csname ismacro.\the\macname\endcsname \message{Warning: redefining \the\macname}% @@ -5581,10 +7377,7 @@ width0pt\relax} \fi \else \errmessage{Macro name \the\macname\space already defined}\fi \global\cslet{macsave.\the\macname}{\the\macname}% \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% - % Add the macroname to \macrolist - \toks0 = \expandafter{\macrolist\do}% - \xdef\macrolist{\the\toks0 - \expandafter\noexpand\csname\the\macname\endcsname}% + \addtomacrolist{\the\macname}% \fi \begingroup \macrobodyctxt \ifrecursive \expandafter\parsermacbody @@ -5598,7 +7391,7 @@ width0pt\relax} \fi % Remove the macro name from \macrolist: \begingroup \expandafter\let\csname#1\endcsname \relax - \let\do\unmacrodo + \let\definedummyword\unmacrodo \xdef\macrolist{\macrolist}% \endgroup \else @@ -5610,10 +7403,10 @@ width0pt\relax} \fi % macro definitions that have been changed to \relax. % \def\unmacrodo#1{% - \ifx#1\relax + \ifx #1\relax % remove this \else - \noexpand\do \noexpand #1% + \noexpand\definedummyword \noexpand#1% \fi } @@ -5622,46 +7415,269 @@ width0pt\relax} \fi % an opening brace, and that opening brace is not consumed. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} -\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacname#1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} -% Parse the optional {params} list. Set up \paramno and \paramlist -% so \defmacro knows what to do. Define \macarg.blah for each blah -% in the params list, to be ##N where N is the position in that list. -% That gets used by \mbodybackslash (above). +% For macro processing make @ a letter so that we can make Texinfo private macro names. +\edef\texiatcatcode{\the\catcode`\@} +\catcode `@=11\relax +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.BLAH for each BLAH +% in the params list to some hook where the argument si to be expanded. If +% there are less than 10 arguments that hook is to be replaced by ##N where N +% is the position in that list, that is to say the macro arguments are to be +% defined `a la TeX in the macro body. +% +% That gets used by \mbodybackslash (above). +% % We need to get `macro parameter char #' into several definitions. -% The technique used is stolen from LaTeX: let \hash be something +% The technique used is stolen from LaTeX: let \hash be something % unexpandable, insert that wherever you need a #, and then redefine % it to # just before using the token list produced. % % The same technique is used to protect \eatspaces till just before % the macro is used. - -\def\parsemargdef#1;{\paramno=0\def\paramlist{}% - \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +% +% If there are 10 or more arguments, a different technique is used, where the +% hook remains in the body, and when macro is to be expanded the body is +% processed again to replace the arguments. +% +% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the +% argument N value and then \edef the body (nothing else will expand because of +% the catcode regime underwhich the body was input). +% +% If you compile with TeX (not eTeX), and you have macros with 10 or more +% arguments, you need that no macro has more than 256 arguments, otherwise an +% error is produced. +\def\parsemargdef#1;{% + \paramno=0\def\paramlist{}% + \let\hash\relax + \let\xeatspaces\relax + \parsemargdefxxx#1,;,% + % In case that there are 10 or more arguments we parse again the arguments + % list to set new definitions for the \macarg.BLAH macros corresponding to + % each BLAH argument. It was anyhow needed to parse already once this list + % in order to count the arguments, and as macros with at most 9 arguments + % are by far more frequent than macro with 10 or more arguments, defining + % twice the \macarg.BLAH macros does not cost too much processing power. + \ifnum\paramno<10\relax\else + \paramno0\relax + \parsemmanyargdef@@#1,;,% 10 or more arguments + \fi +} \def\parsemargdefxxx#1,{% \if#1;\let\next=\relax \else \let\next=\parsemargdefxxx - \advance\paramno by 1% + \advance\paramno by 1 \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname {\xeatspaces{\hash\the\paramno}}% \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} +\def\parsemmanyargdef@@#1,{% + \if#1;\let\next=\relax + \else + \let\next=\parsemmanyargdef@@ + \edef\tempb{\eatspaces{#1}}% + \expandafter\def\expandafter\tempa + \expandafter{\csname macarg.\tempb\endcsname}% + % Note that we need some extra \noexpand\noexpand, this is because we + % don't want \the to be expanded in the \parsermacbody as it uses an + % \xdef . + \expandafter\edef\tempa + {\noexpand\noexpand\noexpand\the\toks\the\paramno}% + \advance\paramno by 1\relax + \fi\next} + % These two commands read recursive and nonrecursive macro bodies. % (They're different since rec and nonrec macros end differently.) +% +\catcode `\@\texiatcatcode \long\def\parsemacbody#1@end macro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% \long\def\parsermacbody#1@end rmacro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\catcode `\@=11\relax -% This defines the macro itself. There are six cases: recursive and -% nonrecursive macros of zero, one, and many arguments. +\let\endargs@\relax +\let\nil@\relax +\def\nilm@{\nil@}% +\long\def\nillm@{\nil@}% + +% This macro is expanded during the Texinfo macro expansion, not during its +% definition. It gets all the arguments values and assigns them to macros +% macarg.ARGNAME +% +% #1 is the macro name +% #2 is the list of argument names +% #3 is the list of argument values +\def\getargvals@#1#2#3{% + \def\macargdeflist@{}% + \def\saveparamlist@{#2}% Need to keep a copy for parameter expansion. + \def\paramlist{#2,\nil@}% + \def\macroname{#1}% + \begingroup + \macroargctxt + \def\argvaluelist{#3,\nil@}% + \def\@tempa{#3}% + \ifx\@tempa\empty + \setemptyargvalues@ + \else + \getargvals@@ + \fi +} + +% +\def\getargvals@@{% + \ifx\paramlist\nilm@ + % Some sanity check needed here that \argvaluelist is also empty. + \ifx\argvaluelist\nillm@ + \else + \errhelp = \EMsimple + \errmessage{Too many arguments in macro `\macroname'!}% + \fi + \let\next\macargexpandinbody@ + \else + \ifx\argvaluelist\nillm@ + % No more arguments values passed to macro. Set remaining named-arg + % macros to empty. + \let\next\setemptyargvalues@ + \else + % pop current arg name into \@tempb + \def\@tempa##1{\pop@{\@tempb}{\paramlist}##1\endargs@}% + \expandafter\@tempa\expandafter{\paramlist}% + % pop current argument value into \@tempc + \def\@tempa##1{\longpop@{\@tempc}{\argvaluelist}##1\endargs@}% + \expandafter\@tempa\expandafter{\argvaluelist}% + % Here \@tempb is the current arg name and \@tempc is the current arg value. + % First place the new argument macro definition into \@tempd + \expandafter\macname\expandafter{\@tempc}% + \expandafter\let\csname macarg.\@tempb\endcsname\relax + \expandafter\def\expandafter\@tempe\expandafter{% + \csname macarg.\@tempb\endcsname}% + \edef\@tempd{\long\def\@tempe{\the\macname}}% + \push@\@tempd\macargdeflist@ + \let\next\getargvals@@ + \fi + \fi + \next +} + +\def\push@#1#2{% + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter#2% + \expandafter\expandafter\expandafter{% + \expandafter#1#2}% +} + +% Replace arguments by their values in the macro body, and place the result +% in macro \@tempa +\def\macvalstoargs@{% + % To do this we use the property that token registers that are \the'ed + % within an \edef expand only once. So we are going to place all argument + % values into respective token registers. + % + % First we save the token context, and initialize argument numbering. + \begingroup + \paramno0\relax + % Then, for each argument number #N, we place the corresponding argument + % value into a new token list register \toks#N + \expandafter\putargsintokens@\saveparamlist@,;,% + % Then, we expand the body so that argument are replaced by their + % values. The trick for values not to be expanded themselves is that they + % are within tokens and that tokens expand only once in an \edef . + \edef\@tempc{\csname mac.\macroname .body\endcsname}% + % Now we restore the token stack pointer to free the token list registers + % which we have used, but we make sure that expanded body is saved after + % group. + \expandafter + \endgroup + \expandafter\def\expandafter\@tempa\expandafter{\@tempc}% + } + +\def\macargexpandinbody@{% + %% Define the named-macro outside of this group and then close this group. + \expandafter + \endgroup + \macargdeflist@ + % First the replace in body the macro arguments by their values, the result + % is in \@tempa . + \macvalstoargs@ + % Then we point at the \norecurse or \gobble (for recursive) macro value + % with \@tempb . + \expandafter\let\expandafter\@tempb\csname mac.\macroname .recurse\endcsname + % Depending on whether it is recursive or not, we need some tailing + % \egroup . + \ifx\@tempb\gobble + \let\@tempc\relax + \else + \let\@tempc\egroup + \fi + % And now we do the real job: + \edef\@tempd{\noexpand\@tempb{\macroname}\noexpand\scanmacro{\@tempa}\@tempc}% + \@tempd +} + +\def\putargsintokens@#1,{% + \if#1;\let\next\relax + \else + \let\next\putargsintokens@ + % First we allocate the new token list register, and give it a temporary + % alias \@tempb . + \toksdef\@tempb\the\paramno + % Then we place the argument value into that token list register. + \expandafter\let\expandafter\@tempa\csname macarg.#1\endcsname + \expandafter\@tempb\expandafter{\@tempa}% + \advance\paramno by 1\relax + \fi + \next +} + +% Save the token stack pointer into macro #1 +\def\texisavetoksstackpoint#1{\edef#1{\the\@cclvi}} +% Restore the token stack pointer from number in macro #1 +\def\texirestoretoksstackpoint#1{\expandafter\mathchardef\expandafter\@cclvi#1\relax} +% newtoks that can be used non \outer . +\def\texinonouternewtoks{\alloc@ 5\toks \toksdef \@cclvi} + +% Tailing missing arguments are set to empty +\def\setemptyargvalues@{% + \ifx\paramlist\nilm@ + \let\next\macargexpandinbody@ + \else + \expandafter\setemptyargvaluesparser@\paramlist\endargs@ + \let\next\setemptyargvalues@ + \fi + \next +} + +\def\setemptyargvaluesparser@#1,#2\endargs@{% + \expandafter\def\expandafter\@tempa\expandafter{% + \expandafter\def\csname macarg.#1\endcsname{}}% + \push@\@tempa\macargdeflist@ + \def\paramlist{#2}% +} + +% #1 is the element target macro +% #2 is the list macro +% #3,#4\endargs@ is the list value +\def\pop@#1#2#3,#4\endargs@{% + \def#1{#3}% + \def#2{#4}% +} +\long\def\longpop@#1#2#3,#4\endargs@{% + \long\def#1{#3}% + \long\def#2{#4}% +} + +% This defines a Texinfo @macro. There are eight cases: recursive and +% nonrecursive macros of zero, one, up to nine, and many arguments. % Much magic with \expandafter here. % \xdef is used so that macro definitions will survive the file % they're defined in; @include reads the file inside a group. +% \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars \ifrecursive @@ -5676,17 +7692,25 @@ width0pt\relax} \fi \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup\noexpand\scanmacro{\temp}}% - \else % many - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \else + \ifnum\paramno<10\relax % at most 9 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \else % 10 or more + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\getargvals@{\the\macname}{\argl}% + }% + \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp + \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble + \fi \fi \else \ifcase\paramno @@ -5703,63 +7727,57 @@ width0pt\relax} \fi \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% - \else % many - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \expandafter\noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% + \else % at most 9 + \ifnum\paramno<10\relax + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % 10 or more: + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\getargvals@{\the\macname}{\argl}% + }% + \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp + \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\norecurse + \fi \fi \fi} +\catcode `\@\texiatcatcode\relax + \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} % \braceorline decides whether the next nonwhitespace character is a % {. If so it reads up to the closing }, if not, it reads the whole % line. Whatever was read is then fed to the next control sequence -% as an argument (by \parsebrace or \parsearg) -\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} +% as an argument (by \parsebrace or \parsearg). +% +\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% \ifx\nchar\bgroup\else \expandafter\parsearg - \fi \next} - -% We want to disable all macros during \shipout so that they are not -% expanded by \write. -\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% - \edef\next{\macrolist}\expandafter\endgroup\next} - -% For \indexnofonts, we need to get rid of all macros, leaving only the -% arguments (if present). Of course this is not nearly correct, but it -% is the best we can do for now. makeinfo does not expand macros in the -% argument to @deffn, which ends up writing an index entry, and texindex -% isn't prepared for an index sort entry that starts with \. -% -% Since macro invocations are followed by braces, we can just redefine them -% to take a single TeX argument. The case of a macro invocation that -% goes to end-of-line is not handled. -% -\def\emptyusermacros{\begingroup - \def\do##1{\let\noexpand##1=\noexpand\asis}% - \edef\next{\macrolist}\expandafter\endgroup\next} + \fi \macnamexxx} % @alias. % We need some trickery to remove the optional spaces around the equal -% sign. Just make them active and then expand them all to nothing. +% sign. Make them active and then expand them all to nothing. +% \def\alias{\parseargusing\obeyspaces\aliasxxx} \def\aliasxxx #1{\aliasyyy#1\relax} \def\aliasyyy #1=#2\relax{% {% \expandafter\let\obeyedspace=\empty + \addtomacrolist{#1}% \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% }% \next @@ -5769,13 +7787,13 @@ width0pt\relax} \fi \message{cross references,} \newwrite\auxfile - \newif\ifhavexrefs % True if xref values are known. \newif\ifwarnedxrefs % True if we warned once that they aren't known. % @inforef is relatively simple. \def\inforef #1{\inforefzzz #1,,,,**} -\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, +\def\inforefzzz #1,#2,#3,#4**{% + \putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, node \samp{\ignorespaces#1{}}} % @node's only job in TeX is to define \lastnode, which is used in @@ -5814,7 +7832,7 @@ width0pt\relax} \fi % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an % anchor), which consists of three parts: -% 1) NAME-title - the current sectioning name taken from \thissection, +% 1) NAME-title - the current sectioning name taken from \lastsection, % or the anchor name. % 2) NAME-snt - section number and type, passed as the SNT arg, or % empty for anchors. @@ -5829,20 +7847,39 @@ width0pt\relax} \fi \iflinks {% \atdummies % preserve commands, but don't expand them - \turnoffactive - \otherbackslash \edef\writexrdef##1##2{% \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% - \toks0 = \expandafter{\thissection}% + \toks0 = \expandafter{\lastsection}% \immediate \writexrdef{title}{\the\toks0 }% \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. - \writexrdef{pg}{\folio}% will be written later, during \shipout + \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout }% \fi } +% @xrefautosectiontitle on|off says whether @section(ing) names are used +% automatically in xrefs, if the third arg is not explicitly specified. +% This was provided as a "secret" @set xref-automatic-section-title +% variable, now it's official. +% +\parseargdef\xrefautomaticsectiontitle{% + \def\temp{#1}% + \ifx\temp\onword + \expandafter\let\csname SETxref-automatic-section-title\endcsname + = \empty + \else\ifx\temp\offword + \expandafter\let\csname SETxref-automatic-section-title\endcsname + = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @xrefautomaticsectiontitle value `\temp', + must be on|off}% + \fi\fi +} + +% % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed @@ -5851,26 +7888,41 @@ width0pt\relax} \fi \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} \def\ref#1{\xrefX[#1,,,,,,,]} +% +\newbox\toprefbox +\newbox\printedrefnamebox +\newbox\infofilenamebox +\newbox\printedmanualbox +% \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup \unsepspaces - \def\printedmanual{\ignorespaces #5}% + % + % Get args without leading/trailing spaces. \def\printedrefname{\ignorespaces #3}% - \setbox1=\hbox{\printedmanual\unskip}% - \setbox0=\hbox{\printedrefname\unskip}% - \ifdim \wd0 = 0pt + \setbox\printedrefnamebox = \hbox{\printedrefname\unskip}% + % + \def\infofilename{\ignorespaces #4}% + \setbox\infofilenamebox = \hbox{\infofilename\unskip}% + % + \def\printedmanual{\ignorespaces #5}% + \setbox\printedmanualbox = \hbox{\printedmanual\unskip}% + % + % If the printed reference name (arg #3) was not explicitly given in + % the @xref, figure out what we want to use. + \ifdim \wd\printedrefnamebox = 0pt % No printed node name was explicitly given. - \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax - % Use the node name inside the square brackets. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname \relax + % Not auto section-title: use node name inside the square brackets. \def\printedrefname{\ignorespaces #1}% \else - % Use the actual chapter/section title appear inside - % the square brackets. Use the real section title if we have it. - \ifdim \wd1 > 0pt - % It is in another manual, so we don't have it. + % Auto section-title: use chapter/section title inside + % the square brackets if we have it. + \ifdim \wd\printedmanualbox > 0pt + % It is in another manual, so we don't have it; use node name. \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs - % We know the real title if we have the xref values. + % We (should) know the real title if we have the xref values. \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. @@ -5882,18 +7934,32 @@ width0pt\relax} \fi % % Make link in pdf output. \ifpdf - \leavevmode - \getfilename{#4}% - {\turnoffactive \otherbackslash - \ifnum\filenamelength>0 - \startlink attr{/Border [0 0 0]}% - goto file{\the\filename.pdf} name{#1}% + {\indexnofonts + \turnoffactive + \makevalueexpandable + % This expands tokens, so do it after making catcode changes, so _ + % etc. don't get their TeX definitions. This ignores all spaces in + % #4, including (wrongly) those in the middle of the filename. + \getfilename{#4}% + % + % This (wrongly) does not take account of leading or trailing + % spaces in #1, which should be ignored. + \edef\pdfxrefdest{#1}% + \ifx\pdfxrefdest\empty + \def\pdfxrefdest{Top}% no empty targets \else - \startlink attr{/Border [0 0 0]}% - goto name{\pdfmkpgn{#1}}% + \txiescapepdf\pdfxrefdest % escape PDF special chars + \fi + % + \leavevmode + \startlink attr{/Border [0 0 0]}% + \ifnum\filenamelength>0 + goto file{\the\filename.pdf} name{\pdfxrefdest}% + \else + goto name{\pdfmkpgn{\pdfxrefdest}}% \fi }% - \linkcolor + \setcolor{\linkcolor}% \fi % % Float references are printed completely differently: "Figure 1.2" @@ -5904,60 +7970,98 @@ width0pt\relax} \fi % include an _ in the xref name, etc. \indexnofonts \turnoffactive - \otherbackslash \expandafter\global\expandafter\let\expandafter\Xthisreftitle \csname XR#1-title\endcsname }% \iffloat\Xthisreftitle % If the user specified the print name (third arg) to the ref, % print it instead of our usual "Figure 1.2". - \ifdim\wd0 = 0pt - \refx{#1-snt}% + \ifdim\wd\printedrefnamebox = 0pt + \refx{#1-snt}{}% \else \printedrefname \fi % - % if the user also gave the printed manual name (fifth arg), append + % If the user also gave the printed manual name (fifth arg), append % "in MANUALNAME". - \ifdim \wd1 > 0pt + \ifdim \wd\printedmanualbox > 0pt \space \putwordin{} \cite{\printedmanual}% \fi \else % node/anchor (non-float) references. + % + % If we use \unhbox to print the node names, TeX does not insert + % empty discretionaries after hyphens, which means that it will not + % find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, + % this is a loss. Therefore, we give the text of the node name + % again, so it is as if TeX is seeing it for the first time. + % + \ifdim \wd\printedmanualbox > 0pt + % Cross-manual reference with a printed manual name. + % + \crossmanualxref{\cite{\printedmanual\unskip}}% + % + \else\ifdim \wd\infofilenamebox > 0pt + % Cross-manual reference with only an info filename (arg 4), no + % printed manual name (arg 5). This is essentially the same as + % the case above; we output the filename, since we have nothing else. + % + \crossmanualxref{\code{\infofilename\unskip}}% % - % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not - % insert empty discretionaries after hyphens, which means that it will - % not find a line break at a hyphen in a node names. Since some manuals - % are best written with fairly long node names, containing hyphens, this - % is a loss. Therefore, we give the text of the node name again, so it - % is as if TeX is seeing it for the first time. - \ifdim \wd1 > 0pt - \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% \else + % Reference within this manual. + % % _ (for example) has to be the character _ for the purposes of the % control sequence corresponding to the node, but it has to expand % into the usual \leavevmode...\vrule stuff for purposes of % printing. So we \turnoffactive for the \refx-snt, back on for the % printing, back off for the \refx-pg. - {\turnoffactive \otherbackslash + {\turnoffactive % Only output a following space if the -snt ref is nonempty; for % @unnumbered and @anchor, it won't be. \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi }% - % output the `[mynode]' via a macro so it can be overridden. + % output the `[mynode]' via the macro below so it can be overridden. \xrefprintnodename\printedrefname % % But we always want a comma and a space: ,\space % % output the `page 3'. - \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% - \fi + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi\fi \fi \endlink \endgroup} +% Output a cross-manual xref to #1. Used just above (twice). +% +% Only include the text "Section ``foo'' in" if the foo is neither +% missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply +% "see The Foo Manual", the idea being to refer to the whole manual. +% +% But, this being TeX, we can't easily compare our node name against the +% string "Top" while ignoring the possible spaces before and after in +% the input. By adding the arbitrary 7sp below, we make it much less +% likely that a real node name would have the same width as "Top" (e.g., +% in a monospaced font). Hopefully it will never happen in practice. +% +% For the same basic reason, we retypeset the "Top" at every +% reference, since the current font is indeterminate. +% +\def\crossmanualxref#1{% + \setbox\toprefbox = \hbox{Top\kern7sp}% + \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% + \ifdim \wd2 > 7sp % nonempty? + \ifdim \wd2 = \wd\toprefbox \else % same as Top? + \putwordSection{} ``\printedrefname'' \putwordin{}\space + \fi + \fi + #1% +} + % This macro is called from \xrefX for the `[nodename]' part of xref % output. It's a separate macro only so it can be changed more easily, % since square brackets don't work well in some documents. Particularly @@ -6008,7 +8112,8 @@ width0pt\relax} \fi \angleleft un\-de\-fined\angleright \iflinks \ifhavexrefs - \message{\linenumber Undefined cross reference `#1'.}% + {\toks0 = {#1}% avoid expansion of possibly-complex value + \message{\linenumber Undefined cross reference `\the\toks0'.}}% \else \ifwarnedxrefs\else \global\warnedxrefstrue @@ -6028,10 +8133,18 @@ width0pt\relax} \fi % collisions). But if this is a float type, we have more work to do. % \def\xrdef#1#2{% - \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value. + {% The node name might contain 8-bit characters, which in our current + % implementation are changed to commands like @'e. Don't let these + % mess up the control sequence name. + \indexnofonts + \turnoffactive + \xdef\safexrefname{#1}% + }% + % + \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref % % Was that xref control sequence that we just defined for a float? - \expandafter\iffloat\csname XR#1\endcsname + \expandafter\iffloat\csname XR\safexrefname\endcsname % it was a float, and we have the (safe) float type in \iffloattype. \expandafter\let\expandafter\floatlist \csname floatlist\iffloattype\endcsname @@ -6046,7 +8159,8 @@ width0pt\relax} \fi % % Remember this xref in the control sequence \floatlistFLOATTYPE, % for later use in \listoffloats. - \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}% + \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 + {\safexrefname}}% \fi } @@ -6055,13 +8169,13 @@ width0pt\relax} \fi \def\tryauxfile{% \openin 1 \jobname.aux \ifeof 1 \else - \readauxfile + \readdatafile{aux}% \global\havexrefstrue \fi \closein 1 } -\def\readauxfile{\begingroup +\def\setupdatafile{% \catcode`\^^@=\other \catcode`\^^A=\other \catcode`\^^B=\other @@ -6130,11 +8244,11 @@ width0pt\relax} \fi % % Make the characters 128-255 be printing characters. {% - \count 1=128 + \count1=128 \def\loop{% - \catcode\count 1=\other - \advance\count 1 by 1 - \ifnum \count 1<256 \loop \fi + \catcode\count1=\other + \advance\count1 by 1 + \ifnum \count1<256 \loop \fi }% }% % @@ -6142,8 +8256,12 @@ width0pt\relax} \fi \catcode`\{=1 \catcode`\}=2 \catcode`\@=0 - % - \input \jobname.aux +} + +\def\readdatafile#1{% +\begingroup + \setupdatafile + \input\jobname.#1 \endgroup} @@ -6159,7 +8277,7 @@ width0pt\relax} \fi % space to prevent strange expansion errors.) \def\supereject{\par\penalty -20000\footnoteno =0 } -% @footnotestyle is meaningful for info output only. +% @footnotestyle is meaningful for Info output only. \let\footnotestyle=\comment {\catcode `\@=11 @@ -6222,6 +8340,8 @@ width0pt\relax} \fi % expands into a box, it must come within the paragraph, lest it % provide a place where TeX can split the footnote. \footstrut + % + % Invoke rest of plain TeX footnote routine. \futurelet\next\fo@t } }%end \catcode `\@=11 @@ -6229,7 +8349,7 @@ width0pt\relax} \fi % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. -% Similarily, if a @footnote appears inside an alignment, save the footnote +% Similarly, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. @@ -6309,7 +8429,7 @@ width0pt\relax} \fi it from ftp://tug.org/tex/epsf.tex.} % \def\image#1{% - \ifx\epsfbox\undefined + \ifx\epsfbox\thisisundefined \ifwarnednoepsf \else \errhelp = \noepsfhelp \errmessage{epsf.tex not found, images will be ignored}% @@ -6325,7 +8445,7 @@ width0pt\relax} \fi % #2 is (optional) width, #3 is (optional) height. % #4 is (ignored optional) html alt text. % #5 is (ignored optional) extension. -% #6 is just the usual extra ignored arg for parsing this stuff. +% #6 is just the usual extra ignored arg for parsing stuff. \newif\ifimagevmode \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup \catcode`\^^M = 5 % in case we're inside an example @@ -6333,15 +8453,30 @@ width0pt\relax} \fi % If the image is by itself, center it. \ifvmode \imagevmodetrue - \nobreak\bigskip + \else \ifx\centersub\centerV + % for @center @image, we need a vbox so we can have our vertical space + \imagevmodetrue + \vbox\bgroup % vbox has better behavior than vtop herev + \fi\fi + % + \ifimagevmode + \nobreak\medskip % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. \nobreak\vskip\parskip \nobreak - \line\bgroup\hss \fi % + % Leave vertical mode so that indentation from an enclosing + % environment such as @quotation is respected. + % However, if we're at the top level, we don't want the + % normal paragraph indentation. + % On the other hand, if we are in the case of @center @image, we don't + % want to start a paragraph, which will create a hsize-width box and + % eradicate the centering. + \ifx\centersub\centerV\else \noindent \fi + % % Output the image. \ifpdf \dopdfimage{#1}{#2}{#3}% @@ -6352,7 +8487,10 @@ width0pt\relax} \fi \epsfbox{#1.eps}% \fi % - \ifimagevmode \hss \egroup \bigbreak \fi % space after the image + \ifimagevmode + \medskip % space after a standalone image + \fi + \ifx\centersub\centerV \egroup \fi \endgroup} @@ -6419,13 +8557,13 @@ width0pt\relax} \fi \global\advance\floatno by 1 % {% - % This magic value for \thissection is output by \setref as the + % This magic value for \lastsection is output by \setref as the % XREFLABEL-title value. \xrefX uses it to distinguish float % labels (which have a completely different output format) from % node and anchor labels. And \xrdef uses it to construct the % lists of floats. % - \edef\thissection{\floatmagic=\safefloattype}% + \edef\lastsection{\floatmagic=\safefloattype}% \setref{\floatlabel}{Yfloat}% }% \fi @@ -6492,7 +8630,8 @@ width0pt\relax} \fi % \floatlabel-lof. Besides \floatident, we include the short % caption if specified, else the full caption if specified, else nothing. {% - \atdummies \turnoffactive \otherbackslash + \atdummies + % % since we read the caption text in the macro world, where ^^M % is turned into a normal character, we have to scan it back, so % we don't write the literal three characters "^^M" into the aux file. @@ -6513,8 +8652,9 @@ width0pt\relax} \fi % % place the captured inserts % - % BEWARE: when the floats start float, we have to issue warning whenever an - % insert appears inside a float which could possibly float. --kasal, 26may04 + % BEWARE: when the floats start floating, we have to issue warning + % whenever an insert appears inside a float which could possibly + % float. --kasal, 26may04 % \checkinserts } @@ -6558,7 +8698,7 @@ width0pt\relax} \fi % #1 is the control sequence we are passed; we expand into a conditional % which is true if #1 represents a float ref. That is, the magic -% \thissection value which we \setref above. +% \lastsection value which we \setref above. % \def\iffloat#1{\expandafter\doiffloat#1==\finish} % @@ -6619,39 +8759,909 @@ width0pt\relax} \fi \writeentry }} -\message{localization,} -% and i18n. -% @documentlanguage is usually given very early, just after -% @setfilename. If done too late, it may not override everything -% properly. Single argument is the language abbreviation. -% It would be nice if we could set up a hyphenation file here. +\message{localization,} + +% For single-language documents, @documentlanguage is usually given very +% early, just after @documentencoding. Single argument is the language +% (de) or locale (de_DE) abbreviation. % -\parseargdef\documentlanguage{% +{ + \catcode`\_ = \active + \globaldefs=1 +\parseargdef\documentlanguage{\begingroup + \let_=\normalunderscore % normal _ character for filenames \tex % read txi-??.tex file in plain TeX. - % Read the file if it exists. + % Read the file by the name they passed if it exists. \openin 1 txi-#1.tex \ifeof 1 - \errhelp = \nolanghelp - \errmessage{Cannot read language file txi-#1.tex}% + \documentlanguagetrywithoutunderscore{#1_\finish}% \else + \globaldefs = 1 % everything in the txi-LL files needs to persist \input txi-#1.tex \fi \closein 1 - \endgroup -} -\newhelp\nolanghelp{The given language definition file cannot be found or -is empty. Maybe you need to install it? In the current directory -should work if nowhere else does.} - - -% @documentencoding should change something in TeX eventually, most -% likely, but for now just recognize it. -\let\documentencoding = \comment - - -% Page size parameters. + \endgroup % end raw TeX +\endgroup} % +% If they passed de_DE, and txi-de_DE.tex doesn't exist, +% try txi-de.tex. +% +\gdef\documentlanguagetrywithoutunderscore#1_#2\finish{% + \openin 1 txi-#1.tex + \ifeof 1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \else + \globaldefs = 1 % everything in the txi-LL files needs to persist + \input txi-#1.tex + \fi + \closein 1 +} +}% end of special _ catcode +% +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? Putting it in the current +directory should work if nowhere else does.} + +% This macro is called from txi-??.tex files; the first argument is the +% \language name to set (without the "\lang@" prefix), the second and +% third args are \{left,right}hyphenmin. +% +% The language names to pass are determined when the format is built. +% See the etex.log file created at that time, e.g., +% /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log. +% +% With TeX Live 2008, etex now includes hyphenation patterns for all +% available languages. This means we can support hyphenation in +% Texinfo, at least to some extent. (This still doesn't solve the +% accented characters problem.) +% +\catcode`@=11 +\def\txisetlanguage#1#2#3{% + % do not set the language if the name is undefined in the current TeX. + \expandafter\ifx\csname lang@#1\endcsname \relax + \message{no patterns for #1}% + \else + \global\language = \csname lang@#1\endcsname + \fi + % but there is no harm in adjusting the hyphenmin values regardless. + \global\lefthyphenmin = #2\relax + \global\righthyphenmin = #3\relax +} + +% Helpers for encodings. +% Set the catcode of characters 128 through 255 to the specified number. +% +\def\setnonasciicharscatcode#1{% + \count255=128 + \loop\ifnum\count255<256 + \global\catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +\def\setnonasciicharscatcodenonglobal#1{% + \count255=128 + \loop\ifnum\count255<256 + \catcode\count255=#1\relax + \advance\count255 by 1 + \repeat +} + +% @documentencoding sets the definition of non-ASCII characters +% according to the specified encoding. +% +\parseargdef\documentencoding{% + % Encoding being declared for the document. + \def\declaredencoding{\csname #1.enc\endcsname}% + % + % Supported encodings: names converted to tokens in order to be able + % to compare them with \ifx. + \def\ascii{\csname US-ASCII.enc\endcsname}% + \def\latnine{\csname ISO-8859-15.enc\endcsname}% + \def\latone{\csname ISO-8859-1.enc\endcsname}% + \def\lattwo{\csname ISO-8859-2.enc\endcsname}% + \def\utfeight{\csname UTF-8.enc\endcsname}% + % + \ifx \declaredencoding \ascii + \asciichardefs + % + \else \ifx \declaredencoding \lattwo + \setnonasciicharscatcode\active + \lattwochardefs + % + \else \ifx \declaredencoding \latone + \setnonasciicharscatcode\active + \latonechardefs + % + \else \ifx \declaredencoding \latnine + \setnonasciicharscatcode\active + \latninechardefs + % + \else \ifx \declaredencoding \utfeight + \setnonasciicharscatcode\active + \utfeightchardefs + % + \else + \message{Unknown document encoding #1, ignoring.}% + % + \fi % utfeight + \fi % latnine + \fi % latone + \fi % lattwo + \fi % ascii +} + +% A message to be logged when using a character that isn't available +% the default font encoding (OT1). +% +\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} + +% Take account of \c (plain) vs. \, (Texinfo) difference. +\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} + +% First, make active non-ASCII characters in order for them to be +% correctly categorized when TeX reads the replacement text of +% macros containing the character definitions. +\setnonasciicharscatcode\active +% +% Latin1 (ISO-8859-1) character definitions. +\def\latonechardefs{% + \gdef^^a0{\tie} + \gdef^^a1{\exclamdown} + \gdef^^a2{\missingcharmsg{CENT SIGN}} + \gdef^^a3{{\pounds}} + \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdef^^a5{\missingcharmsg{YEN SIGN}} + \gdef^^a6{\missingcharmsg{BROKEN BAR}} + \gdef^^a7{\S} + \gdef^^a8{\"{}} + \gdef^^a9{\copyright} + \gdef^^aa{\ordf} + \gdef^^ab{\guillemetleft} + \gdef^^ac{$\lnot$} + \gdef^^ad{\-} + \gdef^^ae{\registeredsymbol} + \gdef^^af{\={}} + % + \gdef^^b0{\textdegree} + \gdef^^b1{$\pm$} + \gdef^^b2{$^2$} + \gdef^^b3{$^3$} + \gdef^^b4{\'{}} + \gdef^^b5{$\mu$} + \gdef^^b6{\P} + % + \gdef^^b7{$^.$} + \gdef^^b8{\cedilla\ } + \gdef^^b9{$^1$} + \gdef^^ba{\ordm} + % + \gdef^^bb{\guillemetright} + \gdef^^bc{$1\over4$} + \gdef^^bd{$1\over2$} + \gdef^^be{$3\over4$} + \gdef^^bf{\questiondown} + % + \gdef^^c0{\`A} + \gdef^^c1{\'A} + \gdef^^c2{\^A} + \gdef^^c3{\~A} + \gdef^^c4{\"A} + \gdef^^c5{\ringaccent A} + \gdef^^c6{\AE} + \gdef^^c7{\cedilla C} + \gdef^^c8{\`E} + \gdef^^c9{\'E} + \gdef^^ca{\^E} + \gdef^^cb{\"E} + \gdef^^cc{\`I} + \gdef^^cd{\'I} + \gdef^^ce{\^I} + \gdef^^cf{\"I} + % + \gdef^^d0{\DH} + \gdef^^d1{\~N} + \gdef^^d2{\`O} + \gdef^^d3{\'O} + \gdef^^d4{\^O} + \gdef^^d5{\~O} + \gdef^^d6{\"O} + \gdef^^d7{$\times$} + \gdef^^d8{\O} + \gdef^^d9{\`U} + \gdef^^da{\'U} + \gdef^^db{\^U} + \gdef^^dc{\"U} + \gdef^^dd{\'Y} + \gdef^^de{\TH} + \gdef^^df{\ss} + % + \gdef^^e0{\`a} + \gdef^^e1{\'a} + \gdef^^e2{\^a} + \gdef^^e3{\~a} + \gdef^^e4{\"a} + \gdef^^e5{\ringaccent a} + \gdef^^e6{\ae} + \gdef^^e7{\cedilla c} + \gdef^^e8{\`e} + \gdef^^e9{\'e} + \gdef^^ea{\^e} + \gdef^^eb{\"e} + \gdef^^ec{\`{\dotless i}} + \gdef^^ed{\'{\dotless i}} + \gdef^^ee{\^{\dotless i}} + \gdef^^ef{\"{\dotless i}} + % + \gdef^^f0{\dh} + \gdef^^f1{\~n} + \gdef^^f2{\`o} + \gdef^^f3{\'o} + \gdef^^f4{\^o} + \gdef^^f5{\~o} + \gdef^^f6{\"o} + \gdef^^f7{$\div$} + \gdef^^f8{\o} + \gdef^^f9{\`u} + \gdef^^fa{\'u} + \gdef^^fb{\^u} + \gdef^^fc{\"u} + \gdef^^fd{\'y} + \gdef^^fe{\th} + \gdef^^ff{\"y} +} + +% Latin9 (ISO-8859-15) encoding character definitions. +\def\latninechardefs{% + % Encoding is almost identical to Latin1. + \latonechardefs + % + \gdef^^a4{\euro} + \gdef^^a6{\v S} + \gdef^^a8{\v s} + \gdef^^b4{\v Z} + \gdef^^b8{\v z} + \gdef^^bc{\OE} + \gdef^^bd{\oe} + \gdef^^be{\"Y} +} + +% Latin2 (ISO-8859-2) character definitions. +\def\lattwochardefs{% + \gdef^^a0{\tie} + \gdef^^a1{\ogonek{A}} + \gdef^^a2{\u{}} + \gdef^^a3{\L} + \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdef^^a5{\v L} + \gdef^^a6{\'S} + \gdef^^a7{\S} + \gdef^^a8{\"{}} + \gdef^^a9{\v S} + \gdef^^aa{\cedilla S} + \gdef^^ab{\v T} + \gdef^^ac{\'Z} + \gdef^^ad{\-} + \gdef^^ae{\v Z} + \gdef^^af{\dotaccent Z} + % + \gdef^^b0{\textdegree} + \gdef^^b1{\ogonek{a}} + \gdef^^b2{\ogonek{ }} + \gdef^^b3{\l} + \gdef^^b4{\'{}} + \gdef^^b5{\v l} + \gdef^^b6{\'s} + \gdef^^b7{\v{}} + \gdef^^b8{\cedilla\ } + \gdef^^b9{\v s} + \gdef^^ba{\cedilla s} + \gdef^^bb{\v t} + \gdef^^bc{\'z} + \gdef^^bd{\H{}} + \gdef^^be{\v z} + \gdef^^bf{\dotaccent z} + % + \gdef^^c0{\'R} + \gdef^^c1{\'A} + \gdef^^c2{\^A} + \gdef^^c3{\u A} + \gdef^^c4{\"A} + \gdef^^c5{\'L} + \gdef^^c6{\'C} + \gdef^^c7{\cedilla C} + \gdef^^c8{\v C} + \gdef^^c9{\'E} + \gdef^^ca{\ogonek{E}} + \gdef^^cb{\"E} + \gdef^^cc{\v E} + \gdef^^cd{\'I} + \gdef^^ce{\^I} + \gdef^^cf{\v D} + % + \gdef^^d0{\DH} + \gdef^^d1{\'N} + \gdef^^d2{\v N} + \gdef^^d3{\'O} + \gdef^^d4{\^O} + \gdef^^d5{\H O} + \gdef^^d6{\"O} + \gdef^^d7{$\times$} + \gdef^^d8{\v R} + \gdef^^d9{\ringaccent U} + \gdef^^da{\'U} + \gdef^^db{\H U} + \gdef^^dc{\"U} + \gdef^^dd{\'Y} + \gdef^^de{\cedilla T} + \gdef^^df{\ss} + % + \gdef^^e0{\'r} + \gdef^^e1{\'a} + \gdef^^e2{\^a} + \gdef^^e3{\u a} + \gdef^^e4{\"a} + \gdef^^e5{\'l} + \gdef^^e6{\'c} + \gdef^^e7{\cedilla c} + \gdef^^e8{\v c} + \gdef^^e9{\'e} + \gdef^^ea{\ogonek{e}} + \gdef^^eb{\"e} + \gdef^^ec{\v e} + \gdef^^ed{\'{\dotless{i}}} + \gdef^^ee{\^{\dotless{i}}} + \gdef^^ef{\v d} + % + \gdef^^f0{\dh} + \gdef^^f1{\'n} + \gdef^^f2{\v n} + \gdef^^f3{\'o} + \gdef^^f4{\^o} + \gdef^^f5{\H o} + \gdef^^f6{\"o} + \gdef^^f7{$\div$} + \gdef^^f8{\v r} + \gdef^^f9{\ringaccent u} + \gdef^^fa{\'u} + \gdef^^fb{\H u} + \gdef^^fc{\"u} + \gdef^^fd{\'y} + \gdef^^fe{\cedilla t} + \gdef^^ff{\dotaccent{}} +} + +% UTF-8 character definitions. +% +% This code to support UTF-8 is based on LaTeX's utf8.def, with some +% changes for Texinfo conventions. It is included here under the GPL by +% permission from Frank Mittelbach and the LaTeX team. +% +\newcount\countUTFx +\newcount\countUTFy +\newcount\countUTFz + +\gdef\UTFviiiTwoOctets#1#2{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\endcsname} +% +\gdef\UTFviiiThreeOctets#1#2#3{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} +% +\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter + \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} + +\gdef\UTFviiiDefined#1{% + \ifx #1\relax + \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \else + \expandafter #1% + \fi +} + +\begingroup + \catcode`\~13 + \catcode`\"12 + + \def\UTFviiiLoop{% + \global\catcode\countUTFx\active + \uccode`\~\countUTFx + \uppercase\expandafter{\UTFviiiTmp}% + \advance\countUTFx by 1 + \ifnum\countUTFx < \countUTFy + \expandafter\UTFviiiLoop + \fi} + + \countUTFx = "C2 + \countUTFy = "E0 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiTwoOctets\string~}} + \UTFviiiLoop + + \countUTFx = "E0 + \countUTFy = "F0 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiThreeOctets\string~}} + \UTFviiiLoop + + \countUTFx = "F0 + \countUTFy = "F4 + \def\UTFviiiTmp{% + \xdef~{\noexpand\UTFviiiFourOctets\string~}} + \UTFviiiLoop +\endgroup + +\begingroup + \catcode`\"=12 + \catcode`\<=12 + \catcode`\.=12 + \catcode`\,=12 + \catcode`\;=12 + \catcode`\!=12 + \catcode`\~=13 + + \gdef\DeclareUnicodeCharacter#1#2{% + \countUTFz = "#1\relax + %\wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% + \begingroup + \parseXMLCharref + \def\UTFviiiTwoOctets##1##2{% + \csname u8:##1\string ##2\endcsname}% + \def\UTFviiiThreeOctets##1##2##3{% + \csname u8:##1\string ##2\string ##3\endcsname}% + \def\UTFviiiFourOctets##1##2##3##4{% + \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter + \gdef\UTFviiiTmp{#2}% + \endgroup} + + \gdef\parseXMLCharref{% + \ifnum\countUTFz < "A0\relax + \errhelp = \EMsimple + \errmessage{Cannot define Unicode char value < 00A0}% + \else\ifnum\countUTFz < "800\relax + \parseUTFviiiA,% + \parseUTFviiiB C\UTFviiiTwoOctets.,% + \else\ifnum\countUTFz < "10000\relax + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% + \else + \parseUTFviiiA;% + \parseUTFviiiA,% + \parseUTFviiiA!% + \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% + \fi\fi\fi + } + + \gdef\parseUTFviiiA#1{% + \countUTFx = \countUTFz + \divide\countUTFz by 64 + \countUTFy = \countUTFz + \multiply\countUTFz by 64 + \advance\countUTFx by -\countUTFz + \advance\countUTFx by 128 + \uccode `#1\countUTFx + \countUTFz = \countUTFy} + + \gdef\parseUTFviiiB#1#2#3#4{% + \advance\countUTFz by "#10\relax + \uccode `#3\countUTFz + \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} +\endgroup + +\def\utfeightchardefs{% + \DeclareUnicodeCharacter{00A0}{\tie} + \DeclareUnicodeCharacter{00A1}{\exclamdown} + \DeclareUnicodeCharacter{00A3}{\pounds} + \DeclareUnicodeCharacter{00A8}{\"{ }} + \DeclareUnicodeCharacter{00A9}{\copyright} + \DeclareUnicodeCharacter{00AA}{\ordf} + \DeclareUnicodeCharacter{00AB}{\guillemetleft} + \DeclareUnicodeCharacter{00AD}{\-} + \DeclareUnicodeCharacter{00AE}{\registeredsymbol} + \DeclareUnicodeCharacter{00AF}{\={ }} + + \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} + \DeclareUnicodeCharacter{00B4}{\'{ }} + \DeclareUnicodeCharacter{00B8}{\cedilla{ }} + \DeclareUnicodeCharacter{00BA}{\ordm} + \DeclareUnicodeCharacter{00BB}{\guillemetright} + \DeclareUnicodeCharacter{00BF}{\questiondown} + + \DeclareUnicodeCharacter{00C0}{\`A} + \DeclareUnicodeCharacter{00C1}{\'A} + \DeclareUnicodeCharacter{00C2}{\^A} + \DeclareUnicodeCharacter{00C3}{\~A} + \DeclareUnicodeCharacter{00C4}{\"A} + \DeclareUnicodeCharacter{00C5}{\AA} + \DeclareUnicodeCharacter{00C6}{\AE} + \DeclareUnicodeCharacter{00C7}{\cedilla{C}} + \DeclareUnicodeCharacter{00C8}{\`E} + \DeclareUnicodeCharacter{00C9}{\'E} + \DeclareUnicodeCharacter{00CA}{\^E} + \DeclareUnicodeCharacter{00CB}{\"E} + \DeclareUnicodeCharacter{00CC}{\`I} + \DeclareUnicodeCharacter{00CD}{\'I} + \DeclareUnicodeCharacter{00CE}{\^I} + \DeclareUnicodeCharacter{00CF}{\"I} + + \DeclareUnicodeCharacter{00D0}{\DH} + \DeclareUnicodeCharacter{00D1}{\~N} + \DeclareUnicodeCharacter{00D2}{\`O} + \DeclareUnicodeCharacter{00D3}{\'O} + \DeclareUnicodeCharacter{00D4}{\^O} + \DeclareUnicodeCharacter{00D5}{\~O} + \DeclareUnicodeCharacter{00D6}{\"O} + \DeclareUnicodeCharacter{00D8}{\O} + \DeclareUnicodeCharacter{00D9}{\`U} + \DeclareUnicodeCharacter{00DA}{\'U} + \DeclareUnicodeCharacter{00DB}{\^U} + \DeclareUnicodeCharacter{00DC}{\"U} + \DeclareUnicodeCharacter{00DD}{\'Y} + \DeclareUnicodeCharacter{00DE}{\TH} + \DeclareUnicodeCharacter{00DF}{\ss} + + \DeclareUnicodeCharacter{00E0}{\`a} + \DeclareUnicodeCharacter{00E1}{\'a} + \DeclareUnicodeCharacter{00E2}{\^a} + \DeclareUnicodeCharacter{00E3}{\~a} + \DeclareUnicodeCharacter{00E4}{\"a} + \DeclareUnicodeCharacter{00E5}{\aa} + \DeclareUnicodeCharacter{00E6}{\ae} + \DeclareUnicodeCharacter{00E7}{\cedilla{c}} + \DeclareUnicodeCharacter{00E8}{\`e} + \DeclareUnicodeCharacter{00E9}{\'e} + \DeclareUnicodeCharacter{00EA}{\^e} + \DeclareUnicodeCharacter{00EB}{\"e} + \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} + \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} + \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} + \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} + + \DeclareUnicodeCharacter{00F0}{\dh} + \DeclareUnicodeCharacter{00F1}{\~n} + \DeclareUnicodeCharacter{00F2}{\`o} + \DeclareUnicodeCharacter{00F3}{\'o} + \DeclareUnicodeCharacter{00F4}{\^o} + \DeclareUnicodeCharacter{00F5}{\~o} + \DeclareUnicodeCharacter{00F6}{\"o} + \DeclareUnicodeCharacter{00F8}{\o} + \DeclareUnicodeCharacter{00F9}{\`u} + \DeclareUnicodeCharacter{00FA}{\'u} + \DeclareUnicodeCharacter{00FB}{\^u} + \DeclareUnicodeCharacter{00FC}{\"u} + \DeclareUnicodeCharacter{00FD}{\'y} + \DeclareUnicodeCharacter{00FE}{\th} + \DeclareUnicodeCharacter{00FF}{\"y} + + \DeclareUnicodeCharacter{0100}{\=A} + \DeclareUnicodeCharacter{0101}{\=a} + \DeclareUnicodeCharacter{0102}{\u{A}} + \DeclareUnicodeCharacter{0103}{\u{a}} + \DeclareUnicodeCharacter{0104}{\ogonek{A}} + \DeclareUnicodeCharacter{0105}{\ogonek{a}} + \DeclareUnicodeCharacter{0106}{\'C} + \DeclareUnicodeCharacter{0107}{\'c} + \DeclareUnicodeCharacter{0108}{\^C} + \DeclareUnicodeCharacter{0109}{\^c} + \DeclareUnicodeCharacter{0118}{\ogonek{E}} + \DeclareUnicodeCharacter{0119}{\ogonek{e}} + \DeclareUnicodeCharacter{010A}{\dotaccent{C}} + \DeclareUnicodeCharacter{010B}{\dotaccent{c}} + \DeclareUnicodeCharacter{010C}{\v{C}} + \DeclareUnicodeCharacter{010D}{\v{c}} + \DeclareUnicodeCharacter{010E}{\v{D}} + + \DeclareUnicodeCharacter{0112}{\=E} + \DeclareUnicodeCharacter{0113}{\=e} + \DeclareUnicodeCharacter{0114}{\u{E}} + \DeclareUnicodeCharacter{0115}{\u{e}} + \DeclareUnicodeCharacter{0116}{\dotaccent{E}} + \DeclareUnicodeCharacter{0117}{\dotaccent{e}} + \DeclareUnicodeCharacter{011A}{\v{E}} + \DeclareUnicodeCharacter{011B}{\v{e}} + \DeclareUnicodeCharacter{011C}{\^G} + \DeclareUnicodeCharacter{011D}{\^g} + \DeclareUnicodeCharacter{011E}{\u{G}} + \DeclareUnicodeCharacter{011F}{\u{g}} + + \DeclareUnicodeCharacter{0120}{\dotaccent{G}} + \DeclareUnicodeCharacter{0121}{\dotaccent{g}} + \DeclareUnicodeCharacter{0124}{\^H} + \DeclareUnicodeCharacter{0125}{\^h} + \DeclareUnicodeCharacter{0128}{\~I} + \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} + \DeclareUnicodeCharacter{012A}{\=I} + \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} + \DeclareUnicodeCharacter{012C}{\u{I}} + \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} + + \DeclareUnicodeCharacter{0130}{\dotaccent{I}} + \DeclareUnicodeCharacter{0131}{\dotless{i}} + \DeclareUnicodeCharacter{0132}{IJ} + \DeclareUnicodeCharacter{0133}{ij} + \DeclareUnicodeCharacter{0134}{\^J} + \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} + \DeclareUnicodeCharacter{0139}{\'L} + \DeclareUnicodeCharacter{013A}{\'l} + + \DeclareUnicodeCharacter{0141}{\L} + \DeclareUnicodeCharacter{0142}{\l} + \DeclareUnicodeCharacter{0143}{\'N} + \DeclareUnicodeCharacter{0144}{\'n} + \DeclareUnicodeCharacter{0147}{\v{N}} + \DeclareUnicodeCharacter{0148}{\v{n}} + \DeclareUnicodeCharacter{014C}{\=O} + \DeclareUnicodeCharacter{014D}{\=o} + \DeclareUnicodeCharacter{014E}{\u{O}} + \DeclareUnicodeCharacter{014F}{\u{o}} + + \DeclareUnicodeCharacter{0150}{\H{O}} + \DeclareUnicodeCharacter{0151}{\H{o}} + \DeclareUnicodeCharacter{0152}{\OE} + \DeclareUnicodeCharacter{0153}{\oe} + \DeclareUnicodeCharacter{0154}{\'R} + \DeclareUnicodeCharacter{0155}{\'r} + \DeclareUnicodeCharacter{0158}{\v{R}} + \DeclareUnicodeCharacter{0159}{\v{r}} + \DeclareUnicodeCharacter{015A}{\'S} + \DeclareUnicodeCharacter{015B}{\'s} + \DeclareUnicodeCharacter{015C}{\^S} + \DeclareUnicodeCharacter{015D}{\^s} + \DeclareUnicodeCharacter{015E}{\cedilla{S}} + \DeclareUnicodeCharacter{015F}{\cedilla{s}} + + \DeclareUnicodeCharacter{0160}{\v{S}} + \DeclareUnicodeCharacter{0161}{\v{s}} + \DeclareUnicodeCharacter{0162}{\cedilla{t}} + \DeclareUnicodeCharacter{0163}{\cedilla{T}} + \DeclareUnicodeCharacter{0164}{\v{T}} + + \DeclareUnicodeCharacter{0168}{\~U} + \DeclareUnicodeCharacter{0169}{\~u} + \DeclareUnicodeCharacter{016A}{\=U} + \DeclareUnicodeCharacter{016B}{\=u} + \DeclareUnicodeCharacter{016C}{\u{U}} + \DeclareUnicodeCharacter{016D}{\u{u}} + \DeclareUnicodeCharacter{016E}{\ringaccent{U}} + \DeclareUnicodeCharacter{016F}{\ringaccent{u}} + + \DeclareUnicodeCharacter{0170}{\H{U}} + \DeclareUnicodeCharacter{0171}{\H{u}} + \DeclareUnicodeCharacter{0174}{\^W} + \DeclareUnicodeCharacter{0175}{\^w} + \DeclareUnicodeCharacter{0176}{\^Y} + \DeclareUnicodeCharacter{0177}{\^y} + \DeclareUnicodeCharacter{0178}{\"Y} + \DeclareUnicodeCharacter{0179}{\'Z} + \DeclareUnicodeCharacter{017A}{\'z} + \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} + \DeclareUnicodeCharacter{017C}{\dotaccent{z}} + \DeclareUnicodeCharacter{017D}{\v{Z}} + \DeclareUnicodeCharacter{017E}{\v{z}} + + \DeclareUnicodeCharacter{01C4}{D\v{Z}} + \DeclareUnicodeCharacter{01C5}{D\v{z}} + \DeclareUnicodeCharacter{01C6}{d\v{z}} + \DeclareUnicodeCharacter{01C7}{LJ} + \DeclareUnicodeCharacter{01C8}{Lj} + \DeclareUnicodeCharacter{01C9}{lj} + \DeclareUnicodeCharacter{01CA}{NJ} + \DeclareUnicodeCharacter{01CB}{Nj} + \DeclareUnicodeCharacter{01CC}{nj} + \DeclareUnicodeCharacter{01CD}{\v{A}} + \DeclareUnicodeCharacter{01CE}{\v{a}} + \DeclareUnicodeCharacter{01CF}{\v{I}} + + \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} + \DeclareUnicodeCharacter{01D1}{\v{O}} + \DeclareUnicodeCharacter{01D2}{\v{o}} + \DeclareUnicodeCharacter{01D3}{\v{U}} + \DeclareUnicodeCharacter{01D4}{\v{u}} + + \DeclareUnicodeCharacter{01E2}{\={\AE}} + \DeclareUnicodeCharacter{01E3}{\={\ae}} + \DeclareUnicodeCharacter{01E6}{\v{G}} + \DeclareUnicodeCharacter{01E7}{\v{g}} + \DeclareUnicodeCharacter{01E8}{\v{K}} + \DeclareUnicodeCharacter{01E9}{\v{k}} + + \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} + \DeclareUnicodeCharacter{01F1}{DZ} + \DeclareUnicodeCharacter{01F2}{Dz} + \DeclareUnicodeCharacter{01F3}{dz} + \DeclareUnicodeCharacter{01F4}{\'G} + \DeclareUnicodeCharacter{01F5}{\'g} + \DeclareUnicodeCharacter{01F8}{\`N} + \DeclareUnicodeCharacter{01F9}{\`n} + \DeclareUnicodeCharacter{01FC}{\'{\AE}} + \DeclareUnicodeCharacter{01FD}{\'{\ae}} + \DeclareUnicodeCharacter{01FE}{\'{\O}} + \DeclareUnicodeCharacter{01FF}{\'{\o}} + + \DeclareUnicodeCharacter{021E}{\v{H}} + \DeclareUnicodeCharacter{021F}{\v{h}} + + \DeclareUnicodeCharacter{0226}{\dotaccent{A}} + \DeclareUnicodeCharacter{0227}{\dotaccent{a}} + \DeclareUnicodeCharacter{0228}{\cedilla{E}} + \DeclareUnicodeCharacter{0229}{\cedilla{e}} + \DeclareUnicodeCharacter{022E}{\dotaccent{O}} + \DeclareUnicodeCharacter{022F}{\dotaccent{o}} + + \DeclareUnicodeCharacter{0232}{\=Y} + \DeclareUnicodeCharacter{0233}{\=y} + \DeclareUnicodeCharacter{0237}{\dotless{j}} + + \DeclareUnicodeCharacter{02DB}{\ogonek{ }} + + \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} + \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} + \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} + \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} + \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} + \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} + \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} + \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} + \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} + \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} + \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} + \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} + + \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} + \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} + + \DeclareUnicodeCharacter{1E20}{\=G} + \DeclareUnicodeCharacter{1E21}{\=g} + \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} + \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} + \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} + \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} + \DeclareUnicodeCharacter{1E26}{\"H} + \DeclareUnicodeCharacter{1E27}{\"h} + + \DeclareUnicodeCharacter{1E30}{\'K} + \DeclareUnicodeCharacter{1E31}{\'k} + \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} + \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} + \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} + \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} + \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} + \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} + \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} + \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} + \DeclareUnicodeCharacter{1E3E}{\'M} + \DeclareUnicodeCharacter{1E3F}{\'m} + + \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} + \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} + \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} + \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} + \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} + \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} + \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} + \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} + \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} + \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} + + \DeclareUnicodeCharacter{1E54}{\'P} + \DeclareUnicodeCharacter{1E55}{\'p} + \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} + \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} + \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} + \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} + \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} + \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} + \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} + \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} + + \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} + \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} + \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} + \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} + \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} + \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} + \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} + \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} + \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} + \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} + + \DeclareUnicodeCharacter{1E7C}{\~V} + \DeclareUnicodeCharacter{1E7D}{\~v} + \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} + \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} + + \DeclareUnicodeCharacter{1E80}{\`W} + \DeclareUnicodeCharacter{1E81}{\`w} + \DeclareUnicodeCharacter{1E82}{\'W} + \DeclareUnicodeCharacter{1E83}{\'w} + \DeclareUnicodeCharacter{1E84}{\"W} + \DeclareUnicodeCharacter{1E85}{\"w} + \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} + \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} + \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} + \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} + \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} + \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} + \DeclareUnicodeCharacter{1E8C}{\"X} + \DeclareUnicodeCharacter{1E8D}{\"x} + \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} + \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} + + \DeclareUnicodeCharacter{1E90}{\^Z} + \DeclareUnicodeCharacter{1E91}{\^z} + \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} + \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} + \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} + \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} + \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} + \DeclareUnicodeCharacter{1E97}{\"t} + \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} + \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} + + \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} + \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} + + \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} + \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} + \DeclareUnicodeCharacter{1EBC}{\~E} + \DeclareUnicodeCharacter{1EBD}{\~e} + + \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} + \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} + \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} + \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} + + \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} + \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} + + \DeclareUnicodeCharacter{1EF2}{\`Y} + \DeclareUnicodeCharacter{1EF3}{\`y} + \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} + + \DeclareUnicodeCharacter{1EF8}{\~Y} + \DeclareUnicodeCharacter{1EF9}{\~y} + + \DeclareUnicodeCharacter{2013}{--} + \DeclareUnicodeCharacter{2014}{---} + \DeclareUnicodeCharacter{2018}{\quoteleft} + \DeclareUnicodeCharacter{2019}{\quoteright} + \DeclareUnicodeCharacter{201A}{\quotesinglbase} + \DeclareUnicodeCharacter{201C}{\quotedblleft} + \DeclareUnicodeCharacter{201D}{\quotedblright} + \DeclareUnicodeCharacter{201E}{\quotedblbase} + \DeclareUnicodeCharacter{2022}{\bullet} + \DeclareUnicodeCharacter{2026}{\dots} + \DeclareUnicodeCharacter{2039}{\guilsinglleft} + \DeclareUnicodeCharacter{203A}{\guilsinglright} + \DeclareUnicodeCharacter{20AC}{\euro} + + \DeclareUnicodeCharacter{2192}{\expansion} + \DeclareUnicodeCharacter{21D2}{\result} + + \DeclareUnicodeCharacter{2212}{\minus} + \DeclareUnicodeCharacter{2217}{\point} + \DeclareUnicodeCharacter{2261}{\equiv} +}% end of \utfeightchardefs + + +% US-ASCII character definitions. +\def\asciichardefs{% nothing need be done + \relax +} + +% Make non-ASCII characters printable again for compatibility with +% existing Texinfo documents that may use them, even without declaring a +% document encoding. +% +\setnonasciicharscatcode \other + + +\message{formatting,} + \newdimen\defaultparindent \defaultparindent = 15pt \chapheadingskip = 15pt plus 4pt minus 2pt @@ -6661,10 +9671,10 @@ should work if nowhere else does.} % Prevent underfull vbox error messages. \vbadness = 10000 -% Don't be so finicky about underfull hboxes, either. -\hbadness = 2000 +% Don't be very finicky about underfull hboxes, either. +\hbadness = 6666 -% Following George Bush, just get rid of widows and orphans. +% Following George Bush, get rid of widows and orphans. \widowpenalty=10000 \clubpenalty=10000 @@ -6682,9 +9692,9 @@ should work if nowhere else does.} \fi } -% Parameters in order: 1) textheight; 2) textwidth; 3) voffset; -% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8) -% physical page width. +% Parameters in order: 1) textheight; 2) textwidth; +% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; +% 7) physical page height; 8) physical page width. % % We also call \setleading{\textleading}, so the caller should define % \textleading. The caller should also set \parskip. @@ -6711,6 +9721,10 @@ should work if nowhere else does.} \ifpdf \pdfpageheight #7\relax \pdfpagewidth #8\relax + % if we don't reset these, they will remain at "1 true in" of + % whatever layout pdftex was dumped with. + \pdfhorigin = 1 true in + \pdfvorigin = 1 true in \fi % \setleading{\textleading} @@ -6725,19 +9739,19 @@ should work if nowhere else does.} \textleading = 13.2pt % % If page is nothing but text, make it come out even. - \internalpagesizes{46\baselineskip}{6in}% + \internalpagesizes{607.2pt}{6in}% that's 46 lines {\voffset}{.25in}% {\bindingoffset}{36pt}% {11in}{8.5in}% }} -% Use @smallbook to reset parameters for 7x9.5 (or so) format. +% Use @smallbook to reset parameters for 7x9.25 trim size. \def\smallbook{{\globaldefs = 1 \parskip = 2pt plus 1pt \textleading = 12pt % \internalpagesizes{7.5in}{5in}% - {\voffset}{.25in}% + {-.2in}{0in}% {\bindingoffset}{16pt}% {9.25in}{7in}% % @@ -6748,6 +9762,24 @@ should work if nowhere else does.} \defbodyindent = .5cm }} +% Use @smallerbook to reset parameters for 6x9 trim size. +% (Just testing, parameters still in flux.) +\def\smallerbook{{\globaldefs = 1 + \parskip = 1.5pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.4in}{4.8in}% + {-.2in}{-.4in}% + {0pt}{14pt}% + {9in}{6in}% + % + \lispnarrowing = 0.25in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .4cm +}} + % Use @afourpaper to print on European A4 paper. \def\afourpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt @@ -6763,7 +9795,7 @@ should work if nowhere else does.} % \global\normaloffset = -6mm % \global\bindingoffset = 10mm % @end tex - \internalpagesizes{51\baselineskip}{160mm} + \internalpagesizes{673.2pt}{160mm}% that's 51 lines {\voffset}{\hoffset}% {\bindingoffset}{44pt}% {297mm}{210mm}% @@ -6828,7 +9860,7 @@ should work if nowhere else does.} \parskip = 3pt plus 2pt minus 1pt \setleading{\textleading}% % - \dimen0 = #1 + \dimen0 = #1\relax \advance\dimen0 by \voffset % \dimen2 = \hsize @@ -6847,25 +9879,21 @@ should work if nowhere else does.} \message{and turning on texinfo input format.} +\def^^L{\par} % remove \outer, so ^L can appear in an @comment + +% DEL is a comment character, in case @c does not suffice. +\catcode`\^^? = 14 + % Define macros to output various characters with catcode for normal text. -\catcode`\"=\other -\catcode`\~=\other -\catcode`\^=\other -\catcode`\_=\other -\catcode`\|=\other -\catcode`\<=\other -\catcode`\>=\other -\catcode`\+=\other -\catcode`\$=\other -\def\normaldoublequote{"} -\def\normaltilde{~} -\def\normalcaret{^} -\def\normalunderscore{_} -\def\normalverticalbar{|} -\def\normalless{<} -\def\normalgreater{>} -\def\normalplus{+} -\def\normaldollar{$}%$ font-lock fix +\catcode`\"=\other \def\normaldoublequote{"} +\catcode`\$=\other \def\normaldollar{$}%$ font-lock fix +\catcode`\+=\other \def\normalplus{+} +\catcode`\<=\other \def\normalless{<} +\catcode`\>=\other \def\normalgreater{>} +\catcode`\^=\other \def\normalcaret{^} +\catcode`\_=\other \def\normalunderscore{_} +\catcode`\|=\other \def\normalverticalbar{|} +\catcode`\~=\other \def\normaltilde{~} % This macro is used to make a character print one way in \tt % (where it can probably be output as-is), and another way in other fonts, @@ -6900,6 +9928,7 @@ should work if nowhere else does.} \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} +\let\realunder=_ % Subroutine for the previous macro. \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } @@ -6922,6 +9951,13 @@ should work if nowhere else does.} % \otherifyactive is called near the end of this file. \def\otherifyactive{\catcode`+=\other \catcode`\_=\other} +% Used sometimes to turn off (effectively) the active characters even after +% parsing them. +\def\turnoffactive{% + \normalturnoffactive + \otherbackslash +} + \catcode`\@=0 % \backslashcurfont outputs one backslash character in current font, @@ -6929,43 +9965,55 @@ should work if nowhere else does.} \global\chardef\backslashcurfont=`\\ \global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work +% \realbackslash is an actual character `\' with catcode other, and +% \doublebackslash is two of them (for the pdf outlines). +{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} + +% In texinfo, backslash is an active character; it prints the backslash +% in fixed width font. +\catcode`\\=\active % @ for escape char from now on. + +% The story here is that in math mode, the \char of \backslashcurfont +% ends up printing the roman \ from the math symbol font (because \char +% in math mode uses the \mathcode, and plain.tex sets +% \mathcode`\\="026E). It seems better for @backslashchar{} to always +% print a typewriter backslash, hence we use an explicit \mathchar, +% which is the decimal equivalent of "715c (class 7, e.g., use \fam; +% ignored family value; char position "5C). We can't use " for the +% usual hex value because it has already been made active. +@def@normalbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} +@let@backslashchar = @normalbackslash % @backslashchar{} is for user documents. + +% On startup, @fixbackslash assigns: +% @let \ = @normalbackslash % \rawbackslash defines an active \ to do \backslashcurfont. % \otherbackslash defines an active \ to be a literal `\' character with -% catcode other. -{\catcode`\\=\active - @gdef@rawbackslash{@let\=@backslashcurfont} - @gdef@otherbackslash{@let\=@realbackslash} -} - -% \realbackslash is an actual character `\' with catcode other. -{\catcode`\\=\other @gdef@realbackslash{\}} - -% \normalbackslash outputs one backslash in fixed width font. -\def\normalbackslash{{\tt\backslashcurfont}} - -\catcode`\\=\active - -% Used sometimes to turn off (effectively) the active characters -% even after parsing them. -@def@turnoffactive{% - @let"=@normaldoublequote - @let\=@realbackslash - @let~=@normaltilde - @let^=@normalcaret - @let_=@normalunderscore - @let|=@normalverticalbar - @let<=@normalless - @let>=@normalgreater - @let+=@normalplus - @let$=@normaldollar %$ font-lock fix - @unsepspaces -} +% catcode other. We switch back and forth between these. +@gdef@rawbackslash{@let\=@backslashcurfont} +@gdef@otherbackslash{@let\=@realbackslash} % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of -% the literal character `\'. (Thus, \ is not expandable when this is in -% effect.) +% the literal character `\'. Also revert - to its normal character, in +% case the active - from code has slipped in. % -@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash} +{@catcode`- = @active + @gdef@normalturnoffactive{% + @let-=@normaldash + @let"=@normaldoublequote + @let$=@normaldollar %$ font-lock fix + @let+=@normalplus + @let<=@normalless + @let>=@normalgreater + @let\=@normalbackslash + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let~=@normaltilde + @markupsetuplqdefault + @markupsetuprqdefault + @unsepspaces + } +} % Make _ and + \other characters, temporarily. % This is canceled by @fixbackslash. @@ -6979,9 +10027,9 @@ should work if nowhere else does.} @global@let\ = @eatinput % On the other hand, perhaps the file did not have a `\input texinfo'. Then -% the first `\{ in the file would cause an error. This macro tries to fix +% the first `\' in the file would cause an error. This macro tries to fix % that, assuming it is called before the first `\' could plausibly occur. -% Also back turn on active characters that might appear in the input +% Also turn back on active characters that might appear in the input % file name, in case not using a pre-dumped format. % @gdef@fixbackslash{% @@ -6993,11 +10041,28 @@ should work if nowhere else does.} % Say @foo, not \foo, in error messages. @escapechar = `@@ -% These look ok in all fonts, so just make them not special. -@catcode`@& = @other -@catcode`@# = @other -@catcode`@% = @other +% These (along with & and #) are made active for url-breaking, so need +% active definitions as the normal characters. +@def@normaldot{.} +@def@normalquest{?} +@def@normalslash{/} +% These look ok in all fonts, so just make them not special. +% @hashchar{} gets its own user-level command, because of #line. +@catcode`@& = @other @def@normalamp{&} +@catcode`@# = @other @def@normalhash{#} +@catcode`@% = @other @def@normalpercent{%} + +@let @hashchar = @normalhash + +@c Finally, make ` and ' active, so that txicodequoteundirected and +@c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}. If we +@c don't make ` and ' active, @code will not get them as active chars. +@c Do this last of all since we use ` in the previous @catcode assignments. +@catcode`@'=@active +@catcode`@`=@active +@markupsetuplqdefault +@markupsetuprqdefault @c Local variables: @c eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/contrib/amd/doc/version.texi b/contrib/amd/doc/version.texi index 41b19a30d5c..9a4feda60f5 100644 --- a/contrib/amd/doc/version.texi +++ b/contrib/amd/doc/version.texi @@ -1,4 +1,4 @@ -@set UPDATED 20 April 2006 -@set UPDATED-MONTH April 2006 -@set EDITION 6.1.5 -@set VERSION 6.1.5 +@set UPDATED 28 October 2014 +@set UPDATED-MONTH October 2014 +@set EDITION 6.2 +@set VERSION 6.2 diff --git a/contrib/amd/fixmount/fixmount.8 b/contrib/amd/fixmount/fixmount.8 index 03673e90661..462984cbe44 100644 --- a/contrib/amd/fixmount/fixmount.8 +++ b/contrib/amd/fixmount/fixmount.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1990 Jan-Simon Pendry .\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,9 +32,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" %W% (Berkeley) %G% .\" -.\" $Id: fixmount.8,v 1.12.2.1 2006/01/02 18:48:25 ezk Exp $ +.\" File: am-utils/fixmount/fixmount.8 .\" $FreeBSD$ .\" .Dd February 26, 2016 diff --git a/contrib/amd/fixmount/fixmount.c b/contrib/amd/fixmount/fixmount.c index c7c69102a55..9465f30d758 100644 --- a/contrib/amd/fixmount/fixmount.c +++ b/contrib/amd/fixmount/fixmount.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -115,7 +111,7 @@ is_same_host(char *name1, char *name2, struct in_addr addr2) } else if (!(he = gethostbyname(name1))) { return 0; } else { - xstrlcpy(lasthost, name1, MAXHOSTNAMELEN); + xstrlcpy(lasthost, name1, sizeof(lasthost)); memcpy(&addr1, he->h_addr, sizeof(addr1)); return (addr1.s_addr == addr2.s_addr); } @@ -176,7 +172,7 @@ remove_mount(CLIENT *client, char *host, mountlist ml, int fixit) (XDRPROC_T_TYPE) xdr_dirpath, (char *) &pathp, (XDRPROC_T_TYPE) xdr_void, - (char *) 0, + (char *) NULL, tv)) != RPC_SUCCESS) { fprintf(stderr, "%s:%s MOUNTPROC_UMNT: ", host, ml->ml_directory); @@ -235,9 +231,9 @@ remove_all(CLIENT *client, char *host) if ((estat = clnt_call(client, MOUNTPROC_UMNTALL, (XDRPROC_T_TYPE) xdr_void, - (char *) 0, + (char *) NULL, (XDRPROC_T_TYPE) xdr_void, - (char *) 0, + (char *) NULL, tv)) != RPC_SUCCESS) { /* * RPC_SYSTEMERROR is returned even if all went well @@ -389,7 +385,7 @@ main(int argc, char *argv[]) if ((estat = clnt_call(client, MOUNTPROC_DUMP, (XDRPROC_T_TYPE) xdr_void, - (char *) 0, + (char *) NULL, (XDRPROC_T_TYPE) xdr_mountlist, (char *) &mntdump, tv)) != RPC_SUCCESS) { @@ -403,7 +399,7 @@ main(int argc, char *argv[]) if ((estat = clnt_call(client, MOUNTPROC_EXPORT, (XDRPROC_T_TYPE) xdr_void, - (char *) 0, + (char *) NULL, (XDRPROC_T_TYPE) xdr_exports, (char *) &mntexports, tv)) != RPC_SUCCESS) { diff --git a/contrib/amd/fsinfo/fsi_analyze.c b/contrib/amd/fsinfo/fsi_analyze.c index 9da40978e62..78598b85464 100644 --- a/contrib/amd/fsinfo/fsi_analyze.c +++ b/contrib/amd/fsinfo/fsi_analyze.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -56,27 +52,27 @@ char *disk_fs_strings[] = { - "fstype", "opts", "dumpset", "passno", "freq", "mount", "log", 0, + "fstype", "opts", "dumpset", "passno", "freq", "mount", "log", NULL, }; char *mount_strings[] = { - "volname", "exportfs", 0, + "volname", "exportfs", NULL, }; char *fsmount_strings[] = { - "as", "volname", "fstype", "opts", "from", 0, + "as", "volname", "fstype", "opts", "from", NULL, }; char *host_strings[] = { - "host", "netif", "config", "arch", "cluster", "os", 0, + "host", "netif", "config", "arch", "cluster", "os", NULL, }; char *ether_if_strings[] = { - "inaddr", "netmask", "hwaddr", 0, + "inaddr", "netmask", "hwaddr", NULL, }; @@ -122,7 +118,7 @@ compute_hostpath(char *hn) do { d = strrchr(p, '.'); if (d) { - *d = 0; + *d = '\0'; xstrlcat(path, d + 1, sizeof(path)); xstrlcat(path, "/", sizeof(path)); } else { @@ -141,7 +137,7 @@ static dict_ent * find_volname(char *nn) { dict_ent *de; - char *p = strdup(nn); + char *p = xstrdup(nn); char *q; do { @@ -186,7 +182,7 @@ check_exportfs(qelem *q, fsi_mount *e) lwarning(mp->m_ioloc, "%s has duplicate exportfs data", mp->m_name); mp->m_exported = mp; if (!ISSET(mp->m_mask, DM_VOLNAME)) - set_mount(mp, DM_VOLNAME, strdup(mp->m_name)); + set_mount(mp, DM_VOLNAME, xstrdup(mp->m_name)); } else { mp->m_exported = e; } @@ -228,7 +224,7 @@ analyze_dkmount_tree(qelem *q, fsi_mount *parent, disk_fs *dk) lwarning(mp->m_ioloc, "sub-directory of %s is named \"default\"", parent->m_name); fsi_log("Changing name %s to %s", mp->m_name, n); XFREE(mp->m_name); - mp->m_name = strdup(n); + mp->m_name = xstrdup(n); } mp->m_name_len = strlen(mp->m_name); @@ -251,7 +247,7 @@ static int analyze_dkmounts(disk_fs *dk, qelem *q) { int errors = 0; - fsi_mount *mp, *mp2 = 0; + fsi_mount *mp, *mp2 = NULL; int i = 0; /* @@ -286,7 +282,7 @@ analyze_dkmounts(disk_fs *dk, qelem *q) char nbuf[1024]; compute_automount_point(nbuf, sizeof(nbuf), dk->d_host, mp2->m_volname); XFREE(mp2->m_name); - mp2->m_name = strdup(nbuf); + mp2->m_name = xstrdup(nbuf); fsi_log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name); } else { lerror(dk->d_ioloc, "no volname given for %s:%s", dk->d_host->h_hostname, dk->d_dev); @@ -298,19 +294,19 @@ analyze_dkmounts(disk_fs *dk, qelem *q) * Fill in the disk mount point */ if (!errors && mp2 && mp2->m_name) - dk->d_mountpt = strdup(mp2->m_name); + dk->d_mountpt = xstrdup(mp2->m_name); else - dk->d_mountpt = strdup("error"); + dk->d_mountpt = xstrdup("error"); /* * Analyze the mount tree */ - errors += analyze_dkmount_tree(q, 0, dk); + errors += analyze_dkmount_tree(q, NULL, dk); /* * Analyze the export tree */ - errors += check_exportfs(q, 0); + errors += check_exportfs(q, NULL); return errors; } @@ -353,7 +349,7 @@ fixup_required_disk_info(disk_fs *dp) * "opts" */ if (!ISSET(dp->d_mask, DF_OPTS)) - set_disk_fs(dp, DF_OPTS, strdup("swap")); + set_disk_fs(dp, DF_OPTS, xstrdup("swap")); /* * "mount" @@ -362,7 +358,7 @@ fixup_required_disk_info(disk_fs *dp) qelem *q = new_que(); fsi_mount *m = new_mount(); - m->m_name = strdup("swap"); + m->m_name = xstrdup("swap"); m->m_mount = new_que(); ins_que(&m->m_q, q->q_back); dp->d_mount = q; @@ -400,7 +396,7 @@ fixup_required_disk_info(disk_fs *dp) * "opts" */ if (!ISSET(dp->d_mask, DF_OPTS)) - set_disk_fs(dp, DF_OPTS, strdup("rw,defaults")); + set_disk_fs(dp, DF_OPTS, xstrdup("rw,defaults")); } } @@ -415,7 +411,7 @@ fixup_required_mount_info(fsmount *fp, dict_ent *de) lerror(fp->f_ioloc, "ambiguous mount: %s is a replicated filesystem", fp->f_volname); } else { dict_data *dd; - fsi_mount *mp = 0; + fsi_mount *mp = NULL; dd = AM_FIRST(dict_data, &de->de_q); mp = (fsi_mount *) dd->dd_data; if (!mp) @@ -427,18 +423,18 @@ fixup_required_mount_info(fsmount *fp, dict_ent *de) } if (!ISSET(fp->f_mask, FM_FSTYPE)) { - set_fsmount(fp, FM_FSTYPE, strdup("nfs")); + set_fsmount(fp, FM_FSTYPE, xstrdup("nfs")); fsi_log("set: fstype is %s", fp->f_fstype); } if (!ISSET(fp->f_mask, FM_OPTS)) { - set_fsmount(fp, FM_OPTS, strdup("rw,nosuid,grpid,defaults")); + set_fsmount(fp, FM_OPTS, xstrdup("rw,nosuid,grpid,defaults")); fsi_log("set: opts are %s", fp->f_opts); } if (!ISSET(fp->f_mask, FM_LOCALNAME)) { if (fp->f_ref) { - set_fsmount(fp, FM_LOCALNAME, strdup(fp->f_volname)); + set_fsmount(fp, FM_LOCALNAME, xstrdup(fp->f_volname)); fsi_log("set: localname is %s", fp->f_localname); } else { lerror(fp->f_ioloc, "cannot determine localname since volname %s is not uniquely defined", fp->f_volname); @@ -485,7 +481,7 @@ analyze_mounts(host *hp) ITER(fp, fsmount, q) { char *p; - char *nn = strdup(fp->f_volname); + char *nn = xstrdup(fp->f_volname); int req; dict_ent *de = (dict_ent *) NULL; int found = 0; @@ -496,7 +492,7 @@ analyze_mounts(host *hp) matched = 1; } else do { - p = 0; + p = NULL; de = find_volname(nn); fsi_log("Mount: %s (trying %s)", fp->f_volname, nn); @@ -511,7 +507,7 @@ analyze_mounts(host *hp) */ if (ISSET(fp->f_mask, FM_FROM) && !ISSET(fp->f_mask, FM_DIRECT)) { dict_data *dd; - fsi_mount *mp2 = 0; + fsi_mount *mp2 = NULL; ITER(dd, dict_data, &de->de_q) { fsi_mount *mp = (fsi_mount *) dd->dd_data; @@ -535,7 +531,7 @@ analyze_mounts(host *hp) } p = strrchr(nn, '/'); if (p) - *p = 0; + *p = '\0'; } while (de && p); XFREE(nn); @@ -635,7 +631,7 @@ analyze_automount_tree(qelem *q, char *pref, int lvl) lerror(ap->a_ioloc, "not allowed '/' in a directory name"); xsnprintf(nname, sizeof(nname), "%s/%s", pref, ap->a_name); XFREE(ap->a_name); - ap->a_name = strdup(nname[1] == '/' ? nname + 1 : nname); + ap->a_name = xstrdup(nname[1] == '/' ? nname + 1 : nname); fsi_log("automount point %s:", ap->a_name); show_new("ana-automount"); @@ -649,7 +645,7 @@ analyze_automount_tree(qelem *q, char *pref, int lvl) } else if (ap->a_symlink) { fsi_log("\tsymlink to %s", ap->a_symlink); } else { - ap->a_volname = strdup(ap->a_name); + ap->a_volname = xstrdup(ap->a_name); fsi_log("\timplicit automount from %s", ap->a_volname); analyze_automount(ap); } diff --git a/contrib/amd/fsinfo/fsi_data.h b/contrib/amd/fsinfo/fsi_data.h index 8276caf36cb..4cc341d85a6 100644 --- a/contrib/amd/fsinfo/fsi_data.h +++ b/contrib/amd/fsinfo/fsi_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/fsinfo/fsi_dict.c b/contrib/amd/fsinfo/fsi_dict.c index 29cd1a3ed08..b909783b61e 100644 --- a/contrib/amd/fsinfo/fsi_dict.c +++ b/contrib/amd/fsinfo/fsi_dict.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/fsinfo/fsi_gram.y b/contrib/amd/fsinfo/fsi_gram.y index 961a89f1af4..85d19aa5cda 100644 --- a/contrib/amd/fsinfo/fsi_gram.y +++ b/contrib/amd/fsinfo/fsi_gram.y @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -200,7 +196,7 @@ automount : opt_auto_opts : /* empty */ - { $$ = strdup(""); } + { $$ = xstrdup(""); } | tOPTS tSTR { $$ = $2; } @@ -233,7 +229,7 @@ filesystem : { $4->d_dev = $2; $$ = $4; } | tFS error '}' - { $$ = (disk_fs *) 0; } + { $$ = (disk_fs *) NULL; } ; /* diff --git a/contrib/amd/fsinfo/fsi_lex.l b/contrib/amd/fsinfo/fsi_lex.l index 6bca59b4dee..4d09e2c55e7 100644 --- a/contrib/amd/fsinfo/fsi_lex.l +++ b/contrib/amd/fsinfo/fsi_lex.l @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -17,11 +17,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -102,7 +98,7 @@ static int ayylineno; */ #ifdef FLEX_SCANNER # ifndef ECHO -# define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +# define ECHO __IGNORE(fwrite( yytext, yyleng, 1, yyout )) # endif /* not ECHO */ #endif /* FLEX_SCANNER */ @@ -111,9 +107,11 @@ static int ayylineno; * which automatically generates yywrap macros and symbols. So I must * distinguish between them and when yywrap is actually needed. */ -#ifndef yywrap +#if !defined(yywrap) || defined(yylex) int yywrap(void); -#endif /* not yywrap */ +#endif /* not yywrap or yylex */ + +int fsi_error(const char *, ...); YYSTYPE yylval; static char *fsi_filename; @@ -153,7 +151,7 @@ struct r { { "passno", tPASSNO }, { "sel", tSEL }, { "volname", tVOLNAME }, - { 0, 0 }, + { NULL, 0 }, }; #define NRES_WORDS (sizeof(rr)/sizeof(rr[0])-1) @@ -162,6 +160,7 @@ struct r { /* This option causes Solaris lex to fail. Use flex. See BUGS file */ /* no need to use yyunput() */ %option nounput +%option noinput /* allocate more output slots so lex scanners don't run out of mem */ %o 1024 @@ -177,7 +176,7 @@ struct r { [={}] { return *yytext; } \" { BEGIN Q; optr = ostr; quoted = 1; } -\n { ayylineno++; yyerror("\" expected"); BEGIN F; } +\n { ayylineno++; fsi_error("\" expected"); BEGIN F; } \\b { *optr++ = '\b'; /* escape */ } \\t { *optr++ = '\t'; /* escape */ } \\\" { *optr++ = '\"'; /* escape */ } @@ -187,11 +186,11 @@ struct r { \\n { *optr++ = '\n'; /* escape */ } \\f { *optr++ = '\f'; /* escape */ } "\\ " { *optr++ = ' '; /* force space */ } -\\. { yyerror("Unknown \\ sequence"); } +\\. { fsi_error("Unknown \\ sequence"); } ([ \t]|"\\\n"){2,} { char *p = (char *) yytext-1; while ((p = strchr(p+1, '\n'))) ayylineno++; } \" { BEGIN F; quoted = 0; *optr = '\0'; - yylval.s = strdup(ostr); + yylval.s = xstrdup(ostr); return tSTR; } . { *optr++ = *yytext; } @@ -224,11 +223,11 @@ find_resword(char *s) switch (tok) { case tLOCALHOST: s = "${host}"; - /* fall through... */ + /*FALLTHROUGH*/ case 0: - yylval.s = strdup(s); + yylval.s = xstrdup(s); tok = tSTR; - /* fall through... */ + /*FALLTHROUGH*/ default: return tok; } @@ -236,7 +235,7 @@ find_resword(char *s) int -yyerror(char *fmt, ...) +fsi_error(const char *fmt, ...) { va_list ap; @@ -266,9 +265,9 @@ current_location(void) * which automatically generates yywrap macros and symbols. So I must * distinguish between them and when yywrap is actually needed. */ -#ifndef yywrap +#if !defined(yywrap) || defined(yylex) int yywrap(void) { return 1; } -#endif /* not yywrap */ +#endif /* not yywrap or yylex */ diff --git a/contrib/amd/fsinfo/fsi_util.c b/contrib/amd/fsinfo/fsi_util.c index 5e7571fd4db..f8ff313cc42 100644 --- a/contrib/amd/fsinfo/fsi_util.c +++ b/contrib/amd/fsinfo/fsi_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -13,11 +13,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -201,7 +197,7 @@ gen_hdr(FILE *ef, char *hn) static void make_banner(FILE *fp) { - time_t t = time((time_t *) 0); + time_t t = time((time_t *) NULL); char *cp = ctime(&t); fprintf(fp, @@ -235,7 +231,7 @@ show_new(char *msg) void show_area_being_processed(char *area, int n) { - static char *last_area = 0; + static char *last_area = NULL; if (verbose < 0) return; @@ -316,9 +312,9 @@ new_automount(char *name) ap->a_ioloc = current_location(); ap->a_name = name; - ap->a_volname = 0; - ap->a_mount = 0; - ap->a_opts = 0; + ap->a_volname = NULL; + ap->a_mount = NULL; + ap->a_opts = NULL; show_new("automount"); return ap; } @@ -355,7 +351,7 @@ set_host(host *hp, int k, char *v) int m = 1 << k; if (hp->h_mask & m) { - yyerror("host field \"%s\" already set", host_strings[k]); + fsi_error("host field \"%s\" already set", host_strings[k]); return; } hp->h_mask |= m; @@ -363,11 +359,11 @@ set_host(host *hp, int k, char *v) switch (k) { case HF_HOST:{ - char *p = strdup(v); + char *p = xstrdup(v); dict_ent *de = dict_locate(dict_of_hosts, v); if (de) - yyerror("duplicate host %s!", v); + fsi_error("duplicate host %s!", v); else dict_add(dict_of_hosts, v, (char *) hp); hp->h_hostname = v; @@ -442,7 +438,7 @@ set_ether_if(ether_if *ep, int k, char *v) int m = 1 << k; if (ep->e_mask & m) { - yyerror("netif field \"%s\" already set", ether_if_strings[k]); + fsi_error("netif field \"%s\" already set", ether_if_strings[k]); return; } ep->e_mask |= m; @@ -452,7 +448,7 @@ set_ether_if(ether_if *ep, int k, char *v) case EF_INADDR:{ ep->e_inaddr.s_addr = inet_addr(v); if ((int) ep->e_inaddr.s_addr == (int) INADDR_NONE) - yyerror("malformed IP dotted quad: %s", v); + fsi_error("malformed IP dotted quad: %s", v); XFREE(v); } break; @@ -463,7 +459,7 @@ set_ether_if(ether_if *ep, int k, char *v) if ((sscanf(v, "0x%lx", &nm) == 1 || sscanf(v, "%lx", &nm) == 1) && nm != 0) ep->e_netmask = htonl(nm); else - yyerror("malformed netmask: %s", v); + fsi_error("malformed netmask: %s", v); XFREE(v); } break; @@ -485,7 +481,7 @@ set_disk_fs(disk_fs *dp, int k, char *v) int m = 1 << k; if (dp->d_mask & m) { - yyerror("fs field \"%s\" already set", disk_fs_strings[k]); + fsi_error("fs field \"%s\" already set", disk_fs_strings[k]); return; } dp->d_mask |= m; @@ -546,7 +542,7 @@ set_mount(fsi_mount *mp, int k, char *v) int m = 1 << k; if (mp->m_mask & m) { - yyerror("mount tree field \"%s\" already set", mount_strings[k]); + fsi_error("mount tree field \"%s\" already set", mount_strings[k]); return; } mp->m_mask |= m; @@ -590,7 +586,7 @@ set_fsmount(fsmount *fp, int k, char *v) int m = 1 << k; if (fp->f_mask & m) { - yyerror("mount field \"%s\" already set", fsmount_strings[k]); + fsi_error("mount field \"%s\" already set", fsmount_strings[k]); return; } fp->f_mask |= m; diff --git a/contrib/amd/fsinfo/fsinfo.8 b/contrib/amd/fsinfo/fsinfo.8 index b1750f00384..f4a1afa94bf 100644 --- a/contrib/amd/fsinfo/fsinfo.8 +++ b/contrib/amd/fsinfo/fsinfo.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1993 Jan-Simon Pendry. .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. @@ -12,11 +12,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -32,32 +28,33 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" from: @(#)fsinfo.8 8.1 (Berkeley) 6/28/93 -.\" $Id: fsinfo.8,v 1.13.2.1 2006/01/02 18:48:25 ezk Exp $ .\" $FreeBSD$ .\" -.Dd February 26, 2016 -.Dt FSINFO 8 -.Os +.\" File: am-utils/fsinfo/fsinfo.8 +.\" +.Dd August 31, 2016 .Sh NAME .Nm fsinfo .Nd co-ordinate site-wide file system information .Sh SYNOPSIS .Nm -.Op Fl qv +.Op fl qv .Op Fl a Ar autodir -.Op Fl b Ar bootparams_prefix -.Op Fl d Ar dumpsets_prefix -.Op Fl e Ar exports_prefix -.Op Fl f Ar fstabs_prefix +.Op Fl b Ar bootparams +.Op Fl d Ar dumpsets +.Op Fl e Ar exports +.Op Fl f Ar fstabs .Op Fl h Ar hostname -.Op Fl m Ar automounts_prefix +.Op Fl m Ar automounts .Op Fl I Ar dir .Oo .Fl D .Ar name Ns Op = Ns Ar string .Oc -.Op Fl U Ar name +.Oo +.Fl U +.Ar name Ns Op = Ns Ar string +.Oc .Ar config ... .Sh DESCRIPTION .Bf -symbolic diff --git a/contrib/amd/fsinfo/fsinfo.c b/contrib/amd/fsinfo/fsinfo.c index e441a47fab4..93122eabbbb 100644 --- a/contrib/amd/fsinfo/fsinfo.c +++ b/contrib/amd/fsinfo/fsinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -213,7 +209,7 @@ find_username(void) if (!u) u = "root"; - return strdup(u); + return xstrdup(u); } @@ -258,7 +254,7 @@ main(int argc, char *argv[]) * Parse input */ show_area_being_processed("read config", 11); - if (yyparse()) + if (fsi_parse()) errors = 1; errors += file_io_errors + parse_errors; diff --git a/contrib/amd/fsinfo/fsinfo.h b/contrib/amd/fsinfo/fsinfo.h index 99b407b04bf..7a871631a0c 100644 --- a/contrib/amd/fsinfo/fsinfo.h +++ b/contrib/amd/fsinfo/fsinfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -104,7 +100,7 @@ extern void show_area_being_processed(char *area, int n); extern void show_new(char *msg); extern void warning(void); -extern int yyerror(char *fmt, ...) +extern int fsi_error(const char *fmt, ...) __attribute__((__format__(__printf__, 1, 2))); extern void domain_strip(char *otherdom, char *localdom); /* @@ -115,7 +111,7 @@ extern void domain_strip(char *otherdom, char *localdom); #ifndef yywrap extern int yywrap(void); #endif /* not yywrap */ -extern int yyparse(void); +extern int fsi_parse(void); extern int write_atab(qelem *q); extern int write_bootparams(qelem *q); extern int write_dumpset(qelem *q); @@ -124,7 +120,7 @@ extern int write_fstab(qelem *q); extern void col_cleanup(int eoj); extern void set_host(host *hp, int k, char *v); extern void set_ether_if(ether_if *ep, int k, char *v); -extern int yylex(void); +extern int fsi_lex(void); #define BITSET(m,b) ((m) |= (1<<(b))) diff --git a/contrib/amd/fsinfo/null_gram.c b/contrib/amd/fsinfo/null_gram.c new file mode 100644 index 00000000000..9b4e9f4a1cc --- /dev/null +++ b/contrib/amd/fsinfo/null_gram.c @@ -0,0 +1,1414 @@ +/* A Bison parser, made by GNU Bison 3.0.2. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + +/* Substitute the variable and function names. */ +#define yyparse null_parse +#define yylex null_lex +#define yyerror null_error +#define yydebug null_debug +#define yynerrs null_nerrs + +#define yylval null_lval +#define yychar null_char + +/* Copy the first part of user declarations. */ +#line 1 "../../fsinfo/null_gram.y" /* yacc.c:339 */ + +void yyerror(const char *fmt, ...); +extern int yylex(void); + +#line 79 "null_gram.c" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "y.tab.h". */ +#ifndef YY_NULL_NULL_GRAM_H_INCLUDED +# define YY_NULL_NULL_GRAM_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int null_debug; +#endif + + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE null_lval; + +int null_parse (void); + +#endif /* !YY_NULL_NULL_GRAM_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 126 "null_gram.c" /* yacc.c:358 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 0 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 3 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 2 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 2 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 3 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 257 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 8, 8 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "$accept", "token", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257 +}; +# endif + +#define YYPACT_NINF -1 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-1))) + +#define YYTABLE_NINF -1 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -1, 0, -1 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 0, 1 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -1, -1 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 1 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_uint8 yytable[] = +{ + 2 +}; + +static const yytype_uint8 yycheck[] = +{ + 0 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 4, 0 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 3, 4 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + +#line 1188 "null_gram.c" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} diff --git a/contrib/amd/fsinfo/null_gram.h b/contrib/amd/fsinfo/null_gram.h new file mode 100644 index 00000000000..77c4ac78ff4 --- /dev/null +++ b/contrib/amd/fsinfo/null_gram.h @@ -0,0 +1,56 @@ +/* A Bison parser, made by GNU Bison 3.0.2. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_NULL_NULL_GRAM_H_INCLUDED +# define YY_NULL_NULL_GRAM_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int null_debug; +#endif + + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE null_lval; + +int null_parse (void); + +#endif /* !YY_NULL_NULL_GRAM_H_INCLUDED */ diff --git a/contrib/amd/fsinfo/null_gram.y b/contrib/amd/fsinfo/null_gram.y new file mode 100644 index 00000000000..d7313b9c49c --- /dev/null +++ b/contrib/amd/fsinfo/null_gram.y @@ -0,0 +1,8 @@ +%{ +void yyerror(const char *fmt, ...); +extern int yylex(void); +%} + +%% + +token: diff --git a/contrib/amd/fsinfo/null_lex.c b/contrib/amd/fsinfo/null_lex.c new file mode 100644 index 00000000000..b890445686e --- /dev/null +++ b/contrib/amd/fsinfo/null_lex.c @@ -0,0 +1,1716 @@ + +#line 3 "lex.null_.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer null__create_buffer +#define yy_delete_buffer null__delete_buffer +#define yy_flex_debug null__flex_debug +#define yy_init_buffer null__init_buffer +#define yy_flush_buffer null__flush_buffer +#define yy_load_buffer_state null__load_buffer_state +#define yy_switch_to_buffer null__switch_to_buffer +#define yyin null_in +#define yyleng null_leng +#define yylex null_lex +#define yylineno null_lineno +#define yyout null_out +#define yyrestart null_restart +#define yytext null_text +#define yywrap null_wrap +#define yyalloc null_alloc +#define yyrealloc null_realloc +#define yyfree null_free + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE null_restart(null_in ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int null_leng; + +extern FILE *null_in, *null_out; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up null_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up null_text again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via null_restart()), so that the user can continue scanning by + * just pointing null_in at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when null_text is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int null_leng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow null_wrap()'s to do buffer switches + * instead of setting up a fresh null_in. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void null_restart (FILE *input_file ); +void null__switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE null__create_buffer (FILE *file,int size ); +void null__delete_buffer (YY_BUFFER_STATE b ); +void null__flush_buffer (YY_BUFFER_STATE b ); +void null_push_buffer_state (YY_BUFFER_STATE new_buffer ); +void null_pop_buffer_state (void ); + +static void null_ensure_buffer_stack (void ); +static void null__load_buffer_state (void ); +static void null__init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER null__flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE null__scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE null__scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE null__scan_bytes (yyconst char *bytes,int len ); + +void *null_alloc (yy_size_t ); +void *null_realloc (void *,yy_size_t ); +void null_free (void * ); + +#define yy_new_buffer null__create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + null_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + null__create_buffer(null_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + null_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + null__create_buffer(null_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +typedef unsigned char YY_CHAR; + +FILE *null_in = (FILE *) 0, *null_out = (FILE *) 0; + +typedef int yy_state_type; + +extern int null_lineno; + +int null_lineno = 1; + +extern char *null_text; +#define yytext_ptr null_text + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up null_text. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + null_leng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 1 +#define YY_END_OF_BUFFER 2 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[6] = + { 0, + 0, 0, 2, 1, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[2] = + { 0, + 1 + } ; + +static yyconst flex_int16_t yy_base[7] = + { 0, + 0, 0, 2, 3, 3, 0 + } ; + +static yyconst flex_int16_t yy_def[7] = + { 0, + 6, 6, 5, 5, 0, 5 + } ; + +static yyconst flex_int16_t yy_nxt[5] = + { 0, + 4, 5, 3, 5 + } ; + +static yyconst flex_int16_t yy_chk[5] = + { 0, + 6, 3, 5, 5 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int null__flex_debug; +int null__flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *null_text; +#line 1 "../../fsinfo/null_lex.l" +#line 2 "../../fsinfo/null_lex.l" +#include "null_gram.h" + +void null_error(const char *fmt, ...) {} +int null_wrap(void) { return 0; } +#define YY_NO_INPUT 1 +#line 481 "lex.null_.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int null_lex_destroy (void ); + +int null_get_debug (void ); + +void null_set_debug (int debug_flag ); + +YY_EXTRA_TYPE null_get_extra (void ); + +void null_set_extra (YY_EXTRA_TYPE user_defined ); + +FILE *null_get_in (void ); + +void null_set_in (FILE * in_str ); + +FILE *null_get_out (void ); + +void null_set_out (FILE * out_str ); + +int null_get_leng (void ); + +char *null_get_text (void ); + +int null_get_lineno (void ); + +void null_set_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int null_wrap (void ); +#else +extern int null_wrap (void ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( null_text, null_leng, 1, null_out )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( null_in )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( null_in ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, null_in))==0 && ferror(null_in)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(null_in); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int null_lex (void); + +#define YY_DECL int null_lex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after null_text and null_leng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 9 "../../fsinfo/null_lex.l" + +#line 668 "lex.null_.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! null_in ) + null_in = stdin; + + if ( ! null_out ) + null_out = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + null_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + null__create_buffer(null_in,YY_BUF_SIZE ); + } + + null__load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of null_text. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 6 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 3 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 10 "../../fsinfo/null_lex.l" +ECHO; + YY_BREAK +#line 756 "lex.null_.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed null_in at a new source and called + * null_lex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = null_in; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( null_wrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * null_text, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of null_lex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + null_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + null_restart(null_in ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) null_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 6 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 6 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 5); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + null_restart(null_in ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( null_wrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve null_text */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void null_restart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + null_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + null__create_buffer(null_in,YY_BUF_SIZE ); + } + + null__init_buffer(YY_CURRENT_BUFFER,input_file ); + null__load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void null__switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * null_pop_buffer_state(); + * null_push_buffer_state(new_buffer); + */ + null_ensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + null__load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (null_wrap()) processing, but the only time this flag + * is looked at is after null_wrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void null__load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + null_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE null__create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) null_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in null__create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) null_alloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in null__create_buffer()" ); + + b->yy_is_our_buffer = 1; + + null__init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with null__create_buffer() + * + */ + void null__delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + null_free((void *) b->yy_ch_buf ); + + null_free((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a null_restart() or at EOF. + */ + static void null__init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + null__flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then null__init_buffer was _probably_ + * called from null_restart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void null__flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + null__load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void null_push_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + null_ensure_buffer_stack(); + + /* This block is copied from null__switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from null__switch_to_buffer. */ + null__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void null_pop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + null__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + null__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void null_ensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)null_alloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in null_ensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)null_realloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in null_ensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE null__scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) null_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in null__scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + null__switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to null_lex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * null__scan_bytes() instead. + */ +YY_BUFFER_STATE null__scan_string (yyconst char * yystr ) +{ + + return null__scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to null_lex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE null__scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) null_alloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in null__scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = null__scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in null__scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up null_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + null_text[null_leng] = (yy_hold_char); \ + (yy_c_buf_p) = null_text + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + null_leng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int null_get_lineno (void) +{ + + return null_lineno; +} + +/** Get the input stream. + * + */ +FILE *null_get_in (void) +{ + return null_in; +} + +/** Get the output stream. + * + */ +FILE *null_get_out (void) +{ + return null_out; +} + +/** Get the length of the current token. + * + */ +int null_get_leng (void) +{ + return null_leng; +} + +/** Get the current token. + * + */ + +char *null_get_text (void) +{ + return null_text; +} + +/** Set the current line number. + * @param line_number + * + */ +void null_set_lineno (int line_number ) +{ + + null_lineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see null__switch_to_buffer + */ +void null_set_in (FILE * in_str ) +{ + null_in = in_str ; +} + +void null_set_out (FILE * out_str ) +{ + null_out = out_str ; +} + +int null_get_debug (void) +{ + return null__flex_debug; +} + +void null_set_debug (int bdebug ) +{ + null__flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from null_lex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + null_in = stdin; + null_out = stdout; +#else + null_in = (FILE *) 0; + null_out = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * null_lex_init() + */ + return 0; +} + +/* null_lex_destroy is for both reentrant and non-reentrant scanners. */ +int null_lex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + null__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + null_pop_buffer_state(); + } + + /* Destroy the stack itself. */ + null_free((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * null_lex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *null_alloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *null_realloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void null_free (void * ptr ) +{ + free( (char *) ptr ); /* see null_realloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 10 "../../fsinfo/null_lex.l" diff --git a/contrib/amd/fsinfo/null_lex.l b/contrib/amd/fsinfo/null_lex.l new file mode 100644 index 00000000000..46bb46381e4 --- /dev/null +++ b/contrib/amd/fsinfo/null_lex.l @@ -0,0 +1,9 @@ +%{ +#include "null_gram.h" + +void null_error(const char *fmt, ...) {} +int yywrap(void) { return 0; } +%} +%option nounput +%option noinput +%% diff --git a/contrib/amd/fsinfo/wr_atab.c b/contrib/amd/fsinfo/wr_atab.c index e02db07f05f..ac132aa76dc 100644 --- a/contrib/amd/fsinfo/wr_atab.c +++ b/contrib/amd/fsinfo/wr_atab.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/fsinfo/wr_bparam.c b/contrib/amd/fsinfo/wr_bparam.c index 9220762f2b1..00befa9cf58 100644 --- a/contrib/amd/fsinfo/wr_bparam.c +++ b/contrib/amd/fsinfo/wr_bparam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -56,7 +52,7 @@ static int write_nfsname(FILE *ef, fsmount *fp, char *hn) { int errors = 0; - char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname); + char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname); domain_strip(h, hn); fprintf(ef, "%s:%s", h, fp->f_volname); diff --git a/contrib/amd/fsinfo/wr_dumpset.c b/contrib/amd/fsinfo/wr_dumpset.c index 69c1257e265..916f95a5a23 100644 --- a/contrib/amd/fsinfo/wr_dumpset.c +++ b/contrib/amd/fsinfo/wr_dumpset.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/fsinfo/wr_exportfs.c b/contrib/amd/fsinfo/wr_exportfs.c index 818d893687c..c6e7936dd16 100644 --- a/contrib/amd/fsinfo/wr_exportfs.c +++ b/contrib/amd/fsinfo/wr_exportfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/fsinfo/wr_fstab.c b/contrib/amd/fsinfo/wr_fstab.c index 52cebbf27e1..166353eb00f 100644 --- a/contrib/amd/fsinfo/wr_fstab.c +++ b/contrib/amd/fsinfo/wr_fstab.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -89,7 +85,7 @@ static struct os_fstab_type { "u4_0", write_ultrix_dkfstab, write_ultrix_dkrmount }, /* Ultrix */ { - 0, 0, 0 + NULL, NULL, NULL } }; @@ -102,7 +98,7 @@ static struct os_fstab_type { static void write_aix1_dkfstab(FILE *ef, disk_fs *dp) { - char *hp = strdup(dp->d_host->h_hostname); + char *hp = xstrdup(dp->d_host->h_hostname); char *p = strchr(hp, '.'); if (p) @@ -123,8 +119,8 @@ write_aix1_dkfstab(FILE *ef, disk_fs *dp) static void write_aix1_dkrmount(FILE *ef, char *hn, fsmount *fp) { - char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname); - char *hp = strdup(h); + char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname); + char *hp = xstrdup(h); char *p = strchr(hp, '.'); if (p) @@ -172,7 +168,7 @@ write_aix3_dkfstab(FILE *ef, disk_fs *dp) static void write_aix3_dkrmount(FILE *ef, char *hn, fsmount *fp) { - char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname); + char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname); domain_strip(h, hn); fprintf(ef, "\n%s:\n\tdev = %s:%s\n\tvfs = %s\n\ttype = %s\n\tvol = %s\n\topts = %s\n\tmount = true\n\tcheck = true\n\tfree = false\n", @@ -206,7 +202,7 @@ write_ultrix_dkfstab(FILE *ef, disk_fs *dp) static void write_ultrix_dkrmount(FILE *ef, char *hn, fsmount *fp) { - char *h = strdup(fp->f_ref->m_dk->d_host->h_hostname); + char *h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname); domain_strip(h, hn); fprintf(ef, "%s@%s:%s:%s:%s:0:0\n", @@ -243,9 +239,9 @@ write_generic_dkrmount(FILE *ef, char *hn, fsmount *fp) char *h; if (fp->f_ref) { - h = strdup(fp->f_ref->m_dk->d_host->h_hostname); + h = xstrdup(fp->f_ref->m_dk->d_host->h_hostname); } else { - h = strdup(fp->f_from); + h = xstrdup(fp->f_from); } domain_strip(h, hn); fprintf(ef, "%s:%s %s %s %s 0 0\n", @@ -261,8 +257,8 @@ write_generic_dkrmount(FILE *ef, char *hn, fsmount *fp) static struct os_fstab_type * find_fstab_type(host *hp) { - struct os_fstab_type *op = 0; - char *os_name = 0; + struct os_fstab_type *op = NULL; + char *os_name = NULL; again:; if (os_name == 0) { diff --git a/contrib/amd/hlfsd/hlfsd.8 b/contrib/amd/hlfsd/hlfsd.8 index d0a04c1439e..1732a446d60 100644 --- a/contrib/amd/hlfsd/hlfsd.8 +++ b/contrib/amd/hlfsd/hlfsd.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1989 Jan-Simon Pendry .\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,9 +32,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: hlfsd.8,v 1.11.2.1 2006/01/02 18:48:25 ezk Exp $ .\" $FreeBSD$ .\" +.\" File: am-utils/hlfsd/hlfsd.8 +.\" .\" HLFSD was written at Columbia University Computer Science Department, by .\" Erez Zadok and Alexander Dupuy .\" It is distributed under the same terms and conditions as AMD. @@ -337,14 +334,16 @@ symbolic link returned by points if it is unable to verify the that user's home directory is accessible. .El -.Sh SEE ALSO -.Xr mail 1 , +.SH "SEE ALSO" +.Xr mail1 , .Xr getgrent 3 , .Xr getpwent 3 , +.Xr mnttab 4 , +.Xr passwd 4 , .Xr mtab 5 , -.Xr passwd 5 , .Xr amd 8 , -.Xr cron 8 , +.Xr automount 8 , +.Xr cron8 , .Xr mount 8 , .Xr sendmail 8 , .Xr umount 8 diff --git a/contrib/amd/hlfsd/hlfsd.c b/contrib/amd/hlfsd/hlfsd.c index 8703f5982c5..686bb63db23 100644 --- a/contrib/amd/hlfsd/hlfsd.c +++ b/contrib/amd/hlfsd/hlfsd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -82,7 +78,7 @@ char *alt_spooldir = ALT_SPOOLDIR; char *home_subdir = HOME_SUBDIR; char *logfile = DEFAULT_LOGFILE; char *passwdfile = NULL; /* alternate passwd file to use */ -char *slinkname = 0; +char *slinkname = NULL; char hostname[MAXHOSTNAMELEN + 1] = "localhost"; u_int cache_interval = DEFAULT_CACHE_INTERVAL; gid_t hlfs_gid = (gid_t) INVALIDID; @@ -102,6 +98,7 @@ char *mnttab_file_name = NULL; /* forward declarations */ void hlfsd_going_down(int rc); +void fatalerror(char *str); static void @@ -260,9 +257,6 @@ main(int argc, char *argv[]) opterrs++; } - /* set some default debugging options */ - if (xlog_level_init == ~0) - switch_option(""); /* need my pid before any dlog/plog */ am_set_mypid(); #ifdef DEBUG @@ -312,7 +306,11 @@ main(int argc, char *argv[]) } /* get hostname for logging and open log before we reset umask */ - gethostname(hostname, sizeof(hostname)); + if (gethostname(hostname, sizeof(hostname)) == -1) { + fprintf(stderr, "%s: gethostname failed \"%s\".\n", + am_get_progname(), strerror(errno)); + exit(1); + } hostname[sizeof(hostname) - 1] = '\0'; if ((dot = strchr(hostname, '.')) != NULL) *dot = '\0'; @@ -418,11 +416,8 @@ main(int argc, char *argv[]) /* * Register hlfsd as an nfs service with the portmapper. */ -#ifdef HAVE_TRANSPORT_TYPE_TLI - ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); -#else /* not HAVE_TRANSPORT_TYPE_TLI */ - ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ + ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2, + NFS_VERSION); if (ret != 0) fatal("cannot create NFS service"); @@ -450,10 +445,10 @@ main(int argc, char *argv[]) #endif /* not HAVE_SIGACTION */ /* - * In the parent, if -D daemon, we don't need to + * In the parent, if -D nodaemon, we don't need to * set this signal handler. */ - if (!amuDebug(D_DAEMON)) { + if (amuDebug(D_DAEMON)) { s = -99; while (stoplight != SIGUSR2) { plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight); @@ -628,10 +623,10 @@ main(int argc, char *argv[]) plog(XLOG_INFO, "hlfsd ready to serve"); /* - * If asked not to fork a daemon (-D daemon), then hlfsd_init() + * If asked not to fork a daemon (-D nodaemon), then hlfsd_init() * will not run svc_run. We must start svc_run here. */ - if (amuDebug(D_DAEMON)) { + if (!amuDebug(D_DAEMON)) { plog(XLOG_DEBUG, "starting no-daemon debugging svc_run"); svc_run(); } @@ -656,9 +651,9 @@ hlfsd_init(void) hlfsd_init_filehandles(); /* - * If not -D daemon then we must fork. + * If -D daemon then we must fork. */ - if (!amuDebug(D_DAEMON)) + if (amuDebug(D_DAEMON)) child = fork(); if (child < 0) @@ -745,17 +740,17 @@ hlfsd_init(void) # endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */ #endif /* not HAVE_SIGACTION */ - if (setitimer(ITIMER_REAL, &reloadinterval, (struct itimerval *) 0) < 0) + if (setitimer(ITIMER_REAL, &reloadinterval, (struct itimerval *) NULL) < 0) fatal("setitimer: %m"); clocktime(&startup); /* - * If not -D daemon, then start serving here in the child, - * and the parent will exit. But if -D daemon, then + * If -D daemon, then start serving here in the child, + * and the parent will exit. But if -D nodaemon, then * skip this code and make sure svc_run is entered elsewhere. */ - if (!amuDebug(D_DAEMON)) { + if (amuDebug(D_DAEMON)) { /* * Dissociate from the controlling terminal */ @@ -839,7 +834,7 @@ cleanup(int signum) struct stat stbuf; int umount_result; - if (!amuDebug(D_DAEMON)) { + if (amuDebug(D_DAEMON)) { if (getpid() != masterpid) return; @@ -865,7 +860,7 @@ cleanup(int signum) break; } - if (!amuDebug(D_DAEMON)) { + if (amuDebug(D_DAEMON)) { plog(XLOG_INFO, "cleanup(): killing processes and terminating"); kill(masterpid, SIGKILL); kill(serverpid, SIGKILL); diff --git a/contrib/amd/hlfsd/hlfsd.h b/contrib/amd/hlfsd/hlfsd.h index ed136b6f230..d5eefedfa61 100644 --- a/contrib/amd/hlfsd/hlfsd.h +++ b/contrib/amd/hlfsd/hlfsd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/hlfsd/homedir.c b/contrib/amd/hlfsd/homedir.c index d60c39f2c2c..462b42380ca 100644 --- a/contrib/amd/hlfsd/homedir.c +++ b/contrib/amd/hlfsd/homedir.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -133,9 +129,10 @@ homedir(int userid, int groupid) } /* - * only run this forking code if did not ask for -D fork + * Only run this forking code if ask for -D fork (default). + * Disable forking using -D nofork. */ - if (!amuDebug(D_FORK)) { + if (amuDebug(D_FORK)) { /* fork child to process request if none in progress */ if (found->child && kill(found->child, 0)) found->child = 0; @@ -265,13 +262,14 @@ delay(uid2home_t *found, int secs) { struct timeval tv; - dlog("delaying on child %ld for %d seconds", (long) found->child, secs); + if (found) + dlog("delaying on child %ld for %d seconds", (long) found->child, secs); tv.tv_usec = 0; do { tv.tv_sec = secs; - if (select(0, 0, 0, 0, &tv) == 0) + if (select(0, NULL, NULL, NULL, &tv) == 0) break; } while (--secs && found->child); } @@ -292,7 +290,7 @@ interlock(int signum) #ifdef HAVE_WAITPID while ((child = waitpid((pid_t) -1, &status, WNOHANG)) > 0) { #else /* not HAVE_WAITPID */ - while ((child = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0) { + while ((child = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) { #endif /* not HAVE_WAITPID */ /* high chances this was the last child forked */ @@ -560,7 +558,7 @@ plt_init(void) int len; if (root_home) XFREE(root_home); - root_home = strdup(pent_p->pw_dir); + root_home = xstrdup(pent_p->pw_dir); len = strlen(root_home); /* remove any trailing '/' chars from root's home (even if just one) */ while (len > 0 && root_home[len - 1] == '/') { @@ -577,7 +575,7 @@ plt_init(void) unt_compare_fxn); if (!root_home) - root_home = strdup(""); + root_home = xstrdup(""); plog(XLOG_INFO, "password map read and sorted"); } @@ -672,14 +670,14 @@ table_add(u_int u, const char *h, const char *n) } /* add new password entry */ - pwtab[cur_pwtab_num].home = strdup(h); + pwtab[cur_pwtab_num].home = xstrdup(h); pwtab[cur_pwtab_num].child = 0; pwtab[cur_pwtab_num].last_access_time = 0; pwtab[cur_pwtab_num].last_status = 0; /* assume best: used homedir */ pwtab[cur_pwtab_num].uid = u; /* add new userhome entry */ - untab[cur_pwtab_num].username = strdup(n); + untab[cur_pwtab_num].username = xstrdup(n); /* just a second pointer */ pwtab[cur_pwtab_num].uname = untab[cur_pwtab_num].username; diff --git a/contrib/amd/hlfsd/nfs_prot_svc.c b/contrib/amd/hlfsd/nfs_prot_svc.c index 8cea0dca700..babaa846a22 100644 --- a/contrib/amd/hlfsd/nfs_prot_svc.c +++ b/contrib/amd/hlfsd/nfs_prot_svc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/hlfsd/stubs.c b/contrib/amd/hlfsd/stubs.c index 3b31043efc2..b26e5f4dc63 100644 --- a/contrib/amd/hlfsd/stubs.c +++ b/contrib/amd/hlfsd/stubs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -137,7 +133,7 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) clocktime(&rootfattr.na_mtime); rootfattr.na_uid = uid; } -#endif +#endif /* 0 */ res.ns_status = NFS_OK; res.ns_u.ns_attr_u = rootfattr; } else if (eq_fh(argp, &slink)) { @@ -240,7 +236,7 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp) clocktime(&rootfattr.na_mtime); rootfattr.na_uid = uid; } -#endif +#endif /* 0 */ res.dr_u.dr_drok_u.drok_fhandle = root; res.dr_u.dr_drok_u.drok_attributes = rootfattr; res.dr_status = NFS_OK; @@ -306,7 +302,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) uid_t userid = (uid_t) INVALIDID; gid_t groupid = hlfs_gid + 1; /* anything not hlfs_gid */ int retval = 0; - char *path_val = (char *) NULL; + char *path_val = NULL; char *username; static uid_t last_uid = (uid_t) INVALIDID; @@ -327,7 +323,7 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) * processing, by getting a NULL returned as a * "special". Child returns result. */ - return (nfsreadlinkres *) NULL; + return NULL; } } else { /* check if asked for user mailbox */ @@ -373,14 +369,15 @@ nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) retval = 0; /* - * If asked for -D fork, then must return the value, + * If asked for -D nofork, then must return the value, * NOT exit, or else the main hlfsd server exits. + * If -D fork (default), then we do want to exit from the process. * Bug: where is that status information being collected? */ if (amuDebug(D_FORK)) + exit(retval); + else return &res; - - exit(retval); } @@ -478,7 +475,7 @@ nfsreaddirres * nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp) { static nfsreaddirres res; - static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}}; + static nfsentry slinkent = {SLINKID, NULL, {SLINKCOOKIE}}; static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent}; static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent}; @@ -501,7 +498,7 @@ nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp) res.rdr_u.rdr_reply_u.dl_entries = &slinkent; break; case SLINKCOOKIE: - res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0; + res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) NULL; break; } res.rdr_u.rdr_reply_u.dl_eof = TRUE; diff --git a/contrib/amd/include/am_compat.h b/contrib/amd/include/am_compat.h index dc3b71d7446..3463f3fa591 100644 --- a/contrib/amd/include/am_compat.h +++ b/contrib/amd/include/am_compat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -90,6 +86,10 @@ # define MNTTAB_OPT_NOAC "noac" #endif /* defined(MNT2_NFS_OPT_NOAC) && !defined(MNTTAB_OPT_NOAC) */ +#if defined(MNT2_NFS_OPT_NOACL) && !defined(MNTTAB_OPT_NOACL) +# define MNTTAB_OPT_NOACL "noacl" +#endif /* defined(MNT2_NFS_OPT_NOACL) && !defined(MNTTAB_OPT_NOACL) */ + #if defined(MNT2_NFS_OPT_NOCONN) && !defined(MNTTAB_OPT_NOCONN) # define MNTTAB_OPT_NOCONN "noconn" # ifndef MNTTAB_OPT_CONN @@ -176,10 +176,30 @@ #if defined(MNT2_CDFS_OPT_GENS) && !defined(MNTTAB_OPT_GENS) # define MNTTAB_OPT_GENS "gens" #endif /* defined(MNT2_CDFS_OPT_GENS) && !defined(MNTTAB_OPT_GENS) */ + #if defined(MNT2_CDFS_OPT_EXTATT) && !defined(MNTTAB_OPT_EXTATT) # define MNTTAB_OPT_EXTATT "extatt" #endif /* defined(MNT2_CDFS_OPT_EXTATT) && !defined(MNTTAB_OPT_EXTATT) */ +#if defined(MNT2_CDFS_OPT_NOJOLIET) && !defined(MNTTAB_OPT_NOJOLIET) +# define MNTTAB_OPT_NOJOLIET "nojoliet" +#endif /* defined(MNT2_CDFS_OPT_NOJOLIET) && !defined(MNTTAB_OPT_NOJOLIET) */ + +#if defined(MNT2_CDFS_OPT_NOCASETRANS) && !defined(MNTTAB_OPT_NOCASETRANS) +# define MNTTAB_OPT_NOCASETRANS "nocasetrans" +#endif /* defined(MNT2_CDFS_OPT_NOCASETRANS) && !defined(MNTTAB_OPT_NOCASETRANS) */ + +#if defined(MNT2_CDFS_OPT_RRCASEINS) && !defined(MNTTAB_OPT_RRCASEINS) +# define MNTTAB_OPT_RRCASEINS "rrcaseins" +#endif /* defined(MNT2_CDFS_OPT_RRCASEINS) && !defined(MNTTAB_OPT_RRCASEINS) */ + +/* + * Complete MNTTAB_OPT_* options based on MNT2_UDF_OPT_* mount options. + */ +#if defined(MNT2_UDF_OPT_CLOSESESSION) && !defined(MNTTAB_OPT_CLOSESESSION) +# define MNTTAB_OPT_CLOSESESSION "closesession" +#endif /* defined(MNT2_UDF_OPT_CLOSESESSION) && !defined(MNTTAB_OPT_CLOSESESSION) */ + /* * Complete MNTTAB_OPT_* options based on MNT2_PCFS_OPT_* mount options. */ @@ -236,6 +256,29 @@ # define MNTTAB_OPT_SYNC "sync" #endif /* defined(MNT2_GEN_OPT_SYNC) && !defined(MNTTAB_OPT_SYNC) */ +#if defined(MNT2_GEN_OPT_LOG) && !defined(MNTTAB_OPT_LOG) +# define MNTTAB_OPT_LOG "log" +#endif /* defined(MNT2_GEN_OPT_LOG) && !defined(MNTTAB_OPT_LOG) */ + +#if defined(MNT2_GEN_OPT_NOATIME) && !defined(MNTTAB_OPT_NOATIME) +# define MNTTAB_OPT_NOATIME "noatime" +#endif /* defined(MNT2_GEN_OPT_NOATIME) && !defined(MNTTAB_OPT_NOATIME) */ + +#if defined(MNT2_GEN_OPT_NODEVMTIME) && !defined(MNTTAB_OPT_NODEVMTIME) +# define MNTTAB_OPT_NODEVMTIME "nodevmtime" +#endif /* defined(MNT2_GEN_OPT_NODEVMTIME) && !defined(MNTTAB_OPT_NODEVMTIME) */ + +#if defined(MNT2_GEN_OPT_SOFTDEP) && !defined(MNTTAB_OPT_SOFTDEP) +# define MNTTAB_OPT_SOFTDEP "softdep" +#endif /* defined(MNT2_GEN_OPT_SOFTDEP) && !defined(MNTTAB_OPT_SOFTDEP) */ + +#if defined(MNT2_GEN_OPT_SYMPERM) && !defined(MNTTAB_OPT_SYMPERM) +# define MNTTAB_OPT_SYMPERM "symperm" +#endif /* defined(MNT2_GEN_OPT_SYMPERM) && !defined(MNTTAB_OPT_SYMPERM) */ + +#if defined(MNT2_GEN_OPT_UNION) && !defined(MNTTAB_OPT_UNION) +# define MNTTAB_OPT_UNION "union" +#endif /* defined(MNT2_GEN_OPT_UNION) && !defined(MNTTAB_OPT_UNION) */ /* * Add missing MNTTAB_OPT_* options. @@ -298,6 +341,20 @@ # define MNTTAB_OPT_DIRMASK "dirmask" #endif /* not MNTTAB_OPT_DIRMASK */ +/* useful for udf mounts */ +#ifndef MNTTAB_OPT_USER +# define MNTTAB_OPT_USER "user" +#endif /* not MNTTAB_OPT_USER */ +#ifndef MNTTAB_OPT_GROUP +# define MNTTAB_OPT_GROUP "group" +#endif /* not MNTTAB_OPT_GROUP */ +#ifndef MNTTAB_OPT_GMTOFF +# define MNTTAB_OPT_GMTOFF "gmtoff" +#endif /* not MNTTAB_OPT_GMTOFF */ +#ifndef MNTTAB_OPT_SESSIONNR +# define MNTTAB_OPT_SESSIONNR "sessionnr" +#endif /* not MNTTAB_OPT_SESSIONNR */ + /* * Incomplete filesystem definitions (sunos4, irix6, solaris2) */ @@ -334,6 +391,13 @@ struct hsfs_args { # define ufs_args_t u_int #endif /* defined(HAVE_FS_UFS) && !defined(ufs_args_t) */ +/* + * if does not define struct udf_args, assume integer bit-field (linux) + */ +#if defined(HAVE_FS_UDF) && !defined(udf_args_t) +# define udf_args_t u_int +#endif /* defined(HAVE_FS_UDF) && !defined(udf_args_t) */ + /* * if does not define struct efs_args, assume integer bit-field (linux) */ @@ -341,12 +405,19 @@ struct hsfs_args { # define efs_args_t u_int #endif /* defined(HAVE_FS_EFS) && !defined(efs_args_t) */ +#if defined(HAVE_FS_TMPFS) && !defined(tmpfs_args_t) +# define tmpfs_args_t u_int +#endif /* defined(HAVE_FS_TMPFS) && !defined(tmpfs_args_t) */ + /* * if does not define struct xfs_args, assume integer bit-field (linux) */ #if defined(HAVE_FS_XFS) && !defined(xfs_args_t) # define xfs_args_t u_int #endif /* defined(HAVE_FS_XFS) && !defined(xfs_args_t) */ +#if defined(HAVE_FS_EXT) && !defined(ext_args_t) +# define ext_args_t u_int +#endif /* defined(HAVE_FS_EXT) && !defined(ext_args_t) */ #if defined(HAVE_FS_AUTOFS) && defined(MOUNT_TYPE_AUTOFS) && !defined(MNTTYPE_AUTOFS) # define MNTTYPE_AUTOFS "autofs" @@ -365,6 +436,14 @@ struct hsfs_args { # endif /* not MNTTAB_OPT_PROTO */ #endif /* not HAVE_FS_NFS3 */ +/* + * If NFS4, then make sure that the "sec" mnttab option is available. + */ +#ifdef HAVE_FS_NFS4 +# ifndef MNTTAB_OPT_SEC +# define MNTTAB_OPT_SEC "sec" +# endif /* not MNTTAB_OPT_SEC */ +#endif /* not HAVE_FS_NFS4 */ /* * If loop device (header file) exists, define mount table option */ diff --git a/contrib/amd/include/am_defs.h b/contrib/amd/include/am_defs.h index f3767f5b905..bb867a49b5a 100644 --- a/contrib/amd/include/am_defs.h +++ b/contrib/amd/include/am_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -67,7 +63,7 @@ # define strchr index # define strrchr rindex # endif /* not HAVE_STRCHR */ -char *strchr(), *strrchr(), *strdup(); +char *strchr(), *strrchr(); #endif /* not STDC_HEADERS */ /* @@ -88,6 +84,14 @@ char *strchr(), *strrchr(), *strdup(); # endif /* __GNUC__ < 2 ... */ #endif /* not __attribute__ */ +#define __IGNORE(result) \ + __ignore((unsigned long)result) + +static inline void +__ignore(unsigned long result) { + (void)&result; +} + /* * How to handle signals of any type */ @@ -134,11 +138,19 @@ struct sigevent; /* * Big-endian or little-endian? */ -#ifdef WORDS_BIGENDIAN -# define ARCH_ENDIAN "big" -#else /* not WORDS_BIGENDIAN */ -# define ARCH_ENDIAN "little" -#endif /* not WORDS_BIGENDIAN */ +#ifndef BYTE_ORDER +# if defined(WORDS_BIGENDIAN) +# define ARCH_ENDIAN "big" +# else /* not WORDS_BIGENDIAN */ +# define ARCH_ENDIAN "little" +# endif /* not WORDS_BIGENDIAN */ +#else +# if BYTE_ORDER == BIG_ENDIAN +# define ARCH_ENDIAN "big" +# else +# define ARCH_ENDIAN "little" +# endif +#endif /* * Actions to take if HAVE_SYS_TYPES_H is defined. @@ -209,12 +221,6 @@ struct sigevent; * Actions to take if HAVE_FCNTL_H is defined. */ #if HAVE_FCNTL_H -# ifdef HAVE_LINUX_LOOP_H -/* so I can mount large files as loop devices */ -/* XXX: need to move these two LARGEFILE defines to a better place */ -# define _LARGEFILE64_SOURCE -# define __USE_LARGEFILE64 -# endif /* HAVE_LINUX_LOOP_H */ # include #endif /* HAVE_FCNTL_H */ @@ -317,14 +323,6 @@ typedef bool_t (*xdrproc_t) __P ((XDR *, __ptr_t, ...)); # include #endif /* HAVE_MNTENT_H */ -/* - * Actions to take if exists. - */ -#ifdef HAVE_SYS_ERRNO_H -# include -extern int errno; -#endif /* HAVE_SYS_ERRNO_H */ - /* * Actions to take if exists. */ @@ -864,6 +862,10 @@ struct sockaddr_dl; #ifdef HAVE_SYS_FS_TMP_H # include #endif /* HAVE_SYS_FS_TMP_H */ +#ifdef HAVE_FS_TMPFS_TMPFS_ARGS_H +# include +#endif /* HAVE_FS_TMPFS_TMPFS_ARGS_H */ + /* * Actions to take if exists. @@ -886,6 +888,9 @@ struct sockaddr_dl; #ifdef HAVE_SYS_FS_EFS_CLNT_H # include #endif /* HAVE_SYS_FS_EFS_CLNT_H */ +#ifdef HAVE_FS_EFS_EFS_MOUNT_H +# include +#endif /* HAVE_FS_EFS_EFS_MOUNT_H */ /* * Actions to take if exists. @@ -927,6 +932,14 @@ struct sockaddr_dl; */ #ifdef HAVE_ERRNO_H # include +#else +/* + * Actions to take if exists. + */ +# ifdef HAVE_SYS_ERRNO_H +# include +extern int errno; +# endif /* HAVE_SYS_ERRNO_H */ #endif /* HAVE_ERRNO_H */ /* @@ -957,6 +970,13 @@ struct sockaddr_dl; # include #endif /* HAVE_ISOFS_CD9660_CD9660_MOUNT_H */ +/* + * Actions to take if exists. + */ +#ifdef HAVE_FS_UDF_UDF_MOUNT_H +# include +#endif /* HAVE_FS_UDF_UDF_MOUNT_H */ + /* * Actions to take if exists. */ @@ -1517,14 +1537,6 @@ extern unsigned int sleep(unsigned int seconds); extern int strcasecmp(const char *s1, const char *s2); #endif /* not HAVE_EXTERN_STRCASECMP */ -#ifndef HAVE_EXTERN_STRDUP -/* - * define this extern even if function does not exist, for it will - * be filled in by libamu/strdup.c - */ -extern char *strdup(const char *s); -#endif /* not HAVE_EXTERN_STRDUP */ - #ifndef HAVE_EXTERN_STRLCAT /* * define this extern even if function does not exist, for it will diff --git a/contrib/amd/include/am_utils.h b/contrib/amd/include/am_utils.h index b7e55ce33e2..0de881ad8c8 100644 --- a/contrib/amd/include/am_utils.h +++ b/contrib/amd/include/am_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -109,8 +105,14 @@ #define XLOG_DEBUG 0x0020 #define XLOG_MAP 0x0040 #define XLOG_STATS 0x0080 -#define XLOG_DEFSTR "all,nomap,nostats" /* Default log options */ +/* log option compositions */ +#define XLOG_MASK 0x00ff /* mask for all flags */ +#define XLOG_MANDATORY (XLOG_FATAL|XLOG_ERROR) /* cannot turn these off */ #define XLOG_ALL (XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS) +/* default: fatal + error + user + warning + info */ +#define XLOG_DEFAULT (XLOG_MASK & (XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS)) + +/* default: no logging options */ #define NO_SUBNET "notknown" /* default subnet name for no subnet */ #define NEXP_AP (1022) /* gdmr: was 254 */ @@ -258,8 +260,6 @@ extern pid_t am_mypid; extern int foreground; /* Foreground process */ extern int orig_umask; /* umask() on startup */ -extern int xlog_level; /* Logging level */ -extern int xlog_level_init; extern serv_state amd_state; /* Should we go now */ extern struct in_addr myipaddr; /* (An) IP address of this host */ extern struct opt_tab xlog_opt[]; @@ -278,15 +278,17 @@ extern char *get_version_string(void); extern char *inet_dquad(char *, size_t, u_long); extern char *print_wires(void); extern char *str3cat(char *, char *, char *, char *); +extern char *strvcat(const char *, ...); extern char *strealloc(char *, char *); extern char *strip_selectors(char *, char *); extern char *strnsave(const char *, int); extern int amu_close(int fd); extern int bind_resv_port(int, u_short *); -extern int cmdoption(char *, struct opt_tab *, int *); +extern int cmdoption(char *, struct opt_tab *, u_int *); extern int compute_automounter_mount_flags(mntent_t *); extern int compute_mount_flags(mntent_t *); -extern int get_amd_program_number(void); +extern void discard_nfs_args(void *, u_long); +extern u_long get_amd_program_number(void); extern int getcreds(struct svc_req *, uid_t *, gid_t *, SVCXPRT *); extern int hasmntval(mntent_t *, char *); extern unsigned int hasmntvalerr(mntent_t *, char *, int *); @@ -300,6 +302,9 @@ extern int make_rpc_packet(char *, int, u_long, struct rpc_msg *, voidp, XDRPROC extern int mkdirs(char *, int); extern int mount_fs(mntent_t *, int, caddr_t, int, MTYPE_TYPE, u_long, const char *, const char *, int); extern void nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp); +extern void nfs_program_3(struct svc_req *rqstp, SVCXPRT *transp); +#define get_nfs_dispatcher_version(a) \ + ((a) == nfs_program_2 ? NFS_VERSION : NFS_VERSION3) extern int pickup_rpc_reply(voidp, int, voidp, XDRPROC_T_TYPE); extern int switch_option(char *); extern int switch_to_logfile(char *logfile, int orig_umask, int truncate_log); @@ -320,14 +325,16 @@ extern void plog(int, const char *,...) __attribute__ ((__format__ (__printf__, 2, 3))); extern void rmdirs(char *); extern void rpc_msg_init(struct rpc_msg *, u_long, u_long, u_long); -extern void set_amd_program_number(int program); +extern void set_amd_program_number(u_long program); extern void show_opts(int ch, struct opt_tab *); extern void unregister_amq(void); extern voidp xmalloc(int); extern voidp xrealloc(voidp, int); extern voidp xzalloc(int); +extern char *xstrdup(const char *); extern int check_pmap_up(char *host, struct sockaddr_in* sin); -extern u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto); +extern u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto, u_long def); +extern int nfs_valid_version(u_long vers); extern long get_server_pid(void); extern void setup_sighandler(int signum, void (*handler)(int)); extern time_t clocktime(nfstime *nt); @@ -367,9 +374,10 @@ extern void write_mntent(mntent_t *, const char *); extern int syslogging; #endif /* defined(HAVE_SYSLOG_H) || defined(HAVE_SYS_SYSLOG_H) */ -extern void compute_nfs_args(nfs_args_t *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name); +extern void compute_nfs_args(void *nap, mntent_t *mntp, int genflags, struct netconfig *nfsncp, struct sockaddr_in *ip_addr, u_long nfs_version, char *nfs_proto, am_nfs_handle_t *fhp, char *host_name, char *fs_name); +extern void destroy_nfs_args(void *nap, u_long nfs_version); extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port); -extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp)); +extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version); extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *); #ifdef HAVE_TRANSPORT_TYPE_TLI @@ -392,8 +400,14 @@ extern int unregister_autofs_service(char *autofs_conftype); /* - * Network File System: the new generation - * NFS V.3 + * Network File System: the old faithful generation NFS V.2 + */ +#ifndef NFS_VERSION2 +# define NFS_VERSION2 ((u_int) 2) +#endif /* not NFS_VERSION2 */ + +/* + * Network File System: the not so new anymore generation NFS V.3 */ #ifdef HAVE_FS_NFS3 # ifndef NFS_VERSION3 @@ -401,6 +415,14 @@ extern int unregister_autofs_service(char *autofs_conftype); # endif /* not NFS_VERSION3 */ #endif /* HAVE_FS_NFS3 */ +/* + * Network File System: the new generation NFS V.4 + */ +#ifdef HAVE_FS_NFS4 +# ifndef NFS_VERSION4 +# define NFS_VERSION4 ((u_int) 4) +# endif /* not NFS_VERSION4 */ +#endif /* HAVE_FS_NFS4 */ /**************************************************************************/ /*** DEBUGGING ***/ @@ -412,30 +434,32 @@ extern int unregister_autofs_service(char *autofs_conftype); #ifdef DEBUG -# define D_ALL (~(D_MTAB|D_HRTIME|D_XDRTRACE|D_DAEMON|D_FORK|D_AMQ)) -# define D_DAEMON 0x0001 /* Don't enter daemon mode */ +# define D_DAEMON 0x0001 /* Enter daemon mode */ # define D_TRACE 0x0002 /* Do protocol trace */ # define D_FULL 0x0004 /* Do full trace */ # define D_MTAB 0x0008 /* Use local mtab */ -# define D_AMQ 0x0010 /* Don't register amq program */ +# define D_AMQ 0x0010 /* Register amq program */ # define D_STR 0x0020 /* Debug string munging */ # ifdef DEBUG_MEM # define D_MEM 0x0040 /* Trace memory allocations */ # else /* not DEBUG_MEM */ # define D_MEM 0x0000 /* Dummy */ # endif /* not DEBUG_MEM */ -# define D_FORK 0x0080 /* Don't fork server */ - /* info service specific debugging (hesiod, nis, etc) */ -# define D_INFO 0x0100 +# define D_FORK 0x0080 /* Fork server (hlfsd only) */ +# define D_INFO 0x0100 /* info service specific debugging (hesiod, nis, etc) */ # define D_HRTIME 0x0200 /* Print high resolution time stamps */ # define D_XDRTRACE 0x0400 /* Trace xdr routines */ # define D_READDIR 0x0800 /* Show browsable_dir progress */ - -/* - * Test mode is test mode: don't daemonize, don't register amq, don't fork, - * don't touch system mtab, etc. - */ -# define D_TEST (~(D_MEM|D_STR|D_XDRTRACE)) +/* debug option compositions */ +# define D_MASK 0x0fff /* mask of known flags */ +# define D_BASIC (D_TRACE|D_FULL|D_STR|D_MEM|D_INFO|D_XDRTRACE|D_READDIR) +# define D_CONTROL (D_DAEMON|D_AMQ|D_FORK) +/* immutable flags: cannot be changed via "amq -D" */ +# define D_IMMUTABLE (D_MTAB | D_CONTROL) +# define D_ALL (D_BASIC | D_CONTROL) +# define D_DEFAULT (D_MASK & D_ALL & ~D_XDRTRACE) +/* test mode: nodaemon, noamq, nofork, (local) mtab */ +# define D_TEST (D_BASIC | D_MTAB) # define amuDebug(x) (debug_flags & (x)) # define dlog if (amuDebug(D_FULL)) dplog @@ -460,34 +484,49 @@ extern void malloc_verify(void); # endif /* not DEBUG_MEM */ /* functions that depend solely on debugging */ -extern void print_nfs_args(const nfs_args_t *nap, u_long nfs_version); +extern void print_nfs_args(const void *, u_long nfs_version); extern int debug_option (char *opt); extern void dplog(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))); #else /* not DEBUG */ +/* set dummy flags to zero */ +# define D_DAEMON 0x0001 /* Enter daemon mode */ +# define D_TRACE 0x0000 /* dummy: Do protocol trace */ +# define D_FULL 0x0000 /* dummy: Do full trace */ +# define D_MTAB 0x0000 /* dummy: Use local mtab */ +# define D_AMQ 0x0010 /* Register amq program */ +# define D_STR 0x0000 /* dummy: Debug string munging */ +# define D_MEM 0x0000 /* dummy: Trace memory allocations */ +# define D_FORK 0x0080 /* Fork server (hlfsd only) */ +# define D_INFO 0x0000 /* dummy: info service debugging */ +# define D_HRTIME 0x0000 /* dummy: hi-res time stamps */ +# define D_XDRTRACE 0x0000 /* dummy: Trace xdr routines */ +# define D_READDIR 0x0000 /* dummy: browsable_dir progress */ +# define D_CONTROL (D_DAEMON|D_AMQ|D_FORK) +# define amuDebug(x) (debug_flags & (x)) /* * If not debugging, then also reset the pointer. * It's safer -- and besides, free() should do that anyway. */ -# define XFREE(x) do { free((voidp)x); x = NULL;} while (0) +# define XFREE(x) do { free((voidp)x); x = NULL;} while (0) -#define amuDebug(x) (0) - -#ifdef __GNUC__ -#define dlog(fmt...) -#else /* not __GNUC__ */ +# if defined(HAVE_GCC_VARARGS_MACROS) +# define dlog(fmt...) +# elif defined(HAVE_C99_VARARGS_MACROS) +# define dlog(...) +# else /* no c99 varargs */ /* this define means that we CCP leaves code behind the (list,of,args) */ -#define dlog -#endif /* not __GNUC__ */ +# define dlog +# endif /* no c99 varargs */ -#define print_nfs_args(nap, nfs_version) -#define debug_option(x) (1) +# define print_nfs_args(nap, nfs_version) +# define debug_option(x) (1) #endif /* not DEBUG */ -extern int debug_flags; /* Debug options */ +extern u_int debug_flags; /* Debug options */ extern struct opt_tab dbg_opt[]; /**************************************************************************/ diff --git a/contrib/amd/include/am_xdr_func.h b/contrib/amd/include/am_xdr_func.h index c4159188c79..3659942ecb6 100644 --- a/contrib/amd/include/am_xdr_func.h +++ b/contrib/amd/include/am_xdr_func.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -43,8 +39,26 @@ #ifdef HAVE_FS_NFS3 +#define AM_MOUNTVERS3 ((unsigned long)(3)) + #define AM_FHSIZE3 64 /* size in bytes of a file handle (v3) */ -#define AM_MOUNTVERS3 ((unsigned long)(3)) +#define AM_NFS3_WRITEVERFSIZE 8 +#define AM_NFS3_CREATEVERFSIZE 8 +#define AM_NFS3_COOKIEVERFSIZE 8 +#define AM_ACCESS3_READ 0x0001 +#define AM_ACCESS3_LOOKUP 0x0002 +#define AM_ACCESS3_MODIFY 0x0004 +#define AM_ACCESS3_EXTEND 0x0008 +#define AM_ACCESS3_DELETE 0x0010 +#define AM_ACCESS3_EXECUTE 0x0020 +#define AM_FSF3_LINK 0x0001 +#define AM_FSF3_SYMLINK 0x0002 +#define AM_FSF3_HOMOGENEOUS 0x0008 +#define AM_FSF3_CANSETTIME 0x0010 + +typedef char am_cookieverf3[AM_NFS3_COOKIEVERFSIZE]; + +typedef uint64 am_cookie3; /* NFSv3 handle */ struct am_nfs_fh3 { @@ -131,37 +145,830 @@ struct am_diropargs3 { }; typedef struct am_diropargs3 am_diropargs3; +enum am_ftype3 { + AM_NF3REG = 1, + AM_NF3DIR = 2, + AM_NF3BLK = 3, + AM_NF3CHR = 4, + AM_NF3LNK = 5, + AM_NF3SOCK = 6, + AM_NF3FIFO = 7, +}; +typedef enum am_ftype3 am_ftype3; + +typedef u_int am_mode3; + +typedef u_int am_uid3; + +typedef u_int am_gid3; + +typedef uint64 am_size3; + +typedef uint64 am_fileid3; + +struct am_specdata3 { + u_int specdata1; + u_int specdata2; +}; +typedef struct am_specdata3 am_specdata3; + +struct am_nfstime3 { + u_int seconds; + u_int nseconds; +}; +typedef struct am_nfstime3 am_nfstime3; + +struct am_fattr3 { + am_ftype3 type; + am_mode3 mode; + u_int nlink; + am_uid3 uid; + am_gid3 gid; + am_size3 size; + am_size3 used; + am_specdata3 rdev; + uint64 fsid; + am_fileid3 fileid; + am_nfstime3 atime; + am_nfstime3 mtime; + am_nfstime3 ctime; +}; +typedef struct am_fattr3 am_fattr3; + +struct am_post_op_attr { + bool_t attributes_follow; + union { + am_fattr3 attributes; + } am_post_op_attr_u; +}; +typedef struct am_post_op_attr am_post_op_attr; + +enum am_stable_how { + AM_UNSTABLE = 0, + AM_DATA_SYNC = 1, + AM_FILE_SYNC = 2, +}; +typedef enum am_stable_how am_stable_how; + +typedef uint64 am_offset3; + +typedef u_int am_count3; + +struct am_wcc_attr { + am_size3 size; + am_nfstime3 mtime; + am_nfstime3 ctime; +}; +typedef struct am_wcc_attr am_wcc_attr; + +struct am_pre_op_attr { + bool_t attributes_follow; + union { + am_wcc_attr attributes; + } am_pre_op_attr_u; +}; +typedef struct am_pre_op_attr am_pre_op_attr; + +struct am_wcc_data { + am_pre_op_attr before; + am_post_op_attr after; +}; +typedef struct am_wcc_data am_wcc_data; + +struct am_WRITE3args { + am_nfs_fh3 file; + am_offset3 offset; + am_count3 count; + am_stable_how stable; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct am_WRITE3args am_WRITE3args; + +typedef char am_writeverf3[AM_NFS3_WRITEVERFSIZE]; + +struct am_WRITE3resok { + am_wcc_data file_wcc; + am_count3 count; + am_stable_how committed; + am_writeverf3 verf; +}; +typedef struct am_WRITE3resok am_WRITE3resok; + +struct am_WRITE3resfail { + am_wcc_data file_wcc; +}; +typedef struct am_WRITE3resfail am_WRITE3resfail; + +struct am_WRITE3res { + am_nfsstat3 status; + union { + am_WRITE3resok ok; + am_WRITE3resfail fail; + } res_u; +}; +typedef struct am_WRITE3res am_WRITE3res; + struct am_LOOKUP3args { - am_diropargs3 what; + am_diropargs3 what; }; typedef struct am_LOOKUP3args am_LOOKUP3args; struct am_LOOKUP3resok { - am_nfs_fh3 object; -#if 0 - post_op_attr obj_attributes; - post_op_attr dir_attributes; -#endif + am_nfs_fh3 object; + am_post_op_attr obj_attributes; + am_post_op_attr dir_attributes; }; typedef struct am_LOOKUP3resok am_LOOKUP3resok; struct am_LOOKUP3resfail { -#if 0 - post_op_attr dir_attributes; -#else - char dummy; /* cannot have an empty declaration */ -#endif + am_post_op_attr dir_attributes; }; typedef struct am_LOOKUP3resfail am_LOOKUP3resfail; struct am_LOOKUP3res { - am_nfsstat3 status; - union { - am_LOOKUP3resok ok; - am_LOOKUP3resfail fail; - } res_u; + am_nfsstat3 status; + union { + am_LOOKUP3resok ok; + am_LOOKUP3resfail fail; + } res_u; }; typedef struct am_LOOKUP3res am_LOOKUP3res; + +struct am_COMMIT3args { + am_nfs_fh3 file; + am_offset3 offset; + am_count3 count; +}; +typedef struct am_COMMIT3args am_COMMIT3args; + +struct am_COMMIT3resok { + am_wcc_data file_wcc; + am_writeverf3 verf; +}; +typedef struct am_COMMIT3resok am_COMMIT3resok; + +struct am_COMMIT3resfail { + am_wcc_data file_wcc; +}; +typedef struct am_COMMIT3resfail am_COMMIT3resfail; + +struct am_COMMIT3res { + am_nfsstat3 status; + union { + am_COMMIT3resok ok; + am_COMMIT3resfail fail; + } res_u; +}; +typedef struct am_COMMIT3res am_COMMIT3res; + +struct am_ACCESS3args { + am_nfs_fh3 object; + u_int access; +}; +typedef struct am_ACCESS3args am_ACCESS3args; + +struct am_ACCESS3resok { + am_post_op_attr obj_attributes; + u_int access; +}; +typedef struct am_ACCESS3resok am_ACCESS3resok; + +struct am_ACCESS3resfail { + am_post_op_attr obj_attributes; +}; +typedef struct am_ACCESS3resfail am_ACCESS3resfail; + +struct am_ACCESS3res { + am_nfsstat3 status; + union { + am_ACCESS3resok ok; + am_ACCESS3resfail fail; + } res_u; +}; +typedef struct am_ACCESS3res am_ACCESS3res; + +struct am_GETATTR3args { + am_nfs_fh3 object; +}; +typedef struct am_GETATTR3args am_GETATTR3args; + +struct am_GETATTR3resok { + am_fattr3 obj_attributes; +}; +typedef struct am_GETATTR3resok am_GETATTR3resok; + +struct am_GETATTR3res { + am_nfsstat3 status; + union { + am_GETATTR3resok ok; + } res_u; +}; +typedef struct am_GETATTR3res am_GETATTR3res; + +enum am_time_how { + AM_DONT_CHANGE = 0, + AM_SET_TO_SERVER_TIME = 1, + AM_SET_TO_CLIENT_TIME = 2, +}; +typedef enum am_time_how am_time_how; + +struct am_set_mode3 { + bool_t set_it; + union { + am_mode3 mode; + } am_set_mode3_u; +}; +typedef struct am_set_mode3 am_set_mode3; + +struct am_set_uid3 { + bool_t set_it; + union { + am_uid3 uid; + } am_set_uid3_u; +}; +typedef struct am_set_uid3 am_set_uid3; + +struct am_set_gid3 { + bool_t set_it; + union { + am_gid3 gid; + } am_set_gid3_u; +}; +typedef struct am_set_gid3 am_set_gid3; + +struct am_set_size3 { + bool_t set_it; + union { + am_size3 size; + } am_set_size3_u; +}; +typedef struct am_set_size3 am_set_size3; + +struct am_set_atime { + am_time_how set_it; + union { + am_nfstime3 atime; + } am_set_atime_u; +}; +typedef struct am_set_atime am_set_atime; + +struct am_set_mtime { + am_time_how set_it; + union { + am_nfstime3 mtime; + } am_set_mtime_u; +}; +typedef struct am_set_mtime am_set_mtime; + +struct am_sattr3 { + am_set_mode3 mode; + am_set_uid3 uid; + am_set_gid3 gid; + am_set_size3 size; + am_set_atime atime; + am_set_mtime mtime; +}; +typedef struct am_sattr3 am_sattr3; + +enum am_createmode3 { + AM_UNCHECKED = 0, + AM_GUARDED = 1, + AM_EXCLUSIVE = 2, +}; +typedef enum am_createmode3 am_createmode3; + +typedef char am_createverf3[AM_NFS3_CREATEVERFSIZE]; + +struct am_createhow3 { + am_createmode3 mode; + union { + am_sattr3 obj_attributes; + am_sattr3 g_obj_attributes; + am_createverf3 verf; + } am_createhow3_u; +}; +typedef struct am_createhow3 am_createhow3; + +struct am_CREATE3args { + am_diropargs3 where; + am_createhow3 how; +}; +typedef struct am_CREATE3args am_CREATE3args; + +struct am_post_op_fh3 { + bool_t handle_follows; + union { + am_nfs_fh3 handle; + } am_post_op_fh3_u; +}; +typedef struct am_post_op_fh3 am_post_op_fh3; + +struct am_CREATE3resok { + am_post_op_fh3 obj; + am_post_op_attr obj_attributes; + am_wcc_data dir_wcc; +}; +typedef struct am_CREATE3resok am_CREATE3resok; + +struct am_CREATE3resfail { + am_wcc_data dir_wcc; +}; +typedef struct am_CREATE3resfail am_CREATE3resfail; + +struct am_CREATE3res { + am_nfsstat3 status; + union { + am_CREATE3resok ok; + am_CREATE3resfail fail; + } res_u; +}; +typedef struct am_CREATE3res am_CREATE3res; + +struct am_REMOVE3args { + am_diropargs3 object; +}; +typedef struct am_REMOVE3args am_REMOVE3args; + +struct am_REMOVE3resok { + am_wcc_data dir_wcc; +}; +typedef struct am_REMOVE3resok am_REMOVE3resok; + +struct am_REMOVE3resfail { + am_wcc_data dir_wcc; +}; +typedef struct am_REMOVE3resfail am_REMOVE3resfail; + +struct am_REMOVE3res { + am_nfsstat3 status; + union { + am_REMOVE3resok ok; + am_REMOVE3resfail fail; + } res_u; +}; +typedef struct am_REMOVE3res am_REMOVE3res; + +struct am_READ3args { + am_nfs_fh3 file; + am_offset3 offset; + am_count3 count; +}; +typedef struct am_READ3args am_READ3args; + +struct am_READ3resok { + am_post_op_attr file_attributes; + am_count3 count; + bool_t eof; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct am_READ3resok am_READ3resok; + +struct am_READ3resfail { + am_post_op_attr file_attributes; +}; +typedef struct am_READ3resfail am_READ3resfail; + +struct am_READ3res { + am_nfsstat3 status; + union { + am_READ3resok ok; + am_READ3resfail fail; + } res_u; +}; +typedef struct am_READ3res am_READ3res; + +struct am_FSINFO3args { + am_nfs_fh3 fsroot; +}; +typedef struct am_FSINFO3args am_FSINFO3args; + +struct am_FSINFO3resok { + am_post_op_attr obj_attributes; + u_int rtmax; + u_int rtpref; + u_int rtmult; + u_int wtmax; + u_int wtpref; + u_int wtmult; + u_int dtpref; + am_size3 maxfilesize; + am_nfstime3 time_delta; + u_int properties; +}; +typedef struct am_FSINFO3resok am_FSINFO3resok; + +struct am_FSINFO3resfail { + am_post_op_attr obj_attributes; +}; +typedef struct am_FSINFO3resfail am_FSINFO3resfail; + +struct am_FSINFO3res { + am_nfsstat3 status; + union { + am_FSINFO3resok ok; + am_FSINFO3resfail fail; + } res_u; +}; +typedef struct am_FSINFO3res am_FSINFO3res; + +struct am_FSSTAT3args { + am_nfs_fh3 fsroot; +}; +typedef struct am_FSSTAT3args am_FSSTAT3args; + +struct am_FSSTAT3resok { + am_post_op_attr obj_attributes; + am_size3 tbytes; + am_size3 fbytes; + am_size3 abytes; + am_size3 tfiles; + am_size3 ffiles; + am_size3 afiles; + u_int invarsec; +}; +typedef struct am_FSSTAT3resok am_FSSTAT3resok; + +struct am_FSSTAT3resfail { + am_post_op_attr obj_attributes; +}; +typedef struct am_FSSTAT3resfail am_FSSTAT3resfail; + +struct am_FSSTAT3res { + am_nfsstat3 status; + union { + am_FSSTAT3resok ok; + am_FSSTAT3resfail fail; + } res_u; +}; +typedef struct am_FSSTAT3res am_FSSTAT3res; + +struct am_PATHCONF3args { + am_nfs_fh3 object; +}; +typedef struct am_PATHCONF3args am_PATHCONF3args; + +struct am_PATHCONF3resok { + am_post_op_attr obj_attributes; + u_int linkmax; + u_int name_max; + bool_t no_trunc; + bool_t chown_restricted; + bool_t case_insensitive; + bool_t case_preserving; +}; +typedef struct am_PATHCONF3resok am_PATHCONF3resok; + +struct am_PATHCONF3resfail { + am_post_op_attr obj_attributes; +}; +typedef struct am_PATHCONF3resfail am_PATHCONF3resfail; + +struct am_PATHCONF3res { + am_nfsstat3 status; + union { + am_PATHCONF3resok ok; + am_PATHCONF3resfail fail; + } res_u; +}; +typedef struct am_PATHCONF3res am_PATHCONF3res; + +typedef char *am_nfspath3; + +struct am_symlinkdata3 { + am_sattr3 symlink_attributes; + am_nfspath3 symlink_data; +}; +typedef struct am_symlinkdata3 am_symlinkdata3; + +struct am_SYMLINK3args { + am_diropargs3 where; + am_symlinkdata3 symlink; +}; +typedef struct am_SYMLINK3args am_SYMLINK3args; + +struct am_SYMLINK3resok { + am_post_op_fh3 obj; + am_post_op_attr obj_attributes; + am_wcc_data dir_wcc; +}; +typedef struct am_SYMLINK3resok am_SYMLINK3resok; + +struct am_SYMLINK3resfail { + am_wcc_data dir_wcc; +}; +typedef struct am_SYMLINK3resfail am_SYMLINK3resfail; + +struct am_SYMLINK3res { + am_nfsstat3 status; + union { + am_SYMLINK3resok ok; + am_SYMLINK3resfail fail; + } res_u; +}; +typedef struct am_SYMLINK3res am_SYMLINK3res; + +struct am_READLINK3args { + am_nfs_fh3 symlink; +}; +typedef struct am_READLINK3args am_READLINK3args; + +struct am_READLINK3resok { + am_post_op_attr symlink_attributes; + am_nfspath3 data; +}; +typedef struct am_READLINK3resok am_READLINK3resok; + +struct am_READLINK3resfail { + am_post_op_attr symlink_attributes; +}; +typedef struct am_READLINK3resfail am_READLINK3resfail; + +struct am_READLINK3res { + am_nfsstat3 status; + union { + am_READLINK3resok ok; + am_READLINK3resfail fail; + } res_u; +}; +typedef struct am_READLINK3res am_READLINK3res; + +struct am_devicedata3 { + am_sattr3 dev_attributes; + am_specdata3 spec; +}; +typedef struct am_devicedata3 am_devicedata3; + +struct am_mknoddata3 { + am_ftype3 type; + union { + am_devicedata3 chr_device; + am_devicedata3 blk_device; + am_sattr3 sock_attributes; + am_sattr3 pipe_attributes; + } am_mknoddata3_u; +}; +typedef struct am_mknoddata3 am_mknoddata3; + +struct am_MKNOD3args { + am_diropargs3 where; + am_mknoddata3 what; +}; +typedef struct am_MKNOD3args am_MKNOD3args; + +struct am_MKNOD3resok { + am_post_op_fh3 obj; + am_post_op_attr obj_attributes; + am_wcc_data dir_wcc; +}; +typedef struct am_MKNOD3resok am_MKNOD3resok; + +struct am_MKNOD3resfail { + am_wcc_data dir_wcc; +}; +typedef struct am_MKNOD3resfail am_MKNOD3resfail; + +struct am_MKNOD3res { + am_nfsstat3 status; + union { + am_MKNOD3resok ok; + am_MKNOD3resfail fail; + } res_u; +}; +typedef struct am_MKNOD3res am_MKNOD3res; + +struct am_MKDIR3args { + am_diropargs3 where; + am_sattr3 attributes; +}; +typedef struct am_MKDIR3args am_MKDIR3args; + +struct am_MKDIR3resok { + am_post_op_fh3 obj; + am_post_op_attr obj_attributes; + am_wcc_data dir_wcc; +}; +typedef struct am_MKDIR3resok am_MKDIR3resok; + +struct am_MKDIR3resfail { + am_wcc_data dir_wcc; +}; +typedef struct am_MKDIR3resfail am_MKDIR3resfail; + +struct am_MKDIR3res { + am_nfsstat3 status; + union { + am_MKDIR3resok ok; + am_MKDIR3resfail fail; + } res_u; +}; +typedef struct am_MKDIR3res am_MKDIR3res; + +struct am_RMDIR3args { + am_diropargs3 object; +}; +typedef struct am_RMDIR3args am_RMDIR3args; + +struct am_RMDIR3resok { + am_wcc_data dir_wcc; +}; +typedef struct am_RMDIR3resok am_RMDIR3resok; + +struct am_RMDIR3resfail { + am_wcc_data dir_wcc; +}; +typedef struct am_RMDIR3resfail am_RMDIR3resfail; + +struct am_RMDIR3res { + am_nfsstat3 status; + union { + am_RMDIR3resok ok; + am_RMDIR3resfail fail; + } res_u; +}; +typedef struct am_RMDIR3res am_RMDIR3res; + +struct am_RENAME3args { + am_diropargs3 from; + am_diropargs3 to; +}; +typedef struct am_RENAME3args am_RENAME3args; + +struct am_RENAME3resok { + am_wcc_data fromdir_wcc; + am_wcc_data todir_wcc; +}; +typedef struct am_RENAME3resok am_RENAME3resok; + +struct am_RENAME3resfail { + am_wcc_data fromdir_wcc; + am_wcc_data todir_wcc; +}; +typedef struct am_RENAME3resfail am_RENAME3resfail; + +struct am_RENAME3res { + am_nfsstat3 status; + union { + am_RENAME3resok ok; + am_RENAME3resfail fail; + } res_u; +}; +typedef struct am_RENAME3res am_RENAME3res; + +struct am_READDIRPLUS3args { + am_nfs_fh3 dir; + am_cookie3 cookie; + am_cookieverf3 cookieverf; + am_count3 dircount; + am_count3 maxcount; +}; +typedef struct am_READDIRPLUS3args am_READDIRPLUS3args; + +struct am_entryplus3 { + am_fileid3 fileid; + am_filename3 name; + am_cookie3 cookie; + am_post_op_attr name_attributes; + am_post_op_fh3 name_handle; + struct am_entryplus3 *nextentry; +}; +typedef struct am_entryplus3 am_entryplus3; + +struct am_dirlistplus3 { + am_entryplus3 *entries; + bool_t eof; +}; +typedef struct am_dirlistplus3 am_dirlistplus3; + +struct am_READDIRPLUS3resok { + am_post_op_attr dir_attributes; + am_cookieverf3 cookieverf; + am_dirlistplus3 reply; +}; +typedef struct am_READDIRPLUS3resok am_READDIRPLUS3resok; + +struct am_READDIRPLUS3resfail { + am_post_op_attr dir_attributes; +}; +typedef struct am_READDIRPLUS3resfail am_READDIRPLUS3resfail; + +struct am_READDIRPLUS3res { + am_nfsstat3 status; + union { + am_READDIRPLUS3resok ok; + am_READDIRPLUS3resfail fail; + } res_u; +}; +typedef struct am_READDIRPLUS3res am_READDIRPLUS3res; + +struct am_READDIR3args { + am_nfs_fh3 dir; + am_cookie3 cookie; + am_cookieverf3 cookieverf; + am_count3 count; +}; +typedef struct am_READDIR3args am_READDIR3args; + +struct am_entry3 { + am_fileid3 fileid; + am_filename3 name; + am_cookie3 cookie; + struct am_entry3 *nextentry; +}; +typedef struct am_entry3 am_entry3; + +struct am_dirlist3 { + am_entry3 *entries; + bool_t eof; +}; +typedef struct am_dirlist3 am_dirlist3; + +struct am_READDIR3resok { + am_post_op_attr dir_attributes; + am_cookieverf3 cookieverf; + am_dirlist3 reply; +}; +typedef struct am_READDIR3resok am_READDIR3resok; + +struct am_READDIR3resfail { + am_post_op_attr dir_attributes; +}; +typedef struct am_READDIR3resfail am_READDIR3resfail; + +struct am_READDIR3res { + am_nfsstat3 status; + union { + am_READDIR3resok ok; + am_READDIR3resfail fail; + } res_u; +}; +typedef struct am_READDIR3res am_READDIR3res; + +struct am_LINK3args { + am_nfs_fh3 file; + am_diropargs3 link; +}; +typedef struct am_LINK3args am_LINK3args; + +struct am_LINK3resok { + am_post_op_attr file_attributes; + am_wcc_data linkdir_wcc; +}; +typedef struct am_LINK3resok am_LINK3resok; + +struct am_LINK3resfail { + am_post_op_attr file_attributes; + am_wcc_data linkdir_wcc; +}; +typedef struct am_LINK3resfail am_LINK3resfail; + +struct am_LINK3res { + am_nfsstat3 status; + union { + am_LINK3resok ok; + am_LINK3resfail fail; + } res_u; +}; +typedef struct am_LINK3res am_LINK3res; + +struct am_sattrguard3 { + bool_t check; + union { + am_nfstime3 obj_ctime; + } am_sattrguard3_u; +}; +typedef struct am_sattrguard3 am_sattrguard3; + +struct am_SETATTR3args { + am_nfs_fh3 object; + am_sattr3 new_attributes; + am_sattrguard3 guard; +}; +typedef struct am_SETATTR3args am_SETATTR3args; + +struct am_SETATTR3resok { + am_wcc_data obj_wcc; +}; +typedef struct am_SETATTR3resok am_SETATTR3resok; + +struct am_SETATTR3resfail { + am_wcc_data obj_wcc; +}; +typedef struct am_SETATTR3resfail am_SETATTR3resfail; + +struct am_SETATTR3res { + am_nfsstat3 status; + union { + am_SETATTR3resok ok; + am_SETATTR3resfail fail; + } res_u; +}; +typedef struct am_SETATTR3res am_SETATTR3res; #endif /* HAVE_FS_NFS3 */ /* @@ -310,6 +1117,74 @@ bool_t xdr_writeargs(XDR *xdrs, nfswriteargs *objp); * NFS3 XDR FUNCTIONS: */ #ifdef HAVE_FS_NFS3 +#define AM_NFS3_NULL 0 +void * am_nfs3_null_3(void *, CLIENT *); +void * am_nfs3_null_3_svc(void *, struct svc_req *); +#define AM_NFS3_GETATTR 1 +am_GETATTR3res * am_nfs3_getattr_3(am_GETATTR3args *, CLIENT *); +am_GETATTR3res * am_nfs3_getattr_3_svc(am_GETATTR3args *, struct svc_req *); +#define AM_NFS3_SETATTR 2 +am_SETATTR3res * am_nfs3_setattr_3(am_SETATTR3args *, CLIENT *); +am_SETATTR3res * am_nfs3_setattr_3_svc(am_SETATTR3args *, struct svc_req *); +#define AM_NFS3_LOOKUP 3 +am_LOOKUP3res * am_nfs3_lookup_3(am_LOOKUP3args *, CLIENT *); +am_LOOKUP3res * am_nfs3_lookup_3_svc(am_LOOKUP3args *, struct svc_req *); +#define AM_NFS3_ACCESS 4 +am_ACCESS3res * am_nfs3_access_3(am_ACCESS3args *, CLIENT *); +am_ACCESS3res * am_nfs3_access_3_svc(am_ACCESS3args *, struct svc_req *); +#define AM_NFS3_READLINK 5 +am_READLINK3res * am_nfs3_readlink_3(am_READLINK3args *, CLIENT *); +am_READLINK3res * am_nfs3_readlink_3_svc(am_READLINK3args *, struct svc_req *); +#define AM_NFS3_READ 6 +am_READ3res * am_nfs3_read_3(am_READ3args *, CLIENT *); +am_READ3res * am_nfs3_read_3_svc(am_READ3args *, struct svc_req *); +#define AM_NFS3_WRITE 7 +am_WRITE3res * am_nfs3_write_3(am_WRITE3args *, CLIENT *); +am_WRITE3res * am_nfs3_write_3_svc(am_WRITE3args *, struct svc_req *); +#define AM_NFS3_CREATE 8 +am_CREATE3res * am_nfs3_create_3(am_CREATE3args *, CLIENT *); +am_CREATE3res * am_nfs3_create_3_svc(am_CREATE3args *, struct svc_req *); +#define AM_NFS3_MKDIR 9 +am_MKDIR3res * am_nfs3_mkdir_3(am_MKDIR3args *, CLIENT *); +am_MKDIR3res * am_nfs3_mkdir_3_svc(am_MKDIR3args *, struct svc_req *); +#define AM_NFS3_SYMLINK 10 +am_SYMLINK3res * am_nfs3_symlink_3(am_SYMLINK3args *, CLIENT *); +am_SYMLINK3res * am_nfs3_symlink_3_svc(am_SYMLINK3args *, struct svc_req *); +#define AM_NFS3_MKNOD 11 +am_MKNOD3res * am_nfs3_mknod_3(am_MKNOD3args *, CLIENT *); +am_MKNOD3res * am_nfs3_mknod_3_svc(am_MKNOD3args *, struct svc_req *); +#define AM_NFS3_REMOVE 12 +am_REMOVE3res * am_nfs3_remove_3(am_REMOVE3args *, CLIENT *); +am_REMOVE3res * am_nfs3_remove_3_svc(am_REMOVE3args *, struct svc_req *); +#define AM_NFS3_RMDIR 13 +am_RMDIR3res * am_nfs3_rmdir_3(am_RMDIR3args *, CLIENT *); +am_RMDIR3res * am_nfs3_rmdir_3_svc(am_RMDIR3args *, struct svc_req *); +#define AM_NFS3_RENAME 14 +am_RENAME3res * am_nfs3_rename_3(am_RENAME3args *, CLIENT *); +am_RENAME3res * am_nfs3_rename_3_svc(am_RENAME3args *, struct svc_req *); +#define AM_NFS3_LINK 15 +am_LINK3res * am_nfs3_link_3(am_LINK3args *, CLIENT *); +am_LINK3res * am_nfs3_link_3_svc(am_LINK3args *, struct svc_req *); +#define AM_NFS3_READDIR 16 +am_READDIR3res * am_nfs3_readdir_3(am_READDIR3args *, CLIENT *); +am_READDIR3res * am_nfs3_readdir_3_svc(am_READDIR3args *, struct svc_req *); +#define AM_NFS3_READDIRPLUS 17 +am_READDIRPLUS3res * am_nfs3_readdirplus_3(am_READDIRPLUS3args *, CLIENT *); +am_READDIRPLUS3res * am_nfs3_readdirplus_3_svc(am_READDIRPLUS3args *, struct svc_req *); +#define AM_NFS3_FSSTAT 18 +am_FSSTAT3res * am_nfs3_fsstat_3(am_FSSTAT3args *, CLIENT *); +am_FSSTAT3res * am_nfs3_fsstat_3_svc(am_FSSTAT3args *, struct svc_req *); +#define AM_NFS3_FSINFO 19 +am_FSINFO3res * am_nfs3_fsinfo_3(am_FSINFO3args *, CLIENT *); +am_FSINFO3res * am_nfs3_fsinfo_3_svc(am_FSINFO3args *, struct svc_req *); +#define AM_NFS3_PATHCONF 20 +am_PATHCONF3res * am_nfs3_pathconf_3(am_PATHCONF3args *, CLIENT *); +am_PATHCONF3res * am_nfs3_pathconf_3_svc(am_PATHCONF3args *, struct svc_req *); +#define AM_NFS3_COMMIT 21 +am_COMMIT3res * am_nfs3_commit_3(am_COMMIT3args *, CLIENT *); +am_COMMIT3res * am_nfs3_commit_3_svc(am_COMMIT3args *, struct svc_req *); +int nfs_program_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + bool_t xdr_am_fhandle3(XDR *xdrs, am_fhandle3 *objp); bool_t xdr_am_mountstat3(XDR *xdrs, am_mountstat3 *objp); bool_t xdr_am_mountres3_ok(XDR *xdrs, am_mountres3_ok *objp); @@ -322,6 +1197,134 @@ bool_t xdr_am_LOOKUP3resfail(XDR *xdrs, am_LOOKUP3resfail *objp); bool_t xdr_am_LOOKUP3resok(XDR *xdrs, am_LOOKUP3resok *objp); bool_t xdr_am_nfsstat3(XDR *xdrs, am_nfsstat3 *objp); bool_t xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp); +bool_t xdr_am_cookieverf3 (XDR *, am_cookieverf3); +bool_t xdr_uint64 (XDR *, uint64*); +bool_t xdr_am_cookie3 (XDR *, am_cookie3*); +bool_t xdr_am_nfs_fh3 (XDR *, am_nfs_fh3*); +bool_t xdr_am_nfsstat3 (XDR *, am_nfsstat3*); +bool_t xdr_am_filename3 (XDR *, am_filename3*); +bool_t xdr_am_diropargs3 (XDR *, am_diropargs3*); +bool_t xdr_am_ftype3 (XDR *, am_ftype3*); +bool_t xdr_am_mode3 (XDR *, am_mode3*); +bool_t xdr_am_uid3 (XDR *, am_uid3*); +bool_t xdr_am_gid3 (XDR *, am_gid3*); +bool_t xdr_am_size3 (XDR *, am_size3*); +bool_t xdr_am_fileid3 (XDR *, am_fileid3*); +bool_t xdr_am_specdata3 (XDR *, am_specdata3*); +bool_t xdr_am_nfstime3 (XDR *, am_nfstime3*); +bool_t xdr_am_fattr3 (XDR *, am_fattr3*); +bool_t xdr_am_post_op_attr (XDR *, am_post_op_attr*); +bool_t xdr_am_stable_how (XDR *, am_stable_how*); +bool_t xdr_am_offset3 (XDR *, am_offset3*); +bool_t xdr_am_count3 (XDR *, am_count3*); +bool_t xdr_am_wcc_attr (XDR *, am_wcc_attr*); +bool_t xdr_am_pre_op_attr (XDR *, am_pre_op_attr*); +bool_t xdr_am_wcc_data (XDR *, am_wcc_data*); +bool_t xdr_am_WRITE3args (XDR *, am_WRITE3args*); +bool_t xdr_am_writeverf3 (XDR *, am_writeverf3); +bool_t xdr_am_WRITE3resok (XDR *, am_WRITE3resok*); +bool_t xdr_am_WRITE3resfail (XDR *, am_WRITE3resfail*); +bool_t xdr_am_WRITE3res (XDR *, am_WRITE3res*); +bool_t xdr_am_LOOKUP3args (XDR *, am_LOOKUP3args*); +bool_t xdr_am_LOOKUP3resok (XDR *, am_LOOKUP3resok*); +bool_t xdr_am_LOOKUP3resfail (XDR *, am_LOOKUP3resfail*); +bool_t xdr_am_LOOKUP3res (XDR *, am_LOOKUP3res*); +bool_t xdr_am_COMMIT3args (XDR *, am_COMMIT3args*); +bool_t xdr_am_COMMIT3resok (XDR *, am_COMMIT3resok*); +bool_t xdr_am_COMMIT3resfail (XDR *, am_COMMIT3resfail*); +bool_t xdr_am_COMMIT3res (XDR *, am_COMMIT3res*); +bool_t xdr_am_ACCESS3args (XDR *, am_ACCESS3args*); +bool_t xdr_am_ACCESS3resok (XDR *, am_ACCESS3resok*); +bool_t xdr_am_ACCESS3resfail (XDR *, am_ACCESS3resfail*); +bool_t xdr_am_ACCESS3res (XDR *, am_ACCESS3res*); +bool_t xdr_am_GETATTR3args (XDR *, am_GETATTR3args*); +bool_t xdr_am_GETATTR3resok (XDR *, am_GETATTR3resok*); +bool_t xdr_am_GETATTR3res (XDR *, am_GETATTR3res*); +bool_t xdr_am_time_how (XDR *, am_time_how*); +bool_t xdr_am_set_mode3 (XDR *, am_set_mode3*); +bool_t xdr_am_set_uid3 (XDR *, am_set_uid3*); +bool_t xdr_am_set_gid3 (XDR *, am_set_gid3*); +bool_t xdr_am_set_size3 (XDR *, am_set_size3*); +bool_t xdr_am_set_atime (XDR *, am_set_atime*); +bool_t xdr_am_set_mtime (XDR *, am_set_mtime*); +bool_t xdr_am_sattr3 (XDR *, am_sattr3*); +bool_t xdr_am_createmode3 (XDR *, am_createmode3*); +bool_t xdr_am_createverf3 (XDR *, am_createverf3); +bool_t xdr_am_createhow3 (XDR *, am_createhow3*); +bool_t xdr_am_CREATE3args (XDR *, am_CREATE3args*); +bool_t xdr_am_post_op_fh3 (XDR *, am_post_op_fh3*); +bool_t xdr_am_CREATE3resok (XDR *, am_CREATE3resok*); +bool_t xdr_am_CREATE3resfail (XDR *, am_CREATE3resfail*); +bool_t xdr_am_CREATE3res (XDR *, am_CREATE3res*); +bool_t xdr_am_REMOVE3args (XDR *, am_REMOVE3args*); +bool_t xdr_am_REMOVE3resok (XDR *, am_REMOVE3resok*); +bool_t xdr_am_REMOVE3resfail (XDR *, am_REMOVE3resfail*); +bool_t xdr_am_REMOVE3res (XDR *, am_REMOVE3res*); +bool_t xdr_am_READ3args (XDR *, am_READ3args*); +bool_t xdr_am_READ3resok (XDR *, am_READ3resok*); +bool_t xdr_am_READ3resfail (XDR *, am_READ3resfail*); +bool_t xdr_am_READ3res (XDR *, am_READ3res*); +bool_t xdr_am_FSINFO3args (XDR *, am_FSINFO3args*); +bool_t xdr_am_FSINFO3resok (XDR *, am_FSINFO3resok*); +bool_t xdr_am_FSINFO3resfail (XDR *, am_FSINFO3resfail*); +bool_t xdr_am_FSINFO3res (XDR *, am_FSINFO3res*); +bool_t xdr_am_FSSTAT3args (XDR *, am_FSSTAT3args*); +bool_t xdr_am_FSSTAT3resok (XDR *, am_FSSTAT3resok*); +bool_t xdr_am_FSSTAT3resfail (XDR *, am_FSSTAT3resfail*); +bool_t xdr_am_FSSTAT3res (XDR *, am_FSSTAT3res*); +bool_t xdr_am_PATHCONF3args (XDR *, am_PATHCONF3args*); +bool_t xdr_am_PATHCONF3resok (XDR *, am_PATHCONF3resok*); +bool_t xdr_am_PATHCONF3resfail (XDR *, am_PATHCONF3resfail*); +bool_t xdr_am_PATHCONF3res (XDR *, am_PATHCONF3res*); +bool_t xdr_am_nfspath3 (XDR *, am_nfspath3*); +bool_t xdr_am_symlinkdata3 (XDR *, am_symlinkdata3*); +bool_t xdr_am_SYMLINK3args (XDR *, am_SYMLINK3args*); +bool_t xdr_am_SYMLINK3resok (XDR *, am_SYMLINK3resok*); +bool_t xdr_am_SYMLINK3resfail (XDR *, am_SYMLINK3resfail*); +bool_t xdr_am_SYMLINK3res (XDR *, am_SYMLINK3res*); +bool_t xdr_am_READLINK3args (XDR *, am_READLINK3args*); +bool_t xdr_am_READLINK3resok (XDR *, am_READLINK3resok*); +bool_t xdr_am_READLINK3resfail (XDR *, am_READLINK3resfail*); +bool_t xdr_am_READLINK3res (XDR *, am_READLINK3res*); +bool_t xdr_am_devicedata3 (XDR *, am_devicedata3*); +bool_t xdr_am_mknoddata3 (XDR *, am_mknoddata3*); +bool_t xdr_am_MKNOD3args (XDR *, am_MKNOD3args*); +bool_t xdr_am_MKNOD3resok (XDR *, am_MKNOD3resok*); +bool_t xdr_am_MKNOD3resfail (XDR *, am_MKNOD3resfail*); +bool_t xdr_am_MKNOD3res (XDR *, am_MKNOD3res*); +bool_t xdr_am_MKDIR3args (XDR *, am_MKDIR3args*); +bool_t xdr_am_MKDIR3resok (XDR *, am_MKDIR3resok*); +bool_t xdr_am_MKDIR3resfail (XDR *, am_MKDIR3resfail*); +bool_t xdr_am_MKDIR3res (XDR *, am_MKDIR3res*); +bool_t xdr_am_RMDIR3args (XDR *, am_RMDIR3args*); +bool_t xdr_am_RMDIR3resok (XDR *, am_RMDIR3resok*); +bool_t xdr_am_RMDIR3resfail (XDR *, am_RMDIR3resfail*); +bool_t xdr_am_RMDIR3res (XDR *, am_RMDIR3res*); +bool_t xdr_am_RENAME3args (XDR *, am_RENAME3args*); +bool_t xdr_am_RENAME3resok (XDR *, am_RENAME3resok*); +bool_t xdr_am_RENAME3resfail (XDR *, am_RENAME3resfail*); +bool_t xdr_am_RENAME3res (XDR *, am_RENAME3res*); +bool_t xdr_am_READDIRPLUS3args (XDR *, am_READDIRPLUS3args*); +bool_t xdr_am_entryplus3 (XDR *, am_entryplus3*); +bool_t xdr_am_dirlistplus3 (XDR *, am_dirlistplus3*); +bool_t xdr_am_READDIRPLUS3resok (XDR *, am_READDIRPLUS3resok*); +bool_t xdr_am_READDIRPLUS3resfail (XDR *, am_READDIRPLUS3resfail*); +bool_t xdr_am_READDIRPLUS3res (XDR *, am_READDIRPLUS3res*); +bool_t xdr_am_READDIR3args (XDR *, am_READDIR3args*); +bool_t xdr_am_entry3 (XDR *, am_entry3*); +bool_t xdr_am_dirlist3 (XDR *, am_dirlist3*); +bool_t xdr_am_READDIR3resok (XDR *, am_READDIR3resok*); +bool_t xdr_am_READDIR3resfail (XDR *, am_READDIR3resfail*); +bool_t xdr_am_READDIR3res (XDR *, am_READDIR3res*); +bool_t xdr_am_LINK3args (XDR *, am_LINK3args*); +bool_t xdr_am_LINK3resok (XDR *, am_LINK3resok*); +bool_t xdr_am_LINK3resfail (XDR *, am_LINK3resfail*); +bool_t xdr_am_LINK3res (XDR *, am_LINK3res*); +bool_t xdr_am_sattrguard3 (XDR *, am_sattrguard3*); +bool_t xdr_am_SETATTR3args (XDR *, am_SETATTR3args*); +bool_t xdr_am_SETATTR3resok (XDR *, am_SETATTR3resok*); +bool_t xdr_am_SETATTR3resfail (XDR *, am_SETATTR3resfail*); +bool_t xdr_am_SETATTR3res (XDR *, am_SETATTR3res*); #endif /* HAVE_FS_NFS3 */ #endif /* not _AM_XDR_FUNC_H */ diff --git a/contrib/amd/include/amq_defs.h b/contrib/amd/include/amq_defs.h index 75c46517103..4db5133cba4 100644 --- a/contrib/amd/include/amq_defs.h +++ b/contrib/amd/include/amq_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -55,7 +51,7 @@ #define AMQ_VERSION ((u_long)1) #define AMQPROC_NULL ((u_long)0) #define AMQPROC_MNTTREE ((u_long)1) -#define AMQPROC_UMNT ((u_long)2) +#define AMQPROC_UMNT ((u_long)2) /* asynchronous unmount */ #define AMQPROC_STATS ((u_long)3) #define AMQPROC_EXPORT ((u_long)4) #define AMQPROC_SETOPT ((u_long)5) @@ -64,15 +60,19 @@ #define AMQPROC_GETVERS ((u_long)8) #define AMQPROC_GETPID ((u_long)9) #define AMQPROC_PAWD ((u_long)10) +#define AMQPROC_SYNC_UMNT ((u_long)11) /* synchronous unmount */ +#define AMQPROC_GETMAPINFO ((u_long)12) /* * TYPEDEFS */ -typedef long *time_type; +typedef time_t *time_type; typedef struct amq_mount_info amq_mount_info; +typedef struct amq_map_info amq_map_info; typedef struct amq_mount_stats amq_mount_stats; typedef struct amq_mount_tree amq_mount_tree; typedef struct amq_setopt amq_setopt; +typedef struct amq_sync_umnt amq_sync_umnt; typedef amq_mount_tree *amq_mount_tree_p; /* @@ -114,6 +114,22 @@ typedef struct { amq_mount_tree_p *amq_mount_tree_list_val; } amq_mount_tree_list; +struct amq_map_info { + amq_string mi_name; + amq_string mi_wildcard; + time_type mi_modify; + int mi_flags; + int mi_refc; + int mi_up; + int mi_reloads; + int mi_nentries; +}; + +typedef struct { + u_int amq_map_info_list_len; + amq_map_info *amq_map_info_list_val; +} amq_map_info_list; + struct amq_mount_stats { int as_drops; int as_stale; @@ -122,6 +138,21 @@ struct amq_mount_stats { int as_uerr; }; +typedef enum { + AMQ_UMNT_OK = 0, /* must be zero! */ + AMQ_UMNT_FAILED = 1, /* unmount failed */ + AMQ_UMNT_FORK = 2, /* fork failed */ + AMQ_UMNT_READ = 3, /* pipe read failed */ + AMQ_UMNT_SERVER = 4, /* server down */ + AMQ_UMNT_SIGNAL = 5 /* received signal */ +} au_etype; + +struct amq_sync_umnt { + au_etype au_etype; /* error type */ + int au_errno; /* error number */ + int au_signal; /* signal received */ +}; + enum amq_opt { AMOPT_DEBUG = 0, AMOPT_LOGFILE = 1, @@ -145,12 +176,15 @@ struct amq_setopt { */ extern bool_t xdr_amq_mount_info(XDR *xdrs, amq_mount_info *objp); extern bool_t xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp); +extern bool_t xdr_amq_map_info(XDR *xdrs, amq_map_info *objp); +extern bool_t xdr_amq_map_info_list(XDR *xdrs, amq_map_info_list *objp); extern bool_t xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp); extern bool_t xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp); extern bool_t xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp); extern bool_t xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp); extern bool_t xdr_amq_opt(XDR *xdrs, amq_opt *objp); extern bool_t xdr_amq_setopt(XDR *xdrs, amq_setopt *objp); +extern bool_t xdr_amq_sync_umnt(XDR *xdrs, amq_sync_umnt *objp); extern bool_t xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr); extern bool_t xdr_time_type(XDR *xdrs, time_type *objp); diff --git a/contrib/amd/include/mount_headers1.h b/contrib/amd/include/mount_headers1.h index 41f26e59f99..7d518a06aa2 100644 --- a/contrib/amd/include/mount_headers1.h +++ b/contrib/amd/include/mount_headers1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -123,50 +119,50 @@ # include #endif /* HAVE_SYS_VMOUNT_H */ -/* - * There is no point in including this on a glibc2 system - * we're only asking for trouble - */ -#if defined HAVE_LINUX_FS_H && (!defined __GLIBC__ || __GLIBC__ < 2) +#if HAVE_LINUX_FS_H +# if !defined(__GLIBC__) || __GLIBC__ < 2 /* * There's a conflict of definitions on redhat alpha linux between * and . * Also a conflict in definitions of ntohl/htonl in RH-5.1 sparc64 * between and (2.1 kernels). */ -# ifdef HAVE_SOCKETBITS_H -# define _LINUX_SOCKET_H -# undef BLKFLSBUF -# undef BLKGETSIZE -# undef BLKRAGET -# undef BLKRASET -# undef BLKROGET -# undef BLKROSET -# undef BLKRRPART -# undef MS_MGC_VAL -# undef MS_RMT_MASK -# endif /* HAVE_SOCKETBITS_H */ -# ifdef HAVE_LINUX_POSIX_TYPES_H -# include -# endif /* HAVE_LINUX_POSIX_TYPES_H */ -# ifndef _LINUX_BYTEORDER_GENERIC_H -# define _LINUX_BYTEORDER_GENERIC_H -# endif /* _LINUX_BYTEORDER_GENERIC_H */ -# ifndef _LINUX_STRING_H_ -# define _LINUX_STRING_H_ -# endif /* not _LINUX_STRING_H_ */ -# ifdef HAVE_LINUX_KDEV_T_H -# define __KERNEL__ -# include -# undef __KERNEL__ -# endif /* HAVE_LINUX_KDEV_T_H */ -# ifdef HAVE_LINUX_LIST_H -# define __KERNEL__ -# include -# undef __KERNEL__ -# endif /* HAVE_LINUX_LIST_H */ -# include -#endif /* HAVE_LINUX_FS_H && (!__GLIBC__ || __GLIBC__ < 2) */ +# ifdef HAVE_SOCKETBITS_H +# define _LINUX_SOCKET_H +# undef BLKFLSBUF +# undef BLKGETSIZE +# undef BLKRAGET +# undef BLKRASET +# undef BLKROGET +# undef BLKROSET +# undef BLKRRPART +# undef MS_MGC_VAL +# undef MS_RMT_MASK +# endif /* HAVE_SOCKETBITS_H */ +# ifdef HAVE_LINUX_POSIX_TYPES_H +# include +# endif /* HAVE_LINUX_POSIX_TYPES_H */ +# ifndef _LINUX_BYTEORDER_GENERIC_H +# define _LINUX_BYTEORDER_GENERIC_H +# endif /* _LINUX_BYTEORDER_GENERIC_H */ +# ifndef _LINUX_STRING_H_ +# define _LINUX_STRING_H_ +# endif /* not _LINUX_STRING_H_ */ +# ifdef HAVE_LINUX_KDEV_T_H +# define __KERNEL__ +# include +# undef __KERNEL__ +# endif /* HAVE_LINUX_KDEV_T_H */ +# ifdef HAVE_LINUX_LIST_H +# define __KERNEL__ +# include +# undef __KERNEL__ +# endif /* HAVE_LINUX_LIST_H */ +# include +# else +# include +# endif/* (!__GLIBC__ || __GLIBC__ < 2) */ +#endif /* HAVE_LINUX_FS_H */ #ifdef HAVE_SYS_FS_TYPES_H # include @@ -192,6 +188,10 @@ # include #endif /* HAVE_ISOFS_CD9660_CD9660_MOUNT_H */ +#ifdef HAVE_FS_UDF_UDF_MOUNT_H +# include +#endif /* HAVE_FS_UDF_UDF_MOUNT_H */ + #ifdef HAVE_SYS_FS_PC_FS_H # include #endif /* HAVE_SYS_FS_PC_FS_H */ @@ -202,6 +202,14 @@ # include #endif /* HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */ +#ifdef HAVE_FS_TMPFS_TMPFS_ARGS_H +# include +#endif /* HAVE_FS_TMPFS_TMPFS_ARGS_H */ + +#ifdef HAVE_FS_EFS_EFS_MOUNT_H +# include +#endif /* HAVE_FS_EFS_EFS_MOUNT_H */ + #ifdef HAVE_RPC_RPC_H # include #endif /* HAVE_RPC_RPC_H */ diff --git a/contrib/amd/include/mount_headers2.h b/contrib/amd/include/mount_headers2.h index 273e89cae10..87bf18efd8b 100644 --- a/contrib/amd/include/mount_headers2.h +++ b/contrib/amd/include/mount_headers2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/include/nfs_common.h b/contrib/amd/include/nfs_common.h new file mode 100644 index 00000000000..d89632b5933 --- /dev/null +++ b/contrib/amd/include/nfs_common.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE 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. + * + * + * File: am-utils/include/nfs_common.c + * + */ +struct nfs_common_args { + u_long flags; + u_long acdirmin; + u_long acdirmax; + u_long acregmin; + u_long acregmax; + u_long timeo; + u_long retrans; + u_long rsize; + u_long wsize; +}; + +#ifdef HAVE_NFS_ARGS_T_ACREGMIN +#define GET_ACREGMIN(nap, a) nap->acregmin = a.acregmin; +#define PUT_ACREGMIN(nap, a) a.acregmin = nap->acregmin; +#else +#define GET_ACREGMIN(nap, a) +#define PUT_ACREGMIN(nap, a) +#endif +#ifdef HAVE_NFS_ARGS_T_ACREGMAX +#define GET_ACREGMAX(nap, a) nap->acregmax = a.acregmax; +#define PUT_ACREGMAX(nap, a) a.acregmax = nap->acregmax; +#else +#define GET_ACREGMAX(nap, a) +#define PUT_ACREGMAX(nap, a) +#endif + +#ifdef HAVE_NFS_ARGS_T_ACDIRMIN +#define GET_ACDIRMIN(nap, a) nap->acdirmin = a.acdirmin; +#define PUT_ACDIRMIN(nap, a) a.acdirmin = nap->acdirmin; +#else +#define GET_ACDIRMIN(nap, a) +#define PUT_ACDIRMIN(nap, a) +#endif +#ifdef HAVE_NFS_ARGS_T_ACDIRMAX +#define GET_ACDIRMAX(nap, a) nap->acdirmax = a.acdirmax; +#define PUT_ACDIRMAX(nap, a) a.acdirmax = nap->acdirmax; +#else +#define GET_ACDIRMAX(nap, a) +#define PUT_ACDIRMAX(nap, a) +#endif + +#define get_nfs_common_args(nap, a) \ + do { \ + nap->flags = a.flags; \ + GET_ACREGMIN(nap, a) \ + GET_ACREGMAX(nap, a) \ + GET_ACDIRMIN(nap, a) \ + GET_ACDIRMAX(nap, a) \ + nap->timeo = a.timeo; \ + nap->retrans = a.retrans; \ + nap->rsize = a.rsize; \ + nap->wsize = a.wsize; \ + } while (/*CONSTCOND*/0) + +#define put_nfs_common_args(nap, a) \ + do { \ + a.flags = nap->flags; \ + PUT_ACREGMIN(nap, a) \ + PUT_ACREGMAX(nap, a) \ + PUT_ACDIRMIN(nap, a) \ + PUT_ACDIRMAX(nap, a) \ + a.timeo = nap->timeo; \ + a.retrans = nap->retrans; \ + a.rsize = nap->rsize; \ + a.wsize = nap->wsize; \ + } while (/*CONSTCOND*/0) diff --git a/contrib/amd/ldap-id.ms b/contrib/amd/ldap-id.ms index 3c0d3085664..77ff4ba1cb2 100644 --- a/contrib/amd/ldap-id.ms +++ b/contrib/amd/ldap-id.ms @@ -303,4 +303,4 @@ Stockholm University S-106 91 Stockholm SWEDEN -Email: leifj@matematik.su.se +Email: leifj AT matematik.su.se diff --git a/contrib/amd/ldap-id.txt b/contrib/amd/ldap-id.txt index 162f6635185..33a9187b768 100644 --- a/contrib/amd/ldap-id.txt +++ b/contrib/amd/ldap-id.txt @@ -333,7 +333,7 @@ Author's Address S-106 91 Stockholm SWEDEN - Email: leifj@matematik.su.se + Email: leifj AT matematik.su.se diff --git a/contrib/amd/libamu/amu.h b/contrib/amd/libamu/amu.h index 1e7834a1526..9415fc404ea 100644 --- a/contrib/amd/libamu/amu.h +++ b/contrib/amd/libamu/amu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -47,11 +43,14 @@ /* * Decide what maximum level of NFS server to try and mount with. */ -#ifdef HAVE_FS_NFS3 +#if defined(HAVE_FS_NFS4) +# define NFS_VERS_MAX NFS_VERSION4 +#elif defined(HAVE_FS_NFS3) # define NFS_VERS_MAX NFS_VERSION3 #else /* not HAVE_FS_NFS3 */ # define NFS_VERS_MAX NFS_VERSION #endif /* not HAVE_FS_NFS3 */ +# define NFS_VERS_MIN NFS_VERSION /* some systems like ncr2 do not define this in */ #ifndef MNTPATHLEN diff --git a/contrib/amd/libamu/hasmntopt.c b/contrib/amd/libamu/hasmntopt.c index 14cceb53b5c..e5a6f2e80df 100644 --- a/contrib/amd/libamu/hasmntopt.c +++ b/contrib/amd/libamu/hasmntopt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ n * modification, are permitted provided that the following conditions * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -67,7 +63,7 @@ nextmntopt(char **p) /* * Skip past white space */ - while (*cp && isspace((int) *cp)) + while (*cp && isspace((unsigned char) *cp)) cp++; /* @@ -106,7 +102,7 @@ amu_hasmntopt(mntent_t *mnt, char *opt) char t[MNTMAXSTR]; char *f; char *o = t; - int l = strlen(opt); + size_t l = strlen(opt); xstrlcpy(t, mnt->mnt_opts, sizeof(t)); diff --git a/contrib/amd/libamu/misc_rpc.c b/contrib/amd/libamu/misc_rpc.c index de0a92036b7..c6ad4486d7d 100644 --- a/contrib/amd/libamu/misc_rpc.c +++ b/contrib/amd/libamu/misc_rpc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/libamu/mount_fs.c b/contrib/amd/libamu/mount_fs.c index 74f064ede64..b5576bdc6d1 100644 --- a/contrib/amd/libamu/mount_fs.c +++ b/contrib/amd/libamu/mount_fs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -46,6 +42,7 @@ #endif /* HAVE_CONFIG_H */ #include #include +#include /* ensure that mount table options are delimited by a comma */ @@ -105,6 +102,30 @@ struct opt_tab mnt_flags[] = {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY}, #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */ +#if defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG) + {MNTTAB_OPT_LOG, MNT2_GEN_OPT_LOG}, +#endif /* defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG) */ + +#if defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME) + {MNTTAB_OPT_NOATIME, MNT2_GEN_OPT_NOATIME}, +#endif /* defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME) */ + +#if defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME) + {MNTTAB_OPT_NODEVMTIME, MNT2_GEN_OPT_NODEVMTIME}, +#endif /* defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME) */ + +#if defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP) + {MNTTAB_OPT_SOFTDEP, MNT2_GEN_OPT_SOFTDEP}, +#endif /* defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP) */ + +#if defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM) + {MNTTAB_OPT_SYMPERM, MNT2_GEN_OPT_SYMPERM}, +#endif /* defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM) */ + +#if defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION) + {MNTTAB_OPT_UNION, MNT2_GEN_OPT_UNION}, +#endif /* defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION) */ + /* * Do not define MNT2_NFS_OPT_* entries here! This is for generic * mount(2) options only, not for NFS mount options. If you need to put @@ -158,6 +179,25 @@ compute_automounter_mount_flags(mntent_t *mntp) } +#if defined(MOUNT_TABLE_ON_FILE) && defined(MNTTAB_OPT_VERS) +/* + * add the extra vers={2,3} field to the mount table, + * unless already specified by user + */ +static void +addvers(char *zopts, size_t l, mntent_t *mnt, u_long have_vers, + u_long want_vers) +{ + if (have_vers == want_vers && + hasmntval(mnt, MNTTAB_OPT_VERS) != want_vers) { + char optsbuf[48]; + xsnprintf(optsbuf, sizeof(optsbuf), + "%s=%d", MNTTAB_OPT_VERS, want_vers); + append_opts(zopts, l, optsbuf); + } +} +#endif /* MOUNT_TABLE_ON_FILE && MNTTAB_OPT_VERS */ + int mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname, int on_autofs) { @@ -166,17 +206,17 @@ mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, char *zopts = NULL, *xopts = NULL; size_t l; #endif /* MOUNT_TABLE_ON_FILE */ - char *mnt_dir = 0; + char *mnt_dir = NULL; #ifdef NEED_AUTOFS_SPACE_HACK - char *old_mnt_dir = 0; + char *old_mnt_dir = NULL; /* perform space hack */ if (on_autofs) { old_mnt_dir = mnt->mnt_dir; mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir); } else #endif /* NEED_AUTOFS_SPACE_HACK */ - mnt_dir = strdup(mnt->mnt_dir); + mnt_dir = xstrdup(mnt->mnt_dir); dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)", mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts); @@ -256,19 +296,15 @@ again: } # endif /* MNTTAB_OPT_DEV */ +# if defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS) + addvers(zopts, l, mnt, nfs_version, NFS_VERSION4); +# endif /* defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS) */ # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) - /* - * add the extra vers={2,3} field to the mount table, - * unless already specified by user - */ - if (nfs_version == NFS_VERSION3 && - hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) { - char optsbuf[48]; - xsnprintf(optsbuf, sizeof(optsbuf), - "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3); - append_opts(zopts, l, optsbuf); - } + addvers(zopts, l, mnt, nfs_version, NFS_VERSION3); # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */ +# ifdef MNTTAB_OPT_VERS + addvers(zopts, l, mnt, nfs_version, NFS_VERSION2); +# endif /* MNTTAB_OPT_VERS */ # ifdef MNTTAB_OPT_PROTO /* @@ -333,7 +369,7 @@ again: * with caution. */ static void -compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) +compute_nfs_attrcache_flags(struct nfs_common_args *nap, mntent_t *mntp) { int acval = 0; int err_acval = 1; /* 1 means we found no 'actimeo' value */ @@ -365,7 +401,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) nap->acregmin = acval; /* min ac timeout for reg files (sec) */ } else { # ifdef MNTTAB_OPT_ACREGMIN - err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, (int *) &nap->acregmin); + int tmp; + err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, &tmp); + nap->acregmin = tmp; # else /* not MNTTAB_OPT_ACREGMIN */ nap->acregmin = 0; # endif /* not MNTTAB_OPT_ACREGMIN */ @@ -384,7 +422,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) nap->acregmax = acval; /* max ac timeout for reg files (sec) */ } else { # ifdef MNTTAB_OPT_ACREGMAX - err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, (int *) &nap->acregmax); + int tmp; + err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, &tmp); + nap->acregmax = tmp; # else /* not MNTTAB_OPT_ACREGMAX */ nap->acregmax = 0; # endif /* not MNTTAB_OPT_ACREGMAX */ @@ -403,7 +443,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) nap->acdirmin = acval; /* min ac timeout for dirs (sec) */ } else { # ifdef MNTTAB_OPT_ACDIRMIN - err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, (int *) &nap->acdirmin); + int tmp; + err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, &tmp); + nap->acdirmin = tmp; # else /* not MNTTAB_OPT_ACDIRMIN */ nap->acdirmin = 0; # endif /* not MNTTAB_OPT_ACDIRMIN */ @@ -422,7 +464,9 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) nap->acdirmax = acval; /* max ac timeout for dirs (sec) */ } else { # ifdef MNTTAB_OPT_ACDIRMAX - err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, (int *) &nap->acdirmax); + int tmp; + err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, &tmp); + nap->acdirmax = tmp; # else /* not MNTTAB_OPT_ACDIRMAX */ nap->acdirmax = 0; # endif /* not MNTTAB_OPT_ACDIRMAX */ @@ -443,6 +487,352 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) } + +static void +compute_nfs_common_args(struct nfs_common_args *nap, mntent_t *mntp, + const char *nfs_proto, u_long nfs_version) +{ +#ifdef MNT2_NFS_OPT_TCP + if (nfs_proto && STREQ(nfs_proto, "tcp")) + nap->flags |= MNT2_NFS_OPT_TCP; +#endif /* MNT2_NFS_OPT_TCP */ + +#ifdef MNT2_NFS_OPT_NOCONN + /* check if user specified to use unconnected or connected sockets */ + if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL) + nap->flags |= MNT2_NFS_OPT_NOCONN; + else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL) + nap->flags &= ~MNT2_NFS_OPT_NOCONN; + else { + /* + * Some OSs want you to set noconn always. Some want you to always turn + * it off. Others want you to turn it on/off only if NFS V.3 is used. + * And all of that changes from revision to another. This is + * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than + * attempt to auto-detect this, I'm forced to "fix" it in the individual + * conf/nfs_prot/nfs_prot_*.h files. + */ +# ifdef USE_UNCONNECTED_NFS_SOCKETS + if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) { + nap->flags |= MNT2_NFS_OPT_NOCONN; + plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)"); + } +# endif /* USE_UNCONNECTED_NFS_SOCKETS */ +# ifdef USE_CONNECTED_NFS_SOCKETS + if (nap->flags & MNT2_NFS_OPT_NOCONN) { + nap->flags &= ~MNT2_NFS_OPT_NOCONN; + plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)"); + } +# endif /* USE_CONNECTED_NFS_SOCKETS */ + } +#endif /* MNT2_NFS_OPT_NOCONN */ + +#ifdef MNT2_NFS_OPT_RESVPORT +# ifdef MNTTAB_OPT_RESVPORT + if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL) + nap->flags |= MNT2_NFS_OPT_RESVPORT; +# else /* not MNTTAB_OPT_RESVPORT */ + nap->flags |= MNT2_NFS_OPT_RESVPORT; +# endif /* not MNTTAB_OPT_RESVPORT */ +#endif /* MNT2_NFS_OPT_RESVPORT */ + + nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE); +#ifdef MNT2_NFS_OPT_RSIZE + if (nap->rsize) + nap->flags |= MNT2_NFS_OPT_RSIZE; +#endif /* MNT2_NFS_OPT_RSIZE */ + if (nfs_version == NFS_VERSION && nap->rsize > 8192) + nap->rsize = 8192; + + nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE); +#ifdef MNT2_NFS_OPT_WSIZE + if (nap->wsize) + nap->flags |= MNT2_NFS_OPT_WSIZE; +#endif /* MNT2_NFS_OPT_WSIZE */ + if (nfs_version == NFS_VERSION && nap->wsize > 8192) + nap->wsize = 8192; + + nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO); +#ifdef MNT2_NFS_OPT_TIMEO + if (nap->timeo) + nap->flags |= MNT2_NFS_OPT_TIMEO; +#endif /* MNT2_NFS_OPT_TIMEO */ + + nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS); +#ifdef MNT2_NFS_OPT_RETRANS + if (nap->retrans) + nap->flags |= MNT2_NFS_OPT_RETRANS; +#endif /* MNT2_NFS_OPT_RETRANS */ + +#ifdef MNT2_NFS_OPT_SOFT + if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL) + nap->flags |= MNT2_NFS_OPT_SOFT; +#endif /* MNT2_NFS_OPT_SOFT */ + +#ifdef MNT2_NFS_OPT_SPONGY + if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) { + nap->flags |= MNT2_NFS_OPT_SPONGY; + if (*flags & MNT2_NFS_OPT_SOFT) { + plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored"); + nap->flags &= ~MNT2_NFS_OPT_SOFT; + } + } +#endif /* MNT2_NFS_OPT_SPONGY */ + +#if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) + /* Ultrix has separate generic and NFS ro flags */ + if (genflags & MNT2_GEN_OPT_RONLY) + nap->flags |= MNT2_NFS_OPT_RONLY; +#endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */ + +#ifdef MNTTAB_OPT_INTR + if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL) + /* + * Either turn on the "allow interrupts" option, or + * turn off the "disallow interrupts" option" + */ +# ifdef MNT2_NFS_OPT_INTR + nap->flags |= MNT2_NFS_OPT_INTR; +# endif /* MNT2_NFS_OPT_INTR */ +# ifdef MNT2_NFS_OPT_NOINTR + nap->flags &= ~MNT2_NFS_OPT_NOINTR; +# endif /* MNT2_NFS_OPT_NOINTR */ +# ifdef MNT2_NFS_OPT_INT + nap->flags |= MNT2_NFS_OPT_INT; +# endif /* MNT2_NFS_OPT_INT */ +# ifdef MNT2_NFS_OPT_NOINT + nap->flags &= ~MNT2_NFS_OPT_NOINT; +# endif /* MNT2_NFS_OPT_NOINT */ +#endif /* MNTTAB_OPT_INTR */ + +#ifdef MNT2_NFS_OPT_NOACL + if (amu_hasmntopt(mntp, MNTTAB_OPT_NOACL) != NULL) + nap->flags |= MNT2_NFS_OPT_NOACL; +#endif /* MNT2_NFS_OPT_NOACL */ + +#ifdef MNTTAB_OPT_NODEVS + if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL) + nap->flags |= MNT2_NFS_OPT_NODEVS; +#endif /* MNTTAB_OPT_NODEVS */ + +#ifdef MNTTAB_OPT_COMPRESS + if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL) + nap->flags |= MNT2_NFS_OPT_COMPRESS; +#endif /* MNTTAB_OPT_COMPRESS */ + +#ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */ + if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL) + nap->flags |= MNT2_NFS_OPT_PRIVATE; +#endif /* MNTTAB_OPT_PRIVATE */ + + +#if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) + if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL) + nap->flags |= MNT2_NFS_OPT_NOCTO; +#endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */ + +#if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) + if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL) + nap->flags |= MNT2_NFS_OPT_PROPLIST; +#endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */ + +#if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) + if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL) + nap->flags |= MNT2_NFS_OPT_NONLM; +#endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */ + +#if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) + if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL) + nap->flags |= MNT2_NFS_OPT_XLATECOOKIE; +#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */ +} + +static void +print_nfs_common_args(const struct nfs_common_args *a) +{ + plog(XLOG_DEBUG, "NA->flags = 0x%lx", a->flags); + + plog(XLOG_DEBUG, "NA->rsize = %lu", a->rsize); + plog(XLOG_DEBUG, "NA->wsize = %lu", a->wsize); + plog(XLOG_DEBUG, "NA->timeo = %lu", a->timeo); + plog(XLOG_DEBUG, "NA->retrans = %lu", a->retrans); + +#ifdef HAVE_NFS_ARGS_T_ACREGMIN + plog(XLOG_DEBUG, "NA->acregmin = %lu", a->acregmin); + plog(XLOG_DEBUG, "NA->acregmax = %lu", a->acregmax); + plog(XLOG_DEBUG, "NA->acdirmin = %lu", a->acdirmin); + plog(XLOG_DEBUG, "NA->acdirmax = %lu", a->acdirmax); +#endif /* HAVE_NFS_ARGS_T_ACREGMIN */ +} + +static void +discard_nfs23_args(nfs_args_t *nap) +{ +#ifdef HAVE_TRANSPORT_TYPE_TLI + free_knetconfig(nap->knconf); + if (nap->addr) + XFREE(nap->addr); /* allocated in compute_nfs_args() */ +#endif /* HAVE_TRANSPORT_TYPE_TLI */ +} + +#ifdef DEBUG +/* get string version (in hex) of identifier */ +static char * +get_hex_string(u_int len, const char *fhdata) +{ + u_int i; + static u_int xlen; + static char *buf; + static u_short *arr; + char str[16]; + + if (!fhdata || len == 0 || len > 10240) + return NULL; + i = len * 4 + 1; + if (xlen < i) { + buf = xrealloc(buf, i); + arr = xrealloc(arr, len * sizeof(*arr)); + xlen = i; + } + + buf[0] = '\0'; + memset(arr, 0, len * sizeof(*arr)); + memcpy(arr, fhdata, len); + len /= sizeof(*arr); + for (i = 0; i < len; i++) { + xsnprintf(str, sizeof(str), "%04x", ntohs(arr[i])); + xstrlcat(buf, str, xlen); + } + return buf; +} + +static void +print_nfs_sockaddr_in(const char *tag, const struct sockaddr_in *sap) +{ + char name[64]; + plog(XLOG_DEBUG, "NA->%s.sin_family = %d", tag, sap->sin_family); + plog(XLOG_DEBUG, "NA->%s.sin_port = %d", tag, ntohs(sap->sin_port)); + if (inet_ntop(AF_INET, &sap->sin_addr, name, sizeof(name)) == NULL) + return; + plog(XLOG_DEBUG, "NA->%s.sin_addr = \"%s\"", tag, name); +} + +/* + * print a subset of fields from "struct nfs_args" that are otherwise + * not being provided anywhere else. + */ +static void +print_nfs23_args(const nfs_args_t *nap, u_long nfs_version) +{ + int fhlen = 32; /* default: NFS V.2 file handle length is 32 */ +#ifdef HAVE_TRANSPORT_TYPE_TLI + struct netbuf *nbp; + struct knetconfig *kncp; +#else /* not HAVE_TRANSPORT_TYPE_TLI */ + struct sockaddr_in *sap; +#endif /* not HAVE_TRANSPORT_TYPE_TLI */ + struct nfs_common_args a; + + if (!nap) { + plog(XLOG_DEBUG, "NULL nfs_args!"); + return; + } + + /* override default file handle size */ +#ifdef FHSIZE + fhlen = FHSIZE; +#endif /* FHSIZE */ +#ifdef NFS_FHSIZE + fhlen = NFS_FHSIZE; +#endif /* NFS_FHSIZE */ + +#ifdef HAVE_TRANSPORT_TYPE_TLI + nbp = nap->addr; + plog(XLOG_DEBUG, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"", + nbp->maxlen, nbp->len, + get_hex_string(nbp->len, nbp->buf)); + nbp = nap->syncaddr; + plog(XLOG_DEBUG, "NA->syncaddr {netbuf} %p", nbp); + kncp = nap->knconf; + plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (u_long) kncp->knc_semantics); + plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly); + plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto); + plog(XLOG_DEBUG, "NA->knconf->rdev %lu", (u_long) kncp->knc_rdev); + /* don't print knconf->unused field */ +#else /* not HAVE_TRANSPORT_TYPE_TLI */ +# ifdef NFS_ARGS_T_ADDR_IS_POINTER + sap = (struct sockaddr_in *) nap->addr; +# else /* not NFS_ARGS_T_ADDR_IS_POINTER */ + sap = (struct sockaddr_in *) &nap->addr; +# endif /* not NFS_ARGS_T_ADDR_IS_POINTER */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + /* as per POSIX, sin_len need not be set (used internally by kernel) */ + plog(XLOG_DEBUG, "NA->addr.sin_len = %d", sap->sin_len); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ + print_nfs_sockaddr_in("addr", sap); +#endif /* not HAVE_TRANSPORT_TYPE_TLI */ +#ifdef HAVE_NFS_ARGS_T_ADDRLEN + plog(XLOG_DEBUG, "NA->addrlen = %d", nap->addrlen); +#endif /* ifdef HAVE_NFS_ARGS_T_ADDRLEN */ + + plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null"); +#ifdef HAVE_NFS_ARGS_T_NAMLEN + plog(XLOG_DEBUG, "NA->namlen = %d", nap->namlen); +#endif /* HAVE_NFS_ARGS_T_NAMLEN */ + +#ifdef MNT2_NFS_OPT_FSNAME + plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null"); +#endif /* MNT2_NFS_OPT_FSNAME */ + +#ifdef HAVE_NFS_ARGS_T_FHSIZE + plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize); + fhlen = nap->fhsize; +#endif /* HAVE_NFS_ARGS_T_FHSIZE */ +#ifdef HAVE_NFS_ARGS_T_FH_LEN + plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len); + fhlen = nap->fh_len; +#endif /* HAVE_NFS_ARGS_T_FH_LEN */ + + /* + * XXX: need to figure out how to correctly print file handles, + * since some times they are pointers, and sometimes the real structure + * is stored in nfs_args. Even if it is a pointer, it can be the actual + * char[] array, or a structure containing multiple fields. + */ + plog(XLOG_DEBUG, "NA->filehandle = \"%s\"", + get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD)); + +#ifdef HAVE_NFS_ARGS_T_SOTYPE + plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype); +#endif /* HAVE_NFS_ARGS_T_SOTYPE */ +#ifdef HAVE_NFS_ARGS_T_PROTO + plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto); +#endif /* HAVE_NFS_ARGS_T_PROTO */ +#ifdef HAVE_NFS_ARGS_T_VERSION + plog(XLOG_DEBUG, "NA->version = %d", nap->version); +#endif /* HAVE_NFS_ARGS_T_VERSION */ + + put_nfs_common_args(nap, a); + print_nfs_common_args(&a); + +#ifdef HAVE_NFS_ARGS_T_BSIZE + plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize); +#endif /* HAVE_NFS_ARGS_T_BSIZE */ + +#ifdef MNTTAB_OPT_SYMTTL + plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl); +#endif /* MNTTAB_OPT_SYMTTL */ +#ifdef MNTTAB_OPT_PG_THRESH + plog(XLOG_DEBUG, "NA->pg_thresh = %d", nap->pg_thresh); +#endif /* MNTTAB_OPT_PG_THRESH */ + +#ifdef MNT2_NFS_OPT_BIODS + plog(XLOG_DEBUG, "NA->biods = %d", nap->biods); +#endif /* MNT2_NFS_OPT_BIODS */ + +} +#endif /* DEBUG */ + /* * Fill in the many possible fields and flags of struct nfs_args. * @@ -451,35 +841,45 @@ compute_nfs_attrcache_flags(nfs_args_t *nap, mntent_t *mntp) * genflags: generic mount flags already determined * nfsncp: (TLI only) netconfig entry for this NFS mount * ip_addr: IP address of file server - * nfs_version: 2, 3, (4 in the future), or 0 if unknown + * nfs_version: 2, 3, or 0 if unknown * nfs_proto: "udp", "tcp", or NULL. * fhp: file handle structure pointer * host_name: name of remote NFS host * fs_name: remote file system name to mount */ -void -compute_nfs_args(nfs_args_t *nap, - mntent_t *mntp, - int genflags, - struct netconfig *nfsncp, - struct sockaddr_in *ip_addr, - u_long nfs_version, - char *nfs_proto, - am_nfs_handle_t *fhp, - char *host_name, - char *fs_name) +static void +compute_nfs23_args(nfs_args_t *nap, + mntent_t *mntp, + int genflags, + struct netconfig *nfsncp, + struct sockaddr_in *ip_addr, + u_long nfs_version, + char *nfs_proto, + am_nfs_handle_t *fhp, + char *host_name, + char *fs_name) { + struct nfs_common_args a; /* initialize just in case */ memset((voidp) nap, 0, sizeof(nfs_args_t)); /* compute all of the NFS attribute-cache flags */ - compute_nfs_attrcache_flags(nap, mntp); + memset(&a, 0, sizeof(a)); + compute_nfs_attrcache_flags(&a, mntp); + compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version); + get_nfs_common_args(nap, a); /************************************************************************/ /*** FILEHANDLE DATA AND LENGTH ***/ /************************************************************************/ #ifdef HAVE_FS_NFS3 if (nfs_version == NFS_VERSION3) { + if (fhp == NULL) { + plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version); + going_down(1); + return; + } + # if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) /* * Some systems (Irix/bsdi3) have a separate field in nfs_args for @@ -499,7 +899,14 @@ compute_nfs_args(nfs_args_t *nap, # endif /* MNT2_NFS_OPT_VER3 */ } else #endif /* HAVE_FS_NFS3 */ + { + if (fhp == NULL) { + plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version); + going_down(1); + return; + } NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2); + } #ifdef HAVE_NFS_ARGS_T_FHSIZE # ifdef HAVE_FS_NFS3 @@ -546,11 +953,6 @@ compute_nfs_args(nfs_args_t *nap, /************************************************************************/ /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/ /************************************************************************/ -#ifdef MNT2_NFS_OPT_TCP - if (nfs_proto && STREQ(nfs_proto, "tcp")) - nap->flags |= MNT2_NFS_OPT_TCP; -#endif /* MNT2_NFS_OPT_TCP */ - #ifdef HAVE_NFS_ARGS_T_SOTYPE /* bsdi3 uses this */ if (nfs_proto) { @@ -585,49 +987,35 @@ compute_nfs_args(nfs_args_t *nap, /************************************************************************/ /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/ /************************************************************************/ -#ifdef MNT2_NFS_OPT_NOCONN - /* check if user specified to use unconnected or connected sockets */ - if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL) - nap->flags |= MNT2_NFS_OPT_NOCONN; - else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL) - nap->flags &= ~MNT2_NFS_OPT_NOCONN; - else { - /* - * Some OSs want you to set noconn always. Some want you to always turn - * it off. Others want you to turn it on/off only if NFS V.3 is used. - * And all of that changes from revision to another. This is - * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than - * attempt to auto-detect this, I'm forced to "fix" it in the individual - * conf/nfs_prot/nfs_prot_*.h files. - */ -# ifdef USE_UNCONNECTED_NFS_SOCKETS - if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) { - nap->flags |= MNT2_NFS_OPT_NOCONN; - plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)"); - } -# endif /* USE_UNCONNECTED_NFS_SOCKETS */ -# ifdef USE_CONNECTED_NFS_SOCKETS - if (nap->flags & MNT2_NFS_OPT_NOCONN) { - nap->flags &= ~MNT2_NFS_OPT_NOCONN; - plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)"); - } -# endif /* USE_CONNECTED_NFS_SOCKETS */ - } -#endif /* MNT2_NFS_OPT_NOCONN */ - -#ifdef MNT2_NFS_OPT_RESVPORT -# ifdef MNTTAB_OPT_RESVPORT - if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL) - nap->flags |= MNT2_NFS_OPT_RESVPORT; -# else /* not MNTTAB_OPT_RESVPORT */ - nap->flags |= MNT2_NFS_OPT_RESVPORT; -# endif /* not MNTTAB_OPT_RESVPORT */ -#endif /* MNT2_NFS_OPT_RESVPORT */ /************************************************************************/ /*** OTHER FLAGS AND OPTIONS ***/ /************************************************************************/ +#ifdef MNT2_NFS_OPT_BIODS + if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS))) + nap->flags |= MNT2_NFS_OPT_BIODS; +#endif /* MNT2_NFS_OPT_BIODS */ + +#ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */ + if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL))) + nap->args.flags |= MNT2_NFS_OPT_SYMTTL; +#endif /* MNTTAB_OPT_SYMTTL */ + +#ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */ + if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH))) + nap->args.flags |= MNT2_NFS_OPT_PGTHRESH; +#endif /* MNT2_NFS_OPT_PGTHRESH */ + +#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX) + if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) { + nap->flags |= MNT2_NFS_OPT_POSIX; +# ifdef HAVE_NFS_ARGS_T_PATHCONF + nap->pathconf = NULL; +# endif /* HAVE_NFS_ARGS_T_PATHCONF */ + } +#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */ + #ifdef HAVE_TRANSPORT_TYPE_TLI /* set up syncaddr field */ nap->syncaddr = (struct netbuf *) NULL; @@ -636,131 +1024,21 @@ compute_nfs_args(nfs_args_t *nap, if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) { plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args"); going_down(1); + return; } /* update the flags field for knconf */ - nap->flags |= MNT2_NFS_OPT_KNCONF; + nap->args.flags |= MNT2_NFS_OPT_KNCONF; #endif /* HAVE_TRANSPORT_TYPE_TLI */ #ifdef MNT2_NFS_OPT_FSNAME nap->fsname = fs_name; - nap->flags |= MNT2_NFS_OPT_FSNAME; + nap->args.flags |= MNT2_NFS_OPT_FSNAME; #endif /* MNT2_NFS_OPT_FSNAME */ - nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE); -#ifdef MNT2_NFS_OPT_RSIZE - if (nap->rsize) - nap->flags |= MNT2_NFS_OPT_RSIZE; -#endif /* MNT2_NFS_OPT_RSIZE */ - if (nfs_version == NFS_VERSION && nap->rsize > 8192) - nap->rsize = 8192; - nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE); -#ifdef MNT2_NFS_OPT_WSIZE - if (nap->wsize) - nap->flags |= MNT2_NFS_OPT_WSIZE; -#endif /* MNT2_NFS_OPT_WSIZE */ - if (nfs_version == NFS_VERSION && nap->wsize > 8192) - nap->wsize = 8192; - - nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO); -#ifdef MNT2_NFS_OPT_TIMEO - if (nap->timeo) - nap->flags |= MNT2_NFS_OPT_TIMEO; -#endif /* MNT2_NFS_OPT_TIMEO */ - - nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS); -#ifdef MNT2_NFS_OPT_RETRANS - if (nap->retrans) - nap->flags |= MNT2_NFS_OPT_RETRANS; -#endif /* MNT2_NFS_OPT_RETRANS */ - -#ifdef MNT2_NFS_OPT_BIODS - if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS))) - nap->flags |= MNT2_NFS_OPT_BIODS; -#endif /* MNT2_NFS_OPT_BIODS */ - -#ifdef MNT2_NFS_OPT_SOFT - if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL) - nap->flags |= MNT2_NFS_OPT_SOFT; -#endif /* MNT2_NFS_OPT_SOFT */ - -#ifdef MNT2_NFS_OPT_SPONGY - if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) { - nap->flags |= MNT2_NFS_OPT_SPONGY; - if (nap->flags & MNT2_NFS_OPT_SOFT) { - plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored"); - nap->flags &= ~MNT2_NFS_OPT_SOFT; - } - } -#endif /* MNT2_NFS_OPT_SPONGY */ - -#if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) - /* Ultrix has separate generic and NFS ro flags */ - if (genflags & MNT2_GEN_OPT_RONLY) - nap->flags |= MNT2_NFS_OPT_RONLY; -#endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */ - -#ifdef MNTTAB_OPT_INTR - if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL) - /* - * Either turn on the "allow interrupts" option, or - * turn off the "disallow interrupts" option" - */ -# ifdef MNT2_NFS_OPT_INTR - nap->flags |= MNT2_NFS_OPT_INTR; -# endif /* MNT2_NFS_OPT_INTR */ -# ifdef MNT2_NFS_OPT_NOINTR - nap->flags &= ~MNT2_NFS_OPT_NOINTR; -# endif /* MNT2_NFS_OPT_NOINTR */ -# ifdef MNT2_NFS_OPT_INT - nap->flags |= MNT2_NFS_OPT_INT; -# endif /* MNT2_NFS_OPT_INT */ -# ifdef MNT2_NFS_OPT_NOINT - nap->flags &= ~MNT2_NFS_OPT_NOINT; -# endif /* MNT2_NFS_OPT_NOINT */ -#endif /* MNTTAB_OPT_INTR */ - -#ifdef MNTTAB_OPT_NODEVS - if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL) - nap->flags |= MNT2_NFS_OPT_NODEVS; -#endif /* MNTTAB_OPT_NODEVS */ - -#ifdef MNTTAB_OPT_COMPRESS - if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL) - nap->flags |= MNT2_NFS_OPT_COMPRESS; -#endif /* MNTTAB_OPT_COMPRESS */ - -#ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */ - if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL) - nap->flags |= MNT2_NFS_OPT_PRIVATE; -#endif /* MNTTAB_OPT_PRIVATE */ - -#ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */ - if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL))) - nap->flags |= MNT2_NFS_OPT_SYMTTL; -#endif /* MNTTAB_OPT_SYMTTL */ - -#ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */ - if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH))) - nap->flags |= MNT2_NFS_OPT_PGTHRESH; -#endif /* MNT2_NFS_OPT_PGTHRESH */ - -#if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) - if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL) - nap->flags |= MNT2_NFS_OPT_NOCTO; -#endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */ - -#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX) - if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) { - nap->flags |= MNT2_NFS_OPT_POSIX; - nap->pathconf = NULL; - } -#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */ - -#if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) - if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL) - nap->flags |= MNT2_NFS_OPT_PROPLIST; -#endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */ +#ifdef HAVE_NFS_ARGS_T_OPTSTR + nap->optstr = mntp->mnt_opts; +#endif /* HAVE_NFS_ARGS_T_OPTSTR */ #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS); @@ -768,20 +1046,6 @@ compute_nfs_args(nfs_args_t *nap, nap->flags |= MNT2_NFS_OPT_MAXGRPS; #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */ -#if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) - if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL) - nap->flags |= MNT2_NFS_OPT_NONLM; -#endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */ - -#if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) - if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL) - nap->flags |= MNT2_NFS_OPT_XLATECOOKIE; -#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */ - -#ifdef HAVE_NFS_ARGS_T_OPTSTR - nap->optstr = mntp->mnt_opts; -#endif /* HAVE_NFS_ARGS_T_OPTSTR */ - /************************************************************************/ /*** FINAL ACTIONS ***/ /************************************************************************/ @@ -794,6 +1058,378 @@ compute_nfs_args(nfs_args_t *nap, return; /* end of compute_nfs_args() function */ } +#ifdef HAVE_FS_NFS4 + +#define RPC_AUTH_GSS_KRB5 390003 +#define RPC_AUTH_GSS_KRB5I 390004 +#define RPC_AUTH_GSS_KRB5P 390005 +#define RPC_AUTH_GSS_LKEY 390006 +#define RPC_AUTH_GSS_LKEYI 390007 +#define RPC_AUTH_GSS_LKEYP 390008 +#define RPC_AUTH_GSS_SPKM 390009 +#define RPC_AUTH_GSS_SPKMI 390010 +#define RPC_AUTH_GSS_SPKMP 390011 + +struct { + const char *name; + int num; +} flavours[] = { + { "unix", AUTH_UNIX }, + { "krb5", RPC_AUTH_GSS_KRB5 }, + { "krb5i", RPC_AUTH_GSS_KRB5I }, + { "krb5p", RPC_AUTH_GSS_KRB5P }, + { "lkey", RPC_AUTH_GSS_LKEY }, + { "lkeyi", RPC_AUTH_GSS_LKEYI }, + { "lkeyp", RPC_AUTH_GSS_LKEYP }, + { "spkm", RPC_AUTH_GSS_SPKM }, + { "spkmi", RPC_AUTH_GSS_SPKMI }, + { "spkmp", RPC_AUTH_GSS_SPKMP }, +}; + +static char * +set_nfs4_security(nfs4_args_t *nap, mntent_t *mntp) +{ + const char *o = hasmnteq(mntp, MNTTAB_OPT_SEC); + char *q, *s, *ss; + size_t l, i; + + if (o == NULL) + o = "unix"; + + for (l = 1, q = strchr(o, ','); q; q = strchr(q + 1, ',')) + l++; + + nap->auth_flavours = xmalloc(l * sizeof(*nap->auth_flavours)); + + s = ss = xstrdup(o); + for (;;) { + q = strchr(s, ','); + if (q) + *q = '\0'; + + for (l = 0, i = 0; i < sizeof(flavours) / sizeof(flavours[0]); i++) + if (strcmp(flavours[i].name, s) == 0) { + nap->auth_flavours[l++] = flavours[i].num; + break; + } + + if (i == sizeof(flavours) / sizeof(flavours[0])) + plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %s\n", s); + + if (q == NULL) + break; + + *q = ':'; + s = ++q; + } + + nap->auth_flavourlen = l; + return ss; +} + +static int +get_my_ipv4addr(struct nfs_string *ns) +{ + struct hostent *hp; + char myname[MAXHOSTNAMELEN]; + + if (gethostname(myname, sizeof(myname)) == -1) + return -1; + if ((hp = gethostbyname(myname)) == NULL) + return -1; + if (inet_ntop(AF_INET, hp->h_addr, myname, sizeof(myname)) == NULL) + return -1; + ns->len = strlen(myname); + ns->data = xmalloc(ns->len + 1); + memcpy(ns->data, myname, ns->len + 1); + return 0; +} + +static void +add_nfs4_mntopts(const nfs4_args_t *nap, mntent_t *mntp, char *sec) +{ + char *opts = mntp->mnt_opts; + char buf[1024], addr[128]; + size_t len = strlen(mntp->mnt_opts); + + if (inet_ntop(AF_INET, + &((const struct sockaddr_in *)nap->host_addr)->sin_addr, + addr, sizeof(addr)) == NULL) + return; + + xsnprintf(buf, sizeof(buf), ",clientaddr=%s,addr=%s", nap->client_addr.data, + addr); + + len += strlen(buf) + 1; + + if (sec && strcmp(sec, "unix") != 0) { + len += strlen(sec) + strlen(MNTTAB_OPT_SEC) + 2; /* 2 = ",=" */ + } else + sec = NULL; + + opts = xrealloc(mntp->mnt_opts, len); + xstrlcat(opts, buf, len); + + if (sec) { + xstrlcat(opts, ",", len); + xstrlcat(opts, MNTTAB_OPT_SEC, len); + xstrlcat(opts, "=", len); + xstrlcat(opts, sec, len); + } + + mntp->mnt_opts = opts; +} + +static void +print_nfs4_security(const nfs4_args_t *nap) +{ + char buf[1024]; + char num[64]; + size_t i, j; + + buf[0] = '\0'; + + for (i = 0; i < nap->auth_flavourlen; i++) { + + for (j = 0; j < sizeof(flavours) / sizeof(flavours[0]); j++) + if (flavours[j].num == nap->auth_flavours[i]) { + xstrlcpy(num, flavours[j].name, sizeof(num)); + break; + } + + if (j == sizeof(flavours) / sizeof(flavours[0])) { + plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %d\n", + nap->auth_flavours[i]); + xsnprintf(num, sizeof(num), "*%d*", nap->auth_flavours[i]); + } + + if (buf[0]) + xstrlcat(buf, ":", sizeof(buf)); + + xstrlcat(buf, num, sizeof(buf)); + } + + plog(XLOG_DEBUG, "NA->auth_flavours \"%s\"\n", buf); +} + +static void +discard_nfs4_args(nfs4_args_t *nap) +{ + if (nap->client_addr.data) + free(nap->client_addr.data); + if (nap->hostname.data) + free(nap->hostname.data); + if (nap->mnt_path.data) + free(nap->mnt_path.data); + if (nap->host_addr) + free(nap->host_addr); + if (nap->auth_flavours) + free(nap->auth_flavours); +} + +/* + * Fill in the many possible fields and flags of struct nfs4_args. + * + * nap: pre-allocated structure to fill in. + * mntp: mount entry structure (includes options) + * genflags: generic mount flags already determined + * nfsncp: (TLI only) netconfig entry for this NFS mount + * ip_addr: IP address of file server + * nfs_version: 4, or 0 if unknown + * nfs_proto: "udp", "tcp", or NULL. + * fhp: file handle structure pointer + * host_name: name of remote NFS host + * fs_name: remote file system name to mount + */ +static void +compute_nfs4_args(nfs4_args_t *nap, + mntent_t *mntp, + int genflags, + struct netconfig *nfsncp, + struct sockaddr_in *ip_addr, + u_long nfs_version, + char *nfs_proto, + am_nfs_handle_t *fhp, + char *host_name, + char *fs_name) +{ + char *s; + struct nfs_common_args a; + uint16_t nfs_port; + + /* initialize just in case */ + memset((voidp) nap, 0, sizeof(nfs4_args_t)); + + /* compute all of the NFS attribute-cache flags */ + memset(&a, 0, sizeof(a)); + compute_nfs_attrcache_flags(&a, mntp); + compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version); + get_nfs_common_args(nap, a); + + get_my_ipv4addr(&nap->client_addr); + + /************************************************************************/ + /*** HOST NAME ***/ + /************************************************************************/ + nap->hostname.len = strlen(host_name); + nap->hostname.data = xmalloc(nap->hostname.len + 1); + memcpy(nap->hostname.data, host_name, nap->hostname.len + 1); + + if ((s = strchr(fs_name, ':')) != NULL) + s++; + else + s = fs_name; + + nap->mnt_path.len = strlen(s); + nap->mnt_path.data = xmalloc(nap->mnt_path.len + 1); + memcpy(nap->mnt_path.data, s, nap->mnt_path.len + 1); + plog(XLOG_DEBUG, "dir name %s\n", nap->mnt_path.data); + + /************************************************************************/ + /*** IP ADDRESS OF REMOTE HOST ***/ + /************************************************************************/ + nap->host_addrlen = sizeof(*ip_addr); + nap->host_addr = xmalloc(nap->host_addrlen); + memcpy(nap->host_addr, ip_addr, nap->host_addrlen); + + nfs_port = hasmntval(mntp, MNTTAB_OPT_PORT); + if (nfs_port == 0) + nfs_port = htons(NFS_PORT); + else + nfs_port = htons(nfs_port); + + ((struct sockaddr_in *)nap->host_addr)->sin_port = nfs_port; + + nap->proto = 0; /* bsdi3 sets this field to zero */ + if (nfs_proto) { + if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */ + nap->proto = IPPROTO_TCP; + else if (STREQ(nfs_proto, "udp")) + nap->proto = IPPROTO_UDP; + } + + nap->version = NFS4_MOUNT_VERSION; /* BSDI 3.0 and OpenBSD 2.2 */ + + /************************************************************************/ + /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/ + /************************************************************************/ + + + /************************************************************************/ + /*** OTHER FLAGS AND OPTIONS ***/ + /************************************************************************/ + +#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX) + if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) { + nap->args.flags |= MNT2_NFS_OPT_POSIX; +# ifdef HAVE_NFS_ARGS_T_PATHCONF + nap->pathconf = NULL; +# endif /* HAVE_NFS_ARGS_T_PATHCONF */ + } +#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */ + +#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) + nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS); + if (nap->maxgrouplist != 0) + nap->args.flags |= MNT2_NFS_OPT_MAXGRPS; +#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */ + +#ifdef HAVE_NFS_ARGS_T_OPTSTR + nap->optstr = mntp->mnt_opts; +#endif /* HAVE_NFS_ARGS_T_OPTSTR */ + + /************************************************************************/ + /*** FINAL ACTIONS ***/ + /************************************************************************/ + +#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS + /* Ultrix stores generic flags in nfs_args.gfs_flags. */ + nap->gfs_flags = genflags; +#endif /* HAVE_NFS_ARGS_T_FLAGS */ + + s = set_nfs4_security(nap, mntp); + + /* Add addresses to the mount options */ + add_nfs4_mntopts(nap, mntp, s); + + return; /* end of compute_nfs4_args() function */ +} + +#ifdef DEBUG +static void +print_nfs4_args(const nfs4_args_t *nap, u_long nfs_version) +{ + struct sockaddr_in *sap; + struct nfs_common_args a; + + if (!nap) { + plog(XLOG_DEBUG, "NULL nfs_args!"); + return; + } + + plog(XLOG_DEBUG, "NA->client_addr \"%s\"\n", nap->client_addr.data); + plog(XLOG_DEBUG, "NA->mnt_path = \"%s\"", nap->mnt_path.data); + plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname.data); + sap = (struct sockaddr_in *) nap->host_addr; + print_nfs_sockaddr_in("host_addr", sap); + plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto); +#ifdef HAVE_NFS_ARGS_T_VERSION + plog(XLOG_DEBUG, "NA->version = %d", nap->version); +#endif /* HAVE_NFS_ARGS_T_VERSION */ + print_nfs4_security(nap); + + put_nfs_common_args(nap, a); + print_nfs_common_args(&a); +} +#endif +#endif /* HAVE_FS_NFS4 */ + +void +compute_nfs_args(void *nap, + mntent_t *mntp, + int genflags, + struct netconfig *nfsncp, + struct sockaddr_in *ip_addr, + u_long nfs_version, + char *nfs_proto, + am_nfs_handle_t *fhp, + char *host_name, + char *fs_name) +{ +#ifdef HAVE_FS_NFS4 + if (nfs_version == NFS_VERSION4) + compute_nfs4_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version, + nfs_proto, fhp, host_name, fs_name); + else +#endif /* HAVE_FS_NFS4 */ + compute_nfs23_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version, + nfs_proto, fhp, host_name, fs_name); +} + +void +discard_nfs_args(void *nap, u_long nfs_version) +{ +#ifdef HAVE_FS_NFS4 + if (nfs_version == NFS_VERSION4) + discard_nfs4_args(nap); + else +#endif /* HAVE_FS_NFS4 */ + discard_nfs23_args(nap); +} + +#ifdef DEBUG +void +print_nfs_args(const void *nap, u_long nfs_version) +{ +#ifdef HAVE_FS_NFS4 + if (nfs_version == NFS_VERSION4) + print_nfs4_args(nap, nfs_version); + else +#endif /* HAVE_FS_NFS4 */ + print_nfs23_args(nap, nfs_version); +} +#endif + /* * Fill in special values for flags and fields of nfs_args, for an @@ -802,6 +1438,8 @@ compute_nfs_args(nfs_args_t *nap, void compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp) { + struct nfs_common_args a; + #ifdef MNT2_NFS_OPT_SYMTTL /* * Don't let the kernel cache symbolic links we generate, or else lookups @@ -837,7 +1475,10 @@ compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp) #endif /* MNT2_NFS_OPT_DUMBTIMR */ /* compute all of the NFS attribute-cache flags */ - compute_nfs_attrcache_flags(nap, mntp); + memset(&a, 0, sizeof(a)); + a.flags = nap->flags; + compute_nfs_attrcache_flags(&a, mntp); + get_nfs_common_args(nap, a); /* * Provide a slight bit more security by requiring the kernel to use @@ -848,156 +1489,8 @@ compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp) #endif /* MNT2_NFS_OPT_RESVPORT */ } - -#ifdef DEBUG -/* get string version (in hex) of identifier */ -static char * -get_hex_string(u_int len, const char *fhdata) +int +nfs_valid_version(u_long v) { - u_int i; - static char buf[128]; /* better not go over it! */ - char str[16]; - short int arr[64]; - - if (!fhdata) - return NULL; - buf[0] = '\0'; - memset(&arr[0], 0, (64 * sizeof(short int))); - memcpy(&arr[0], &fhdata[0], len); - for (i=0; i= NFS_VERS_MIN && v <= NFS_VERS_MAX; } - - -/* - * print a subset of fields from "struct nfs_args" that are otherwise - * not being provided anywhere else. - */ -void -print_nfs_args(const nfs_args_t *nap, u_long nfs_version) -{ - int fhlen = 32; /* default: NFS V.2 file handle length is 32 */ -#ifdef HAVE_TRANSPORT_TYPE_TLI - struct netbuf *nbp; - struct knetconfig *kncp; -#else /* not HAVE_TRANSPORT_TYPE_TLI */ - struct sockaddr_in *sap; -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ - - if (!nap) { - plog(XLOG_DEBUG, "NULL nfs_args!"); - return; - } - - /* override default file handle size */ -#ifdef FHSIZE - fhlen = FHSIZE; -#endif /* FHSIZE */ -#ifdef NFS_FHSIZE - fhlen = NFS_FHSIZE; -#endif /* NFS_FHSIZE */ - -#ifdef HAVE_TRANSPORT_TYPE_TLI - nbp = nap->addr; - plog(XLOG_DEBUG, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"", - nbp->maxlen, nbp->len, - get_hex_string(nbp->len, nbp->buf)); - nbp = nap->syncaddr; - plog(XLOG_DEBUG, "NA->syncaddr {netbuf} %p", nbp); - kncp = nap->knconf; - plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (u_long) kncp->knc_semantics); - plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly); - plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto); - plog(XLOG_DEBUG, "NA->knconf->rdev %lu", (u_long) kncp->knc_rdev); - /* don't print knconf->unused field */ -#else /* not HAVE_TRANSPORT_TYPE_TLI */ -# ifdef NFS_ARGS_T_ADDR_IS_POINTER - sap = (struct sockaddr_in *) nap->addr; -# else /* not NFS_ARGS_T_ADDR_IS_POINTER */ - sap = (struct sockaddr_in *) &nap->addr; -# endif /* not NFS_ARGS_T_ADDR_IS_POINTER */ - plog(XLOG_DEBUG, "NA->addr {sockaddr_in} (len=%d) = \"%s\"", - (int) sizeof(struct sockaddr_in), - get_hex_string(sizeof(struct sockaddr_in), (const char *)sap)); -#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - /* as per POSIX, sin_len need not be set (used internally by kernel) */ - plog(XLOG_DEBUG, "NA->addr.sin_len = %d", sap->sin_len); -#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ - plog(XLOG_DEBUG, "NA->addr.sin_family = %d", sap->sin_family); - plog(XLOG_DEBUG, "NA->addr.sin_port = %d", sap->sin_port); - plog(XLOG_DEBUG, "NA->addr.sin_addr = \"%s\"", - get_hex_string(sizeof(struct in_addr), (const char *) &sap->sin_addr)); -#endif /* not HAVE_TRANSPORT_TYPE_TLI */ -#ifdef HAVE_NFS_ARGS_T_ADDRLEN - plog(XLOG_DEBUG, "NA->addrlen = %d", nap->addrlen); -#endif /* ifdef HAVE_NFS_ARGS_T_ADDRLEN */ - - plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null"); -#ifdef HAVE_NFS_ARGS_T_NAMLEN - plog(XLOG_DEBUG, "NA->namlen = %d", nap->namlen); -#endif /* HAVE_NFS_ARGS_T_NAMLEN */ - -#ifdef MNT2_NFS_OPT_FSNAME - plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null"); -#endif /* MNT2_NFS_OPT_FSNAME */ - -#ifdef HAVE_NFS_ARGS_T_FHSIZE - plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize); - fhlen = nap->fhsize; -#endif /* HAVE_NFS_ARGS_T_FHSIZE */ -#ifdef HAVE_NFS_ARGS_T_FH_LEN - plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len); - fhlen = nap->fh_len; -#endif /* HAVE_NFS_ARGS_T_FH_LEN */ - - /* - * XXX: need to figure out how to correctly print file handles, - * since some times they are pointers, and sometimes the real structure - * is stored in nfs_args. Even if it is a pointer, it can be the actual - * char[] array, or a structure containing multiple fields. - */ - plog(XLOG_DEBUG, "NA->filehandle = \"%s\"", - get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD)); - -#ifdef HAVE_NFS_ARGS_T_SOTYPE - plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype); -#endif /* HAVE_NFS_ARGS_T_SOTYPE */ -#ifdef HAVE_NFS_ARGS_T_PROTO - plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto); -#endif /* HAVE_NFS_ARGS_T_PROTO */ -#ifdef HAVE_NFS_ARGS_T_VERSION - plog(XLOG_DEBUG, "NA->version = %d", nap->version); -#endif /* HAVE_NFS_ARGS_T_VERSION */ - - plog(XLOG_DEBUG, "NA->flags = 0x%x", (int) nap->flags); - - plog(XLOG_DEBUG, "NA->rsize = %d", (int) nap->rsize); - plog(XLOG_DEBUG, "NA->wsize = %d", (int) nap->wsize); -#ifdef HAVE_NFS_ARGS_T_BSIZE - plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize); -#endif /* HAVE_NFS_ARGS_T_BSIZE */ - plog(XLOG_DEBUG, "NA->timeo = %d", (int) nap->timeo); - plog(XLOG_DEBUG, "NA->retrans = %d", (int) nap->retrans); - -#ifdef HAVE_NFS_ARGS_T_ACREGMIN - plog(XLOG_DEBUG, "NA->acregmin = %d", (int) nap->acregmin); - plog(XLOG_DEBUG, "NA->acregmax = %d", (int) nap->acregmax); - plog(XLOG_DEBUG, "NA->acdirmin = %d", (int) nap->acdirmin); - plog(XLOG_DEBUG, "NA->acdirmax = %d", (int) nap->acdirmax); -#endif /* HAVE_NFS_ARGS_T_ACREGMIN */ -#ifdef MNTTAB_OPT_SYMTTL - plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl); -#endif /* MNTTAB_OPT_SYMTTL */ -#ifdef MNTTAB_OPT_PG_THRESH - plog(XLOG_DEBUG, "NA->pg_thresh = %d", nap->pg_thresh); -#endif /* MNTTAB_OPT_PG_THRESH */ - -#ifdef MNT2_NFS_OPT_BIODS - plog(XLOG_DEBUG, "NA->biods = %d", nap->biods); -#endif /* MNT2_NFS_OPT_BIODS */ - -} -#endif /* DEBUG */ diff --git a/contrib/amd/libamu/mtab.c b/contrib/amd/libamu/mtab.c index 50ba994733f..ee603af3435 100644 --- a/contrib/amd/libamu/mtab.c +++ b/contrib/amd/libamu/mtab.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -233,9 +229,9 @@ hasmntstr(mntent_t *mnt, char *opt) char *endptr = strchr(eq, ','); - /* if saw no comma, return strdup'd string */ + /* if saw no comma, return xstrdup'd string */ if (!endptr) - return strdup(eq); + return xstrdup(eq); else { /* else we need to copy only the chars needed */ int len = endptr - eq; diff --git a/contrib/amd/libamu/nfs_prot_xdr.c b/contrib/amd/libamu/nfs_prot_xdr.c index df8a0b006b5..bfdc7b2492a 100644 --- a/contrib/amd/libamu/nfs_prot_xdr.c +++ b/contrib/amd/libamu/nfs_prot_xdr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -56,3 +52,14 @@ xdr_amq_string(XDR *xdrs, amq_string *objp) } return (TRUE); } + + +bool_t +xdr_amq_sync_umnt(XDR *xdrs, amq_sync_umnt *objp) +{ + + if (!xdr_opaque(xdrs, (char *) objp, sizeof(*objp))) { + return (FALSE); + } + return (TRUE); +} diff --git a/contrib/amd/libamu/strerror.c b/contrib/amd/libamu/strerror.c index 49dd2fc3ce9..faf2916f31e 100644 --- a/contrib/amd/libamu/strerror.c +++ b/contrib/amd/libamu/strerror.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002-2006 Ion Badulescu - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 2002-2014 Ion Badulescu + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -17,11 +17,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * diff --git a/contrib/amd/libamu/strutil.c b/contrib/amd/libamu/strutil.c index 5a1e759bff6..03a8e88f608 100644 --- a/contrib/amd/libamu/strutil.c +++ b/contrib/amd/libamu/strutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -268,3 +264,37 @@ xvsnprintf(char *str, size_t size, const char *format, va_list ap) return ret; } + +static size_t +vstrlen(const char *src, va_list ap) +{ + size_t len = strlen(src); + while ((src = va_arg(ap, const char *)) != NULL) + len += strlen(src); + return len; +} + +static void +vstrcpy(char *dst, const char *src, va_list ap) +{ + strcpy(dst, src); + while ((src = va_arg(ap, const char *)) != NULL) + strcat(dst, src); +} + +char * +strvcat(const char *src, ...) +{ + size_t len; + char *dst; + va_list ap; + + va_start(ap, src); + len = vstrlen(src, ap); + va_end(ap); + dst = xmalloc(len + 1); + va_start(ap, src); + vstrcpy(dst, src, ap); + va_end(ap); + return dst; +} diff --git a/contrib/amd/libamu/wire.c b/contrib/amd/libamu/wire.c index c1852cdca7f..c9da0fe276a 100644 --- a/contrib/amd/libamu/wire.c +++ b/contrib/amd/libamu/wire.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -226,7 +222,7 @@ getwire_lookup(u_long address, u_long netmask, int ishost) } /* fill in network number (string) */ - al->ip_net_num = strdup(netNumberBuf); + al->ip_net_num = xstrdup(netNumberBuf); if (np != NULL) s = np->n_name; @@ -242,7 +238,7 @@ getwire_lookup(u_long address, u_long netmask, int ishost) } /* fill in network name (string) */ - al->ip_net_name = strdup(s); + al->ip_net_name = xstrdup(s); /* Let's be cautious here about buffer overflows -Ion */ if (strlen(s) > MAXHOSTNAMELEN) { al->ip_net_name[MAXHOSTNAMELEN] = '\0'; @@ -318,9 +314,14 @@ is_network_member(const char *net) if (STREQ(net, al->ip_net_name) || STREQ(net, al->ip_net_num)) return TRUE; } else { - char *netstr = strdup(net), *maskstr; + char *netstr = xstrdup(net), *maskstr; u_long netnum, masknum = 0; maskstr = strchr(netstr, '/'); + if (maskstr == NULL) { + plog(XLOG_ERROR, "%s: netstr %s does not have a `/'", __func__, netstr); + XFREE(netstr); + return FALSE; + } maskstr[0] = '\0'; /* null terminate netstr */ maskstr++; if (*maskstr == '\0') /* if empty string, make it NULL */ diff --git a/contrib/amd/libamu/xdr_func.c b/contrib/amd/libamu/xdr_func.c index 6bd0254318c..e437dd49d56 100644 --- a/contrib/amd/libamu/xdr_func.c +++ b/contrib/amd/libamu/xdr_func.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -951,7 +947,6 @@ xdr_am_mountres3_ok(XDR *xdrs, am_mountres3_ok *objp) return (TRUE); } - bool_t xdr_am_mountres3(XDR *xdrs, am_mountres3 *objp) { @@ -968,6 +963,78 @@ xdr_am_mountres3(XDR *xdrs, am_mountres3 *objp) return (TRUE); } +bool_t +xdr_am_cookieverf3(XDR *xdrs, am_cookieverf3 objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_cookieverf3:"); + + if (!xdr_opaque(xdrs, objp, AM_NFS3_COOKIEVERFSIZE)) + return FALSE; + return TRUE; +} + +#if 0 +/* In FreeBSD xdr_uint64() is defined in ../../../include/rpcsvc/nfs_prot.x */ +/* + * Not ideal, xdr_u_int64_t() is not defined in Linux glibc RPC + * but xdr_u_quad_t() is. But in libtirpc xdr_u_quad_t() is not + * defined and xdr_u_int64_t() is. So xdr_u_int64_t() is probably + * an expected standard xdr function so, if it isn't defined use + * an internal xdr_u_int64_t() that uses xdr_u_quad_t(). + */ +#ifndef HAVE_XDR_U_INT64_T +#define xdr_u_int64_t(xdrs, objp) xdr_u_quad_t(xdrs, objp) +#endif /* HAVE_XDR_U_INT64_T */ + +bool_t +xdr_uint64(XDR *xdrs, uint64 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_uint64:"); + + if (!xdr_u_int64_t(xdrs, objp)) + return FALSE; + return TRUE; +} +#endif + +bool_t +xdr_am_cookie3(XDR *xdrs, am_cookie3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_cookie3:"); + + if (!xdr_uint64(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_nfs_fh3:"); + + if (!xdr_u_int(xdrs, &objp->am_fh3_length)) + return (FALSE); + if (objp->am_fh3_length > AM_FHSIZE3) + return (FALSE); + if (!xdr_opaque(xdrs, objp->am_fh3_data, objp->am_fh3_length)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_am_nfsstat3(XDR *xdrs, am_nfsstat3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_nfsstat3:"); + + if (!xdr_enum(xdrs, (enum_t *)objp)) + return (FALSE); + return (TRUE); +} bool_t xdr_am_diropargs3(XDR *xdrs, am_diropargs3 *objp) @@ -982,7 +1049,6 @@ xdr_am_diropargs3(XDR *xdrs, am_diropargs3 *objp) return (TRUE); } - bool_t xdr_am_filename3(XDR *xdrs, am_filename3 *objp) { @@ -994,6 +1060,315 @@ xdr_am_filename3(XDR *xdrs, am_filename3 *objp) return (TRUE); } +bool_t +xdr_am_ftype3(XDR *xdrs, am_ftype3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_ftype3:"); + + if (!xdr_enum(xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_mode3(XDR *xdrs, am_mode3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_mode3:"); + + if (!xdr_u_int(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_uid3(XDR *xdrs, am_uid3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_uid3:"); + + if (!xdr_u_int(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_gid3(XDR *xdrs, am_gid3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_gid3:"); + + if (!xdr_u_int(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_size3(XDR *xdrs, am_size3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_size3:"); + + if (!xdr_uint64(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_fileid3(XDR *xdrs, am_fileid3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_fileid3:"); + + if (!xdr_uint64(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_specdata3(XDR *xdrs, am_specdata3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_specdata3:"); + + if (!xdr_u_int(xdrs, &objp->specdata1)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->specdata2)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_nfstime3(XDR *xdrs, am_nfstime3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_nfstime3:"); + + if (!xdr_u_int(xdrs, &objp->seconds)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->nseconds)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_fattr3(XDR *xdrs, am_fattr3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_fattr3:"); + + if (!xdr_am_ftype3(xdrs, &objp->type)) + return FALSE; + if (!xdr_am_mode3(xdrs, &objp->mode)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->nlink)) + return FALSE; + if (!xdr_am_uid3(xdrs, &objp->uid)) + return FALSE; + if (!xdr_am_gid3(xdrs, &objp->gid)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->size)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->used)) + return FALSE; + if (!xdr_am_specdata3(xdrs, &objp->rdev)) + return FALSE; + if (!xdr_uint64(xdrs, &objp->fsid)) + return FALSE; + if (!xdr_am_fileid3(xdrs, &objp->fileid)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->atime)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->mtime)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->ctime)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_post_op_attr(XDR *xdrs, am_post_op_attr *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_post_op_attr:"); + + if (!xdr_bool(xdrs, &objp->attributes_follow)) + return FALSE; + switch (objp->attributes_follow) { + case TRUE: + if (!xdr_am_fattr3(xdrs, &objp->am_post_op_attr_u.attributes)) + return FALSE; + break; + case FALSE: + break; + default: + return FALSE; + } + return TRUE; +} + +bool_t +xdr_am_stable_how(XDR *xdrs, am_stable_how *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_stable_how:"); + + if (!xdr_enum(xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_offset3(XDR *xdrs, am_offset3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_offset3:"); + + if (!xdr_uint64(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_count3(XDR *xdrs, am_count3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_count3:"); + + if (!xdr_u_int(xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_wcc_attr(XDR *xdrs, am_wcc_attr *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_wcc_attr:"); + + if (!xdr_am_size3(xdrs, &objp->size)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->mtime)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->ctime)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_pre_op_attr(XDR *xdrs, am_pre_op_attr *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, ":xdr_am_pre_op_attr"); + + if (!xdr_bool(xdrs, &objp->attributes_follow)) + return FALSE; + switch (objp->attributes_follow) { + case TRUE: + if (!xdr_am_wcc_attr(xdrs, &objp->am_pre_op_attr_u.attributes)) + return FALSE; + break; + case FALSE: + break; + default: + return FALSE; + } + return TRUE; +} + +bool_t +xdr_am_wcc_data(XDR *xdrs, am_wcc_data *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_wcc_data:"); + + if (!xdr_am_pre_op_attr(xdrs, &objp->before)) + return FALSE; + if (!xdr_am_post_op_attr(xdrs, &objp->after)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_WRITE3args(XDR *xdrs, am_WRITE3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_WRITE3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->file)) + return FALSE; + if (!xdr_am_offset3(xdrs, &objp->offset)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->count)) + return FALSE; + if (!xdr_am_stable_how(xdrs, &objp->stable)) + return FALSE; + if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, + (u_int *) &objp->data.data_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_writeverf3(XDR *xdrs, am_writeverf3 objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_writeverf3:"); + + if (!xdr_opaque(xdrs, objp, AM_NFS3_WRITEVERFSIZE)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_WRITE3resok(XDR *xdrs, am_WRITE3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_WRITE3resok:"); + + if (!xdr_am_wcc_data(xdrs, &objp->file_wcc)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->count)) + return FALSE; + if (!xdr_am_stable_how(xdrs, &objp->committed)) + return FALSE; + if (!xdr_am_writeverf3(xdrs, objp->verf)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_WRITE3resfail(XDR *xdrs, am_WRITE3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_WRITE3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->file_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_WRITE3res(XDR *xdrs, am_WRITE3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_WRITE3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_WRITE3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_WRITE3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} bool_t xdr_am_LOOKUP3args(XDR *xdrs, am_LOOKUP3args *objp) @@ -1006,7 +1381,6 @@ xdr_am_LOOKUP3args(XDR *xdrs, am_LOOKUP3args *objp) return (TRUE); } - bool_t xdr_am_LOOKUP3res(XDR *xdrs, am_LOOKUP3res *objp) { @@ -1028,25 +1402,17 @@ xdr_am_LOOKUP3res(XDR *xdrs, am_LOOKUP3res *objp) return (TRUE); } - bool_t xdr_am_LOOKUP3resfail(XDR *xdrs, am_LOOKUP3resfail *objp) { if (amuDebug(D_XDRTRACE)) plog(XLOG_DEBUG, "xdr_am_LOOKUP3resfail:"); - /* - * Don't xdr post_op_attr: amd doesn't need them, but they require many - * additional xdr functions. - */ -#if 0 - if (!xdr_post_op_attr(xdrs, &objp->dir_attributes)) + if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes)) return (FALSE); -#endif return (TRUE); } - bool_t xdr_am_LOOKUP3resok(XDR *xdrs, am_LOOKUP3resok *objp) { @@ -1055,44 +1421,1656 @@ xdr_am_LOOKUP3resok(XDR *xdrs, am_LOOKUP3resok *objp) if (!xdr_am_nfs_fh3(xdrs, &objp->object)) return (FALSE); - /* - * Don't xdr post_op_attr: amd doesn't need them, but they require many - * additional xdr functions. - */ -#if 0 - if (!xdr_post_op_attr(xdrs, &objp->obj_attributes)) + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) return (FALSE); - if (!xdr_post_op_attr(xdrs, &objp->dir_attributes)) + if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes)) return (FALSE); -#endif return (TRUE); } - bool_t -xdr_am_nfs_fh3(XDR *xdrs, am_nfs_fh3 *objp) +xdr_am_COMMIT3args(XDR *xdrs, am_COMMIT3args *objp) { if (amuDebug(D_XDRTRACE)) - plog(XLOG_DEBUG, "xdr_am_nfs_fh3:"); + plog(XLOG_DEBUG, "xdr_am_COMMIT3args:"); - if (!xdr_u_int(xdrs, &objp->am_fh3_length)) - return (FALSE); - if (objp->am_fh3_length > AM_FHSIZE3) - return (FALSE); - if (!xdr_opaque(xdrs, objp->am_fh3_data, objp->am_fh3_length)) - return (FALSE); - return (TRUE); + if (!xdr_am_nfs_fh3(xdrs, &objp->file)) + return FALSE; + if (!xdr_am_offset3(xdrs, &objp->offset)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->count)) + return FALSE; + return TRUE; } - bool_t -xdr_am_nfsstat3(XDR *xdrs, am_nfsstat3 *objp) +xdr_am_COMMIT3resok(XDR *xdrs, am_COMMIT3resok *objp) { if (amuDebug(D_XDRTRACE)) - plog(XLOG_DEBUG, "xdr_am_nfsstat3:"); + plog(XLOG_DEBUG, "xdr_am_COMMIT3resok:"); - if (!xdr_enum(xdrs, (enum_t *)objp)) - return (FALSE); - return (TRUE); + if (!xdr_am_wcc_data(xdrs, &objp->file_wcc)) + return FALSE; + if (!xdr_am_writeverf3(xdrs, objp->verf)) + return FALSE; + return TRUE; } -#endif /* not HAVE_FS_NFS3 */ + +bool_t +xdr_am_COMMIT3resfail(XDR *xdrs, am_COMMIT3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_COMMIT3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->file_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_COMMIT3res(XDR *xdrs, am_COMMIT3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_COMMIT3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_COMMIT3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_COMMIT3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_ACCESS3args(XDR *xdrs, am_ACCESS3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_ACCESS3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->object)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->access)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_ACCESS3resok(XDR *xdrs, am_ACCESS3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_ACCESS3resok:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->access)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_ACCESS3resfail(XDR *xdrs, am_ACCESS3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_ACCESS3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_ACCESS3res(XDR *xdrs, am_ACCESS3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_ACCESS3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_ACCESS3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_ACCESS3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_GETATTR3args(XDR *xdrs, am_GETATTR3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_GETATTR3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->object)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_GETATTR3resok(XDR *xdrs, am_GETATTR3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_GETATTR3resok:"); + + if (!xdr_am_fattr3(xdrs, &objp->obj_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_GETATTR3res(XDR *xdrs, am_GETATTR3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_GETATTR3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_GETATTR3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_time_how(XDR *xdrs, am_time_how *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_time_how:"); + + if (!xdr_enum(xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_set_mode3(XDR *xdrs, am_set_mode3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_set_mode3:"); + + if (!xdr_bool(xdrs, &objp->set_it)) + return FALSE; + switch (objp->set_it) { + case TRUE: + if (!xdr_am_mode3(xdrs, &objp->am_set_mode3_u.mode)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_set_uid3(XDR *xdrs, am_set_uid3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_set_uid3:"); + + if (!xdr_bool(xdrs, &objp->set_it)) + return FALSE; + switch (objp->set_it) { + case TRUE: + if (!xdr_am_uid3(xdrs, &objp->am_set_uid3_u.uid)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_set_gid3(XDR *xdrs, am_set_gid3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_set_gid3:"); + + if (!xdr_bool(xdrs, &objp->set_it)) + return FALSE; + switch (objp->set_it) { + case TRUE: + if (!xdr_am_gid3(xdrs, &objp->am_set_gid3_u.gid)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_set_size3(XDR *xdrs, am_set_size3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_set_size3:"); + + if (!xdr_bool(xdrs, &objp->set_it)) + return FALSE; + switch (objp->set_it) { + case TRUE: + if (!xdr_am_size3(xdrs, &objp->am_set_size3_u.size)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_set_atime(XDR *xdrs, am_set_atime *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_set_atime:"); + + if (!xdr_am_time_how(xdrs, &objp->set_it)) + return FALSE; + switch (objp->set_it) { + case AM_SET_TO_CLIENT_TIME: + if (!xdr_am_nfstime3(xdrs, &objp->am_set_atime_u.atime)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_set_mtime(XDR *xdrs, am_set_mtime *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_set_mtime:"); + + if (!xdr_am_time_how(xdrs, &objp->set_it)) + return FALSE; + switch (objp->set_it) { + case AM_SET_TO_CLIENT_TIME: + if (!xdr_am_nfstime3(xdrs, &objp->am_set_mtime_u.mtime)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_sattr3(XDR *xdrs, am_sattr3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_sattr3:"); + + if (!xdr_am_set_mode3(xdrs, &objp->mode)) + return FALSE; + if (!xdr_am_set_uid3(xdrs, &objp->uid)) + return FALSE; + if (!xdr_am_set_gid3(xdrs, &objp->gid)) + return FALSE; + if (!xdr_am_set_size3(xdrs, &objp->size)) + return FALSE; + if (!xdr_am_set_atime(xdrs, &objp->atime)) + return FALSE; + if (!xdr_am_set_mtime(xdrs, &objp->mtime)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_createmode3(XDR *xdrs, am_createmode3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_createmode3:"); + + if (!xdr_enum(xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_createverf3(XDR *xdrs, am_createverf3 objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_createverf3:"); + + if (!xdr_opaque(xdrs, objp, AM_NFS3_CREATEVERFSIZE)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_createhow3(XDR *xdrs, am_createhow3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_createhow3:"); + + if (!xdr_am_createmode3(xdrs, &objp->mode)) + return FALSE; + switch (objp->mode) { + case AM_UNCHECKED: + if (!xdr_am_sattr3(xdrs, &objp->am_createhow3_u.obj_attributes)) + return FALSE; + break; + case AM_GUARDED: + if (!xdr_am_sattr3(xdrs, &objp->am_createhow3_u.g_obj_attributes)) + return FALSE; + break; + case AM_EXCLUSIVE: + if (!xdr_am_createverf3(xdrs, objp->am_createhow3_u.verf)) + return FALSE; + break; + default: + return FALSE; + } + return TRUE; +} + +bool_t +xdr_am_CREATE3args(XDR *xdrs, am_CREATE3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_CREATE3args:"); + + if (!xdr_am_diropargs3(xdrs, &objp->where)) + return FALSE; + if (!xdr_am_createhow3(xdrs, &objp->how)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_post_op_fh3(XDR *xdrs, am_post_op_fh3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_post_op_fh3:"); + + if (!xdr_bool(xdrs, &objp->handle_follows)) + return FALSE; + switch (objp->handle_follows) { + case TRUE: + if (!xdr_am_nfs_fh3(xdrs, &objp->am_post_op_fh3_u.handle)) + return FALSE; + break; + case FALSE: + break; + default: + return FALSE; + } + return TRUE; +} + +bool_t +xdr_am_CREATE3resok(XDR *xdrs, am_CREATE3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_CREATE3resok:"); + + if (!xdr_am_post_op_fh3(xdrs, &objp->obj)) + return FALSE; + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_CREATE3resfail(XDR *xdrs, am_CREATE3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_CREATE3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_CREATE3res(XDR *xdrs, am_CREATE3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_CREATE3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_CREATE3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_CREATE3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_REMOVE3args(XDR *xdrs, am_REMOVE3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_REMOVE3args:"); + + if (!xdr_am_diropargs3(xdrs, &objp->object)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_REMOVE3resok(XDR *xdrs, am_REMOVE3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_REMOVE3resok:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_REMOVE3resfail(XDR *xdrs, am_REMOVE3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_REMOVE3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_REMOVE3res(XDR *xdrs, am_REMOVE3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_REMOVE3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_REMOVE3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_REMOVE3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_READ3args(XDR *xdrs, am_READ3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READ3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->file)) + return FALSE; + if (!xdr_am_offset3(xdrs, &objp->offset)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->count)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READ3resok(XDR *xdrs, am_READ3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READ3resok:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->count)) + return FALSE; + if (!xdr_bool(xdrs, &objp->eof)) + return FALSE; + if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READ3resfail(XDR *xdrs, am_READ3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READ3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READ3res(XDR *xdrs, am_READ3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READ3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_READ3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_READ3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_FSINFO3args(XDR *xdrs, am_FSINFO3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSINFO3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->fsroot)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_FSINFO3resok(XDR *xdrs, am_FSINFO3resok *objp) +{ + register int32_t *buf; + + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSINFO3resok:"); + + if (xdrs->x_op == XDR_ENCODE) { + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + buf = XDR_INLINE(xdrs, 7 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_int(xdrs, &objp->rtmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->rtpref)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->rtmult)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtpref)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtmult)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->dtpref)) + return FALSE; + } else { + IXDR_PUT_U_LONG(buf, objp->rtmax); + IXDR_PUT_U_LONG(buf, objp->rtpref); + IXDR_PUT_U_LONG(buf, objp->rtmult); + IXDR_PUT_U_LONG(buf, objp->wtmax); + IXDR_PUT_U_LONG(buf, objp->wtpref); + IXDR_PUT_U_LONG(buf, objp->wtmult); + IXDR_PUT_U_LONG(buf, objp->dtpref); + } + if (!xdr_am_size3(xdrs, &objp->maxfilesize)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->time_delta)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->properties)) + return FALSE; + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + buf = XDR_INLINE(xdrs, 7 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_int (xdrs, &objp->rtmax)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rtpref)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->rtmult)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->wtmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtpref)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtmult)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->dtpref)) + return FALSE; + } else { + objp->rtmax = IXDR_GET_U_LONG(buf); + objp->rtpref = IXDR_GET_U_LONG(buf); + objp->rtmult = IXDR_GET_U_LONG(buf); + objp->wtmax = IXDR_GET_U_LONG(buf); + objp->wtpref = IXDR_GET_U_LONG(buf); + objp->wtmult = IXDR_GET_U_LONG(buf); + objp->dtpref = IXDR_GET_U_LONG(buf); + } + if (!xdr_am_size3(xdrs, &objp->maxfilesize)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->time_delta)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->properties)) + return FALSE; + return TRUE; + } + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->rtmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->rtpref)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->rtmult)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtpref)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->wtmult)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->dtpref)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->maxfilesize)) + return FALSE; + if (!xdr_am_nfstime3(xdrs, &objp->time_delta)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->properties)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_FSINFO3resfail(XDR *xdrs, am_FSINFO3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSINFO3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_FSINFO3res(XDR *xdrs, am_FSINFO3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSINFO3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_FSINFO3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_FSINFO3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_FSSTAT3args(XDR *xdrs, am_FSSTAT3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSSTAT3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->fsroot)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_FSSTAT3resok(XDR *xdrs, am_FSSTAT3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSSTAT3resok:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->tbytes)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->fbytes)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->abytes)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->tfiles)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->ffiles)) + return FALSE; + if (!xdr_am_size3(xdrs, &objp->afiles)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->invarsec)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_FSSTAT3resfail(XDR *xdrs, am_FSSTAT3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSSTAT3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_FSSTAT3res(XDR *xdrs, am_FSSTAT3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_FSSTAT3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_FSSTAT3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_FSSTAT3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_PATHCONF3args(XDR *xdrs, am_PATHCONF3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_PATHCONF3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->object)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_PATHCONF3resok(XDR *xdrs, am_PATHCONF3resok *objp) +{ + register int32_t *buf; + + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_PATHCONF3resok:"); + + if (xdrs->x_op == XDR_ENCODE) { + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_int(xdrs, &objp->linkmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->name_max)) + return FALSE; + if (!xdr_bool(xdrs, &objp->no_trunc)) + return FALSE; + if (!xdr_bool(xdrs, &objp->chown_restricted)) + return FALSE; + if (!xdr_bool(xdrs, &objp->case_insensitive)) + return FALSE; + if (!xdr_bool(xdrs, &objp->case_preserving)) + return FALSE; + } else { + IXDR_PUT_U_LONG(buf, objp->linkmax); + IXDR_PUT_U_LONG(buf, objp->name_max); + IXDR_PUT_BOOL(buf, objp->no_trunc); + IXDR_PUT_BOOL(buf, objp->chown_restricted); + IXDR_PUT_BOOL(buf, objp->case_insensitive); + IXDR_PUT_BOOL(buf, objp->case_preserving); + } + return TRUE; + } else if (xdrs->x_op == XDR_DECODE) { + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (!xdr_u_int(xdrs, &objp->linkmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->name_max)) + return FALSE; + if (!xdr_bool(xdrs, &objp->no_trunc)) + return FALSE; + if (!xdr_bool(xdrs, &objp->chown_restricted)) + return FALSE; + if (!xdr_bool(xdrs, &objp->case_insensitive)) + return FALSE; + if (!xdr_bool(xdrs, &objp->case_preserving)) + return FALSE; + } else { + objp->linkmax = IXDR_GET_U_LONG(buf); + objp->name_max = IXDR_GET_U_LONG(buf); + objp->no_trunc = IXDR_GET_BOOL(buf); + objp->chown_restricted = IXDR_GET_BOOL(buf); + objp->case_insensitive = IXDR_GET_BOOL(buf); + objp->case_preserving = IXDR_GET_BOOL(buf); + } + return TRUE; + } + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->linkmax)) + return FALSE; + if (!xdr_u_int(xdrs, &objp->name_max)) + return FALSE; + if (!xdr_bool(xdrs, &objp->no_trunc)) + return FALSE; + if (!xdr_bool(xdrs, &objp->chown_restricted)) + return FALSE; + if (!xdr_bool(xdrs, &objp->case_insensitive)) + return FALSE; + if (!xdr_bool(xdrs, &objp->case_preserving)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_PATHCONF3resfail(XDR *xdrs, am_PATHCONF3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_PATHCONF3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_PATHCONF3res(XDR *xdrs, am_PATHCONF3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_PATHCONF3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_PATHCONF3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_PATHCONF3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_nfspath3(XDR *xdrs, am_nfspath3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_nfspath3:"); + + if (!xdr_string(xdrs, objp, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_symlinkdata3(XDR *xdrs, am_symlinkdata3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_symlinkdata3:"); + + if (!xdr_am_sattr3(xdrs, &objp->symlink_attributes)) + return FALSE; + if (!xdr_am_nfspath3(xdrs, &objp->symlink_data)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_SYMLINK3args(XDR *xdrs, am_SYMLINK3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SYMLINK3args:"); + + if (!xdr_am_diropargs3(xdrs, &objp->where)) + return FALSE; + if (!xdr_am_symlinkdata3(xdrs, &objp->symlink)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_SYMLINK3resok(XDR *xdrs, am_SYMLINK3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SYMLINK3resok:"); + + if (!xdr_am_post_op_fh3(xdrs, &objp->obj)) + return FALSE; + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_SYMLINK3resfail(XDR *xdrs, am_SYMLINK3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SYMLINK3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_SYMLINK3res(XDR *xdrs, am_SYMLINK3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SYMLINK3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_SYMLINK3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_SYMLINK3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_READLINK3args(XDR *xdrs, am_READLINK3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READLINK3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->symlink)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READLINK3resok(XDR *xdrs, am_READLINK3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READLINK3resok:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->symlink_attributes)) + return FALSE; + if (!xdr_am_nfspath3(xdrs, &objp->data)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READLINK3resfail(XDR *xdrs, am_READLINK3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READLINK3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->symlink_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READLINK3res(XDR *xdrs, am_READLINK3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READLINK3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_READLINK3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_READLINK3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_devicedata3(XDR *xdrs, am_devicedata3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_devicedata3:"); + + if (!xdr_am_sattr3(xdrs, &objp->dev_attributes)) + return FALSE; + if (!xdr_am_specdata3(xdrs, &objp->spec)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_mknoddata3(XDR *xdrs, am_mknoddata3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_mknoddata3:"); + + if (!xdr_am_ftype3(xdrs, &objp->type)) + return FALSE; + switch (objp->type) { + case AM_NF3CHR: + if (!xdr_am_devicedata3(xdrs, &objp->am_mknoddata3_u.chr_device)) + return FALSE; + break; + case AM_NF3BLK: + if (!xdr_am_devicedata3(xdrs, &objp->am_mknoddata3_u.blk_device)) + return FALSE; + break; + case AM_NF3SOCK: + if (!xdr_am_sattr3(xdrs, &objp->am_mknoddata3_u.sock_attributes)) + return FALSE; + break; + case AM_NF3FIFO: + if (!xdr_am_sattr3(xdrs, &objp->am_mknoddata3_u.pipe_attributes)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_am_MKNOD3args(XDR *xdrs, am_MKNOD3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_MKNOD3args:"); + + if (!xdr_am_diropargs3(xdrs, &objp->where)) + return FALSE; + if (!xdr_am_mknoddata3(xdrs, &objp->what)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_MKNOD3resok(XDR *xdrs, am_MKNOD3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_MKNOD3resok:"); + + if (!xdr_am_post_op_fh3(xdrs, &objp->obj)) + return FALSE; + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_MKNOD3resfail(XDR *xdrs, am_MKNOD3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_MKNOD3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_MKNOD3res(XDR *xdrs, am_MKNOD3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, ":"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_MKNOD3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_MKNOD3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_MKDIR3args(XDR *xdrs, am_MKDIR3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, ":"); + + if (!xdr_am_diropargs3(xdrs, &objp->where)) + return FALSE; + if (!xdr_am_sattr3(xdrs, &objp->attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_MKDIR3resok(XDR *xdrs, am_MKDIR3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_MKDIR3resok:"); + + if (!xdr_am_post_op_fh3(xdrs, &objp->obj)) + return FALSE; + if (!xdr_am_post_op_attr(xdrs, &objp->obj_attributes)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_MKDIR3resfail(XDR *xdrs, am_MKDIR3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_MKDIR3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_MKDIR3res(XDR *xdrs, am_MKDIR3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_MKDIR3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_MKDIR3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_MKDIR3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_RMDIR3args(XDR *xdrs, am_RMDIR3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RMDIR3args:"); + + if (!xdr_am_diropargs3(xdrs, &objp->object)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_RMDIR3resok(XDR *xdrs, am_RMDIR3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RMDIR3resok:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_RMDIR3resfail(XDR *xdrs, am_RMDIR3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RMDIR3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->dir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_RMDIR3res(XDR *xdrs, am_RMDIR3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RMDIR3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_RMDIR3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_RMDIR3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_RENAME3args(XDR *xdrs, am_RENAME3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RENAME3args:"); + + if (!xdr_am_diropargs3(xdrs, &objp->from)) + return FALSE; + if (!xdr_am_diropargs3(xdrs, &objp->to)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_RENAME3resok(XDR *xdrs, am_RENAME3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RENAME3resok:"); + + if (!xdr_am_wcc_data(xdrs, &objp->fromdir_wcc)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->todir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_RENAME3resfail(XDR *xdrs, am_RENAME3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RENAME3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->fromdir_wcc)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->todir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_RENAME3res(XDR *xdrs, am_RENAME3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_RENAME3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_RENAME3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_RENAME3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_READDIRPLUS3args(XDR *xdrs, am_READDIRPLUS3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->dir)) + return FALSE; + if (!xdr_am_cookie3(xdrs, &objp->cookie)) + return FALSE; + if (!xdr_am_cookieverf3(xdrs, objp->cookieverf)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->dircount)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->maxcount)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_entryplus3(XDR *xdrs, am_entryplus3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_entryplus3:"); + + if (!xdr_am_fileid3(xdrs, &objp->fileid)) + return FALSE; + if (!xdr_am_filename3(xdrs, &objp->name)) + return FALSE; + if (!xdr_am_cookie3(xdrs, &objp->cookie)) + return FALSE; + if (!xdr_am_post_op_attr(xdrs, &objp->name_attributes)) + return FALSE; + if (!xdr_am_post_op_fh3(xdrs, &objp->name_handle)) + return FALSE; + if (!xdr_pointer(xdrs, (char **)&objp->nextentry, + sizeof(am_entryplus3), (xdrproc_t) xdr_am_entryplus3)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_dirlistplus3(XDR *xdrs, am_dirlistplus3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_dirlistplus3:"); + + if (!xdr_pointer(xdrs, (char **)&objp->entries, + sizeof(am_entryplus3), (xdrproc_t) xdr_am_entryplus3)) + return FALSE; + if (!xdr_bool(xdrs, &objp->eof)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READDIRPLUS3resok(XDR *xdrs, am_READDIRPLUS3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3resok:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes)) + return FALSE; + if (!xdr_am_cookieverf3(xdrs, objp->cookieverf)) + return FALSE; + if (!xdr_am_dirlistplus3(xdrs, &objp->reply)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READDIRPLUS3resfail(XDR *xdrs, am_READDIRPLUS3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READDIRPLUS3res(XDR *xdrs, am_READDIRPLUS3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIRPLUS3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_READDIRPLUS3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_READDIRPLUS3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_READDIR3args(XDR *xdrs, am_READDIR3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIR3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->dir)) + return FALSE; + if (!xdr_am_cookie3(xdrs, &objp->cookie)) + return FALSE; + if (!xdr_am_cookieverf3(xdrs, objp->cookieverf)) + return FALSE; + if (!xdr_am_count3(xdrs, &objp->count)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_entry3(XDR *xdrs, am_entry3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_entry3:"); + + if (!xdr_am_fileid3(xdrs, &objp->fileid)) + return FALSE; + if (!xdr_am_filename3(xdrs, &objp->name)) + return FALSE; + if (!xdr_am_cookie3(xdrs, &objp->cookie)) + return FALSE; + if (!xdr_pointer(xdrs, (char **)&objp->nextentry, + sizeof(am_entry3), (xdrproc_t) xdr_am_entry3)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_dirlist3(XDR *xdrs, am_dirlist3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_dirlist3:"); + + if (!xdr_pointer(xdrs, (char **)&objp->entries, + sizeof(am_entry3), (xdrproc_t) xdr_am_entry3)) + return FALSE; + if (!xdr_bool (xdrs, &objp->eof)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READDIR3resok(XDR *xdrs, am_READDIR3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIR3resok:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes)) + return FALSE; + if (!xdr_am_cookieverf3(xdrs, objp->cookieverf)) + return FALSE; + if (!xdr_am_dirlist3(xdrs, &objp->reply)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READDIR3resfail(XDR *xdrs, am_READDIR3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIR3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->dir_attributes)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_READDIR3res(XDR *xdrs, am_READDIR3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_READDIR3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_READDIR3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_READDIR3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_LINK3args(XDR *xdrs, am_LINK3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_LINK3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->file)) + return FALSE; + if (!xdr_am_diropargs3(xdrs, &objp->link)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_LINK3resok(XDR *xdrs, am_LINK3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_LINK3resok:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->linkdir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_LINK3resfail(XDR *xdrs, am_LINK3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_LINK3resfail:"); + + if (!xdr_am_post_op_attr(xdrs, &objp->file_attributes)) + return FALSE; + if (!xdr_am_wcc_data(xdrs, &objp->linkdir_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_LINK3res(XDR *xdrs, am_LINK3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_LINK3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_LINK3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_LINK3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_am_sattrguard3(XDR *xdrs, am_sattrguard3 *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_sattrguard3:"); + + if (!xdr_bool(xdrs, &objp->check)) + return FALSE; + switch (objp->check) { + case TRUE: + if (!xdr_am_nfstime3(xdrs, &objp->am_sattrguard3_u.obj_ctime)) + return FALSE; + break; + case FALSE: + break; + default: + return FALSE; + } + return TRUE; +} + +bool_t +xdr_am_SETATTR3args(XDR *xdrs, am_SETATTR3args *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SETATTR3args:"); + + if (!xdr_am_nfs_fh3(xdrs, &objp->object)) + return FALSE; + if (!xdr_am_sattr3(xdrs, &objp->new_attributes)) + return FALSE; + if (!xdr_am_sattrguard3(xdrs, &objp->guard)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_SETATTR3resok(XDR *xdrs, am_SETATTR3resok *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SETATTR3resok:"); + + if (!xdr_am_wcc_data(xdrs, &objp->obj_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_SETATTR3resfail(XDR *xdrs, am_SETATTR3resfail *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SETATTR3resfail:"); + + if (!xdr_am_wcc_data(xdrs, &objp->obj_wcc)) + return FALSE; + return TRUE; +} + +bool_t +xdr_am_SETATTR3res(XDR *xdrs, am_SETATTR3res *objp) +{ + if (amuDebug(D_XDRTRACE)) + plog(XLOG_DEBUG, "xdr_am_SETATTR3res:"); + + if (!xdr_am_nfsstat3(xdrs, &objp->status)) + return FALSE; + switch (objp->status) { + case AM_NFS3_OK: + if (!xdr_am_SETATTR3resok(xdrs, &objp->res_u.ok)) + return FALSE; + break; + default: + if (!xdr_am_SETATTR3resfail(xdrs, &objp->res_u.fail)) + return FALSE; + break; + } + return TRUE; +} +#endif /* HAVE_FS_NFS3 */ diff --git a/contrib/amd/libamu/xutil.c b/contrib/amd/libamu/xutil.c index 3a33b9c0b14..1159fe5ec83 100644 --- a/contrib/amd/libamu/xutil.c +++ b/contrib/amd/libamu/xutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -63,14 +59,13 @@ static char am_hostname[MAXHOSTNAMELEN] = "unknown"; /* Hostname */ pid_t am_mypid = -1; /* process ID */ serv_state amd_state; /* amd's state */ int foreground = 1; /* 1 == this is the top-level server */ -int debug_flags = 0; +u_int debug_flags = D_CONTROL; /* set regardless if compiled with debugging */ #ifdef HAVE_SYSLOG int syslogging; #endif /* HAVE_SYSLOG */ -int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS; -int xlog_level_init = ~0; -static int amd_program_number = AMQ_PROGRAM; +static u_int xlog_level = XLOG_DEFAULT; +static u_long amd_program_number = AMQ_PROGRAM; #ifdef DEBUG_MEM # if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) @@ -92,23 +87,23 @@ static void real_plog(int lvl, const char *fmt, va_list vargs) struct opt_tab dbg_opt[] = { {"all", D_ALL}, /* All non-disruptive options */ - {"amq", D_AMQ}, /* Don't register for AMQ program */ - {"daemon", D_DAEMON}, /* Don't enter daemon mode */ - {"fork", D_FORK}, /* Don't fork server */ + {"defaults", D_DEFAULT}, /* Default options */ + {"test", D_TEST}, /* Full debug - no daemon, no fork, no amq, local mtab */ + {"amq", D_AMQ}, /* Register for AMQ program */ + {"daemon", D_DAEMON}, /* Enter daemon mode */ + {"fork", D_FORK}, /* Fork server (hlfsd only) */ {"full", D_FULL}, /* Program trace */ #ifdef HAVE_CLOCK_GETTIME {"hrtime", D_HRTIME}, /* Print high resolution time stamps */ #endif /* HAVE_CLOCK_GETTIME */ - /* info service specific debugging (hesiod, nis, etc) */ - {"info", D_INFO}, + {"info", D_INFO}, /* info service specific debugging (hesiod, nis, etc) */ {"mem", D_MEM}, /* Trace memory allocations */ {"mtab", D_MTAB}, /* Use local mtab file */ {"readdir", D_READDIR}, /* Check on browsable_dirs progress */ {"str", D_STR}, /* Debug string munging */ - {"test", D_TEST}, /* Full debug - no daemon, no amq, local mtab */ {"trace", D_TRACE}, /* Protocol trace */ {"xdrtrace", D_XDRTRACE}, /* Trace xdr routines */ - {0, 0} + {NULL, 0} }; #endif /* DEBUG */ @@ -118,6 +113,7 @@ struct opt_tab dbg_opt[] = struct opt_tab xlog_opt[] = { {"all", XLOG_ALL}, /* All messages */ + {"defaults", XLOG_DEFAULT}, /* Default messages */ #ifdef DEBUG {"debug", XLOG_DEBUG}, /* Debug messages */ #endif /* DEBUG */ /* DEBUG */ @@ -129,7 +125,7 @@ struct opt_tab xlog_opt[] = {"user", XLOG_USER}, /* Non-fatal user errors */ {"warn", XLOG_WARNING}, /* Warnings */ {"warning", XLOG_WARNING}, /* Warnings */ - {0, 0} + {NULL, 0} }; @@ -150,7 +146,7 @@ am_get_progname(void) void am_set_hostname(char *hn) { - xstrlcpy(am_hostname, hn, MAXHOSTNAMELEN); + xstrlcpy(am_hostname, hn, sizeof(am_hostname)); } @@ -295,17 +291,23 @@ expand_error(const char *f, char *e, size_t maxlen) const char *p; char *q; int error = errno; - int len = 0; + size_t len = 0, l; - for (p = f, q = e; (*q = *p) && (size_t) len < maxlen; len++, q++, p++) { + *e = '\0'; + for (p = f, q = e; len < maxlen && (*q = *p); len++, q++, p++) { if (p[0] == '%' && p[1] == 'm') { - xstrlcpy(q, strerror(error), maxlen); - len += strlen(q) - 1; - q += strlen(q) - 1; + if (len >= maxlen) + break; + xstrlcpy(q, strerror(error), maxlen - len); + l = strlen(q); + if (l != 0) + l--; + len += l; + q += l; p++; } } - e[maxlen-1] = '\0'; /* null terminate, to be sure */ + e[maxlen - 1] = '\0'; /* null terminate, to be sure */ return e; } @@ -317,7 +319,7 @@ static void show_time_host_and_name(int lvl) { static time_t last_t = 0; - static char *last_ctime = 0; + static char *last_ctime = NULL; time_t t; #if defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) struct timespec ts; @@ -390,21 +392,63 @@ show_time_host_and_name(int lvl) int debug_option(char *opt) { - return cmdoption(opt, dbg_opt, &debug_flags); + u_int dl = debug_flags; + static int initialized_debug_flags = 0; + int rc = cmdoption(opt, dbg_opt, &dl); + + if (rc) /* if got any error, don't update debug flags */ + return EINVAL; + + /* + * If we already initialized the debugging flags once (via amd.conf), then + * don't allow "immutable" flags to be changed again (via amq -D), because + * they could mess Amd's state and only make sense to be set once when Amd + * starts. + */ + if (initialized_debug_flags && + debug_flags != 0 && + (dl & D_IMMUTABLE) != (debug_flags & D_IMMUTABLE)) { + plog(XLOG_ERROR, "cannot change immutable debug flags"); + /* undo any attempted change to an immutable flag */ + dl = (dl & ~D_IMMUTABLE) | (debug_flags & D_IMMUTABLE); + } + initialized_debug_flags = 1; + debug_flags = dl; + + return rc; } void dplog(const char *fmt, ...) { +#ifdef HAVE_SIGACTION + sigset_t old, chld; +#else /* not HAVE_SIGACTION */ + int mask; +#endif /* not HAVE_SIGACTION */ va_list ap; +#ifdef HAVE_SIGACTION + sigemptyset(&chld); + sigaddset(&chld, SIGCHLD); +#else /* not HAVE_SIGACTION */ + mask = sigblock(sigmask(SIGCHLD)); +#endif /* not HAVE_SIGACTION */ + + sigprocmask(SIG_BLOCK, &chld, &old); if (!logfp) logfp = stderr; /* initialize before possible first use */ va_start(ap, fmt); real_plog(XLOG_DEBUG, fmt, ap); va_end(ap); + +#ifdef HAVE_SIGACTION + sigprocmask(SIG_SETMASK, &old, NULL); +#else /* not HAVE_SIGACTION */ + mask = sigblock(sigmask(SIGCHLD)); +#endif /* not HAVE_SIGACTION */ } #endif /* DEBUG */ @@ -412,14 +456,33 @@ dplog(const char *fmt, ...) void plog(int lvl, const char *fmt, ...) { +#ifdef HAVE_SIGACTION + sigset_t old, chld; +#else /* not HAVE_SIGACTION */ + int mask; +#endif /* not HAVE_SIGACTION */ va_list ap; +#ifdef HAVE_SIGACTION + sigemptyset(&chld); + sigaddset(&chld, SIGCHLD); + sigprocmask(SIG_BLOCK, &chld, &old); +#else /* not HAVE_SIGACTION */ + mask = sigblock(sigmask(SIGCHLD)); +#endif /* not HAVE_SIGACTION */ + if (!logfp) logfp = stderr; /* initialize before possible first use */ va_start(ap, fmt); real_plog(lvl, fmt, ap); va_end(ap); + +#ifdef HAVE_SIGACTION + sigprocmask(SIG_SETMASK, &old, NULL); +#else /* not HAVE_SIGACTION */ + sigsetmask(mask); +#endif /* not HAVE_SIGACTION */ } @@ -497,11 +560,11 @@ real_plog(int lvl, const char *fmt, va_list vargs) switch (last_count) { case 0: /* never printed at all */ last_count = 1; - if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */ + if (strlcpy(last_msg, msg, sizeof(last_msg)) >= sizeof(last_msg)) /* don't use xstrlcpy here (recursive!) */ fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg); last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ - fwrite(msg, ptr - msg, 1, logfp); + __IGNORE(fwrite(msg, ptr - msg, 1, logfp)); fflush(logfp); break; @@ -510,11 +573,11 @@ real_plog(int lvl, const char *fmt, va_list vargs) last_count++; } else { /* last msg printed once, new one differs */ /* last_count remains at 1 */ - if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */ + if (strlcpy(last_msg, msg, sizeof(last_msg)) >= sizeof(last_msg)) /* don't use xstrlcpy here (recursive!) */ fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg); last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ - fwrite(msg, ptr - msg, 1, logfp); + __IGNORE(fwrite(msg, ptr - msg, 1, logfp)); fflush(logfp); } break; @@ -527,7 +590,7 @@ real_plog(int lvl, const char *fmt, va_list vargs) show_time_host_and_name(last_lvl); xsnprintf(last_msg, sizeof(last_msg), "last message repeated %d times\n", last_count); - fwrite(last_msg, strlen(last_msg), 1, logfp); + __IGNORE(fwrite(last_msg, strlen(last_msg), 1, logfp)); fflush(logfp); last_count = 0; /* start from scratch */ break; @@ -539,13 +602,13 @@ real_plog(int lvl, const char *fmt, va_list vargs) show_time_host_and_name(last_lvl); xsnprintf(last_msg, sizeof(last_msg), "last message repeated %d times\n", last_count); - fwrite(last_msg, strlen(last_msg), 1, logfp); + __IGNORE(fwrite(last_msg, strlen(last_msg), 1, logfp)); if (strlcpy(last_msg, msg, 1024) >= 1024) /* don't use xstrlcpy here (recursive!) */ fprintf(stderr, "real_plog: string \"%s\" truncated to \"%s\"\n", last_msg, msg); last_count = 1; last_lvl = lvl; show_time_host_and_name(lvl); /* mimic syslog header */ - fwrite(msg, ptr - msg, 1, logfp); + __IGNORE(fwrite(msg, ptr - msg, 1, logfp)); fflush(logfp); } break; @@ -573,7 +636,7 @@ show_opts(int ch, struct opt_tab *opts) int -cmdoption(char *s, struct opt_tab *optb, int *flags) +cmdoption(char *s, struct opt_tab *optb, u_int *flags) { char *p = s; int errs = 0; @@ -581,7 +644,7 @@ cmdoption(char *s, struct opt_tab *optb, int *flags) while (p && *p) { int neg; char *opt; - struct opt_tab *dp, *dpn = 0; + struct opt_tab *dp, *dpn = NULL; s = p; p = strchr(p, ','); @@ -624,7 +687,7 @@ cmdoption(char *s, struct opt_tab *optb, int *flags) * This will log to stderr when parsing the command line * since any -l option will not yet have taken effect. */ - plog(XLOG_USER, "option \"%s\" not recognized", s); + plog(XLOG_ERROR, "option \"%s\" not recognized", s); errs++; } @@ -645,22 +708,22 @@ cmdoption(char *s, struct opt_tab *optb, int *flags) int switch_option(char *opt) { - int xl = xlog_level; + u_int xl = xlog_level; int rc = cmdoption(opt, xlog_opt, &xl); - if (rc) { - rc = EINVAL; - } else { - /* - * Keep track of initial log level, and - * don't allow options to be turned off. - */ - if (xlog_level_init == ~0) - xlog_level_init = xl; - else - xl |= xlog_level_init; - xlog_level = xl; + if (rc) /* if got any error, don't update flags */ + return EINVAL; + + /* + * Don't allow "mandatory" flags to be turned off, because + * we must always be able to report on flag re/setting errors. + */ + if ((xl & XLOG_MANDATORY) != XLOG_MANDATORY) { + plog(XLOG_ERROR, "cannot turn off mandatory logging options"); + xl |= XLOG_MANDATORY; } + if (xlog_level != xl) + xlog_level = xl; /* set new flags */ return rc; } @@ -801,7 +864,7 @@ switch_to_logfile(char *logfile, int old_umask, int truncate_log) } else { /* regular log file */ (void) umask(old_umask); if (truncate_log) - truncate(logfile, 0); + __IGNORE(truncate(logfile, 0)); new_logfp = fopen(logfile, "a"); umask(0); } @@ -834,7 +897,8 @@ switch_to_logfile(char *logfile, int old_umask, int truncate_log) void unregister_amq(void) { - if (!amuDebug(D_AMQ)) { + + if (amuDebug(D_AMQ)) { /* find which instance of amd to unregister */ u_long amd_prognum = get_amd_program_number(); @@ -875,7 +939,7 @@ going_down(int rc) /* return the rpc program number under which amd was used */ -int +u_long get_amd_program_number(void) { return amd_program_number; @@ -884,7 +948,7 @@ get_amd_program_number(void) /* set the rpc program number used for amd */ void -set_amd_program_number(int program) +set_amd_program_number(u_long program) { amd_program_number = program; } @@ -955,9 +1019,9 @@ amu_release_controlling_tty(void) close(fd); } return; -#endif /* not TIOCNOTTY */ - +#else plog(XLOG_ERROR, "unable to release controlling tty"); +#endif /* not TIOCNOTTY */ } @@ -1012,7 +1076,7 @@ mkdirs(char *path, int mode) /* * take a copy in case path is in readonly store */ - char *p2 = strdup(path); + char *p2 = xstrdup(path); char *sp = p2; struct stat stb; int error_so_far = 0; @@ -1056,7 +1120,7 @@ mkdirs(char *path, int mode) void rmdirs(char *dir) { - char *xdp = strdup(dir); + char *xdp = xstrdup(dir); char *dp; do { @@ -1089,3 +1153,15 @@ rmdirs(char *dir) XFREE(xdp); } + +/* + * Dup a string + */ +char * +xstrdup(const char *s) +{ + size_t len = strlen(s); + char *sp = xmalloc(len + 1); + memcpy(sp, s, len + 1); + return sp; +} diff --git a/contrib/amd/mk-amd-map/mk-amd-map.8 b/contrib/amd/mk-amd-map/mk-amd-map.8 index 28bbb9b84fe..677f41a268f 100644 --- a/contrib/amd/mk-amd-map/mk-amd-map.8 +++ b/contrib/amd/mk-amd-map/mk-amd-map.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1993 Jan-Simon Pendry .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. @@ -12,11 +12,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -32,10 +28,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" from: @(#)mk-amd-map.8 8.1 (Berkeley) 6/28/93 -.\" $Id: mk-amd-map.8,v 1.9.2.1 2006/01/02 18:48:26 ezk Exp $ .\" $FreeBSD$ .\" +.\" File: am-utils/mk-amd-map/mk-amd-map.8 +.\" .Dd January 2, 2006 .Dt MK-AMD-MAP 8 .Os diff --git a/contrib/amd/mk-amd-map/mk-amd-map.c b/contrib/amd/mk-amd-map/mk-amd-map.c index 48d82b0bd0d..e6ca9d93983 100644 --- a/contrib/amd/mk-amd-map/mk-amd-map.c +++ b/contrib/amd/mk-amd-map/mk-amd-map.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -93,7 +89,7 @@ read_line(char *buf, int size, FILE *fp) /* * Skip leading white space on next line */ - while ((ch = getc(fp)) != EOF && isascii(ch) && isspace(ch)) ; + while ((ch = getc(fp)) != EOF && isascii((unsigned char)ch) && isspace((unsigned char)ch)) ; (void) ungetc(ch, fp); } else { return done; @@ -144,7 +140,7 @@ read_file(FILE *fp, char *map, voidp db) /* * Find start of key */ - for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ; + for (kp = key_val; *kp && isascii((unsigned char)*kp) && isspace((unsigned char)*kp); kp++) ; /* * Ignore blank lines @@ -155,7 +151,7 @@ read_file(FILE *fp, char *map, voidp db) /* * Find end of key */ - for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ; + for (cp = kp; *cp && (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)); cp++) ; /* * Check whether key matches, or whether @@ -163,7 +159,7 @@ read_file(FILE *fp, char *map, voidp db) */ if (*cp) *cp++ = '\0'; - while (*cp && isascii(*cp) && isspace((int)*cp)) + while (*cp && isascii((unsigned char)*cp) && isspace((unsigned char)*cp)) cp++; if (*kp == '+') { fprintf(stderr, "Can't interpolate %s\n", kp); diff --git a/contrib/amd/scripts/amd.conf-sample b/contrib/amd/scripts/amd.conf-sample index 880a74ba755..4d965787099 100644 --- a/contrib/amd/scripts/amd.conf-sample +++ b/contrib/amd/scripts/amd.conf-sample @@ -64,8 +64,8 @@ nis_domain = nisDom-CS.columbia.edu # (amd -x) log_options = fatal,error,user,warn,info,map,stats,all # (amd -D) -debug_options = all,amq,daemon,fork,full,hrtime,info,mem,mtab,\ - str,readdir,test,trace,xdrtrace +debug_options = all,defaults,test,amq,daemon,fork,\ + full,hrtime,info,mem,mtab,str,readdir,trace,xdrtrace # path for mtab file during mtab debug mode debug_mtab_file = /tmp/mnttab # (amd -S) @@ -108,7 +108,7 @@ exec_map_timeout = 10 normalize_slashes = yes | no ############################################################################## -# these 8 global options can be overridden by each map individually +# these 9 global options can be overridden by each map individually browsable_dirs = no | yes | full map_options = cache:=all map_type = file|hesiod|ndbm|nis|nisplus|passwd|union|ldap @@ -119,6 +119,8 @@ autofs_use_lofs = yes | no search_path = /etc/local:/etc/amdmaps:/misc/yp # selectors are not recognized by default in the /defaults entry selectors_in_defaults = no | yes +# does this map use Sun Automounter map syntax? +sun_map_syntax = no | yes ############################################################################## ############################################################################## diff --git a/contrib/amd/scripts/amd.conf.5 b/contrib/amd/scripts/amd.conf.5 index 5967e8ffd58..1adc2ba8567 100644 --- a/contrib/amd/scripts/amd.conf.5 +++ b/contrib/amd/scripts/amd.conf.5 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1990 Jan-Simon Pendry .\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,9 +32,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" %W% (Berkeley) %G% .\" -.\" $Id: amd.conf.5,v 1.39.2.5 2006/04/21 01:12:04 ezk Exp $ +.\" File: am-utils/scripts/amd.conf.5 .\" $FreeBSD$ .\" .Dd February 26, 2016 @@ -274,8 +269,14 @@ slow slip-based networks as follows: wire!=slip-net;opts:=intr,rsize=8192,wsize=8192 .Ed Deprecated form: selectors_on_default +.TP +.BR sun_map_syntax " (boolean, default=no)" +If "yes," then Amd will parse the map according to the Sun Automount syntax. + +.\" ************************************************************************** .El .Ss "Parameters applicable to the global section only" + .Bl -tag -width 4n .It Va arch Pq string, default to compiled in value Same as the @@ -345,12 +346,13 @@ option to Specify any debugging options for .Xr amd 8 . Works only if +Works only if am-utils was configured for debugging using the .Fl Fl enable-debug option. The .Cm mem -option alone can be turned on via +option, as well as all other options, can be turned on via .Fl Fl enable-debug Ns = Ns Cm mem . Otherwise debugging options are ignored. Options are @@ -364,7 +366,9 @@ Possible values are: .Pp .Bl -tag -width ".Cm xdrtrace" -compact .It Cm all -all options +all options (excludes hrtime and mtab) +.It Cm defaults +"sensible" default options (all--excluding hrtime, mtab, and xdrtrace) .It Cm amq register for .Xr amq 8 @@ -374,6 +378,8 @@ enter daemon mode fork server .It Cm full program trace +.It Cm hrtime +print high resolution time stamps (only if syslog(3) is not used) .It Cm info info service specific debugging (hesiod, nis, etc.) @@ -383,14 +389,16 @@ trace memory allocations use local .Pa ./mtab file +\fBreaddir\fR show browsable_dirs progress .It Cm str debug string munging .It Cm test -full debug but no daemon +full debug options plus mtab,nodaemon,nofork,noamq .It Cm trace trace protocol and NFS mount arguments .It Cm xdrtrace trace XDR routines +.BR dismount_interval " (numeric, default=120)" .El .It Va dismount_interval Pq numeric, default=120 Same as the @@ -580,12 +588,14 @@ Possible values are: .Bl -tag -width ".Cm warning" -compact .It Cm all all messages +.It Cm defaults +default messages (fatal,error,user,warning,info) .It Cm debug debug messages .It Cm error -non-fatal system errors +non-fatal system errors (cannot be turned off) .It Cm fatal -fatal errors +fatal errors (cannot be turned off) .It Cm info information .It Cm map @@ -596,6 +606,7 @@ additional statistical information non-fatal user errors .It Cm warn warnings +\fBwarning\fR warnings .It Cm warning warnings .El @@ -1074,7 +1085,9 @@ map_name = amd.tftpboot .Sh SEE ALSO .Xr hosts_access 5 , .Xr amd 8 , -.Xr amq 8 +.Xr amq 8 , +.xr automount 8 , +.Xr ctl-amd 8 . .Pp .Dq am-utils .Xr info 1 diff --git a/contrib/amd/scripts/automount2amd.8 b/contrib/amd/scripts/automount2amd.8 index bd3b61230ab..f9a04d928cd 100644 --- a/contrib/amd/scripts/automount2amd.8 +++ b/contrib/amd/scripts/automount2amd.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1990 Jan-Simon Pendry .\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,9 +32,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" %W% (Berkeley) %G% .\" -.\" $Id: automount2amd.8,v 1.8.2.1 2006/01/02 18:48:26 ezk Exp $ +.\" File: am-utils/scripts/automount2amd.8 .\" .TH AUTOMOUNT2AMD 8L "24 May 1993" .SH NAME diff --git a/contrib/amd/scripts/fixrmtab.in b/contrib/amd/scripts/fixrmtab.in index 23003806e4c..a1fbebf6150 100755 --- a/contrib/amd/scripts/fixrmtab.in +++ b/contrib/amd/scripts/fixrmtab.in @@ -10,15 +10,23 @@ #set -x -RMTAB=/etc/rmtab -TMP=/tmp/rmtab.$$ +# allow user to pass RMTAB file name from environment +if test -z "${RMTAB}" ; then + RMTAB=/etc/rmtab +fi -if [ ! -f /etc/rmtab ]; then +if [ ! -f "$RMTAB" ]; then exit 0 fi -for host in $* +TMP="$(mktemp ${RMTAB}.XXXXXX)" +if [ -z "$TMP" ]; then + exit 1 +fi + +trap "rm -f $TMP" 0 1 2 3 15 + +for host do - sed -e '/^'$host':/s/^./#/' $RMTAB > $TMP && cp $TMP $RMTAB + sed -e "/^$host:/s/^./#/" "$RMTAB" > "$TMP" && cp "$TMP" "$RMTAB" done -rm -f $TMP diff --git a/contrib/amd/vers.m4 b/contrib/amd/vers.m4 index 7343910d5f2..99d4f06750c 100644 --- a/contrib/amd/vers.m4 +++ b/contrib/amd/vers.m4 @@ -1 +1 @@ -[6.1.5]dnl +[6.2]dnl diff --git a/contrib/amd/wire-test/wire-test.8 b/contrib/amd/wire-test/wire-test.8 index 65c15c5d4e6..b8d60d89d10 100644 --- a/contrib/amd/wire-test/wire-test.8 +++ b/contrib/amd/wire-test/wire-test.8 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1997-2006 Erez Zadok +.\" Copyright (c) 1997-2014 Erez Zadok .\" Copyright (c) 1990 Jan-Simon Pendry .\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine .\" Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ .\" 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 acknowledgment: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors +.\" 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. .\" @@ -36,9 +32,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" %W% (Berkeley) %G% .\" -.\" $Id: wire-test.8,v 1.10.2.1 2006/01/02 18:48:26 ezk Exp $ +.\" File: am-utils/wire-test/wire-test.8 .\" $FreeBSD$ .\" .Dd February 26, 2016 diff --git a/contrib/amd/wire-test/wire-test.c b/contrib/amd/wire-test/wire-test.c index bcaaf5a3151..0adcf5d6666 100644 --- a/contrib/amd/wire-test/wire-test.c +++ b/contrib/amd/wire-test/wire-test.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Erez Zadok + * Copyright (c) 1997-2014 Erez Zadok * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990 The Regents of the University of California. @@ -16,11 +16,7 @@ * 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 acknowledgment: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 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. * @@ -59,7 +55,7 @@ main(int argc, char **argv) char *testhost, *proto, *tmp_buf; int nv, ret; struct sockaddr_in *ip; - struct hostent *hp = 0; + struct hostent *hp = NULL; am_set_progname(argv[0]); @@ -102,12 +98,11 @@ main(int argc, char **argv) memmove((voidp) &ip->sin_addr, (voidp) hp->h_addr, sizeof(ip->sin_addr)); ip->sin_port = htons(NFS_PORT); - xlog_level = 0; /* turn off debugging */ fprintf(stderr, "NFS Version and protocol tests to host \"%s\"...\n", testhost); proto = "udp"; for (nv=2; nv<=3; ++nv) { fprintf(stderr, "\ttesting vers=%d, proto=\"%s\" -> ", nv, proto); - ret = get_nfs_version(testhost, ip, nv, proto); + ret = get_nfs_version(testhost, ip, nv, proto, 0); if (ret == 0) fprintf(stderr, "failed!\n"); else @@ -117,7 +112,7 @@ main(int argc, char **argv) proto = "tcp"; for (nv=2; nv<=3; ++nv) { fprintf(stderr, "\ttesting vers=%d, proto=\"%s\" -> ", nv, proto); - ret = get_nfs_version(testhost, ip, nv, proto); + ret = get_nfs_version(testhost, ip, nv, proto, 0); if (ret == 0) fprintf(stderr, "failed!\n"); else diff --git a/share/man/man4/hv_ata_pci_disengage.4 b/contrib/hyperv/tools/hv_vss_daemon.8 similarity index 57% rename from share/man/man4/hv_ata_pci_disengage.4 rename to contrib/hyperv/tools/hv_vss_daemon.8 index e7a33523333..090690c368b 100644 --- a/share/man/man4/hv_ata_pci_disengage.4 +++ b/contrib/hyperv/tools/hv_vss_daemon.8 @@ -1,6 +1,4 @@ -.\" $FreeBSD$ -.\" -.\" Copyright (c) 2012 Microsoft Corp. +.\" Copyright (c) 2016 Microsoft Corp. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,63 +22,63 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 10, 2013 -.Dt HYPER-V 4 +.\" $FreeBSD$ +.Dd October 12, 2016 +.Dt HV_VSS_DAEMON 8 .Os .Sh NAME -.Nm hv_ata_pci_disengage -.Nd Hyper-V ATA PCI Disengage driver +.Nm hv_vss_daemon +.Nd Hyper-V Volume Shadow Copy Service Daemon .Sh SYNOPSIS -To compile this driver into the kernel, place the following lines in -the system kernel configuration file: -.Bd -ragged -offset indent -.Cd "device hyperv" -.Ed +.Nm +.Op Fl dn .Sh DESCRIPTION The .Nm -driver prevents the native +daemon provides the ability to freeze and thaw the file system for .Fx -ATA driver from -loading in the presence of Hyper-V. +guest partitions running on Hyper-V. +.Pp +Hyper-V allows administrators to backup or restore the .Fx -guests running on Hyper-V can take advantage of the Hyper-V Storage -Virtual Consumer -.Pq Xr hv_storvsc 4 -for using their IDE devices. -Since the ATA -driver serves IDE devices as well, there is a chance that the ATA driver may -interfere with the operations of -.Xr hv_storvsc 4 . +guest partition. +Administrators can +use Windows Powershell scripts to backup or restore the +.Fx +VM. +.Pp The .Nm -driver avoids -conflicts between the ATA driver and -.Xr hv_storvsc 4 -by disabling the ATA driver -when the -.Fx -guest is booting. +accepts file system freeze and thaw requests from the +.Xr hv_utils 4 +driver and performs the actual file-system operation. .Pp -A side effect of disabling the ATA driver is that CDROM may become -inoperational on +The file system freeze and thaw functionality is +useful when the Hyper-V host wants to do live backup of .Fx -guest partitions. -If CDROM access is a must then users may use -"set hw.ata.disk_enable=1" at boot time to prevent the ATA driver from being -disabled. +guest. Hyper-V host sends file system freezing request to +.Nm +which conducts the real operation. After successfully freezing file +system, Hyper-V host takes a snapshot of the VM. In the future, +Hyper-V host can restore the +.Fx +VM through that snapshot. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d +Run as regular process instead of a daemon for debugging purpose. +.It Fl n +Generate debugging output. +.El .Sh SEE ALSO +.Xr hv_vmbus 4 , +.Xr hv_utils 4 , .Xr hv_netvsc 4 , .Xr hv_storvsc 4 , -.Xr hv_utils 4 , -.Xr hv_vmbus 4 +.Xr hv_kvp 4 .Sh HISTORY -Support for -.Nm -first appeared in -.Fx 10.0 . -The driver was developed through a joint effort between Citrix Incorporated, -Microsoft Corporation, and Network Appliance Incorporated. +The daemon was introduced in October 2016 and developed by Microsoft Corp. .Sh AUTHORS .An -nosplit .Fx diff --git a/contrib/hyperv/tools/hv_vss_daemon.c b/contrib/hyperv/tools/hv_vss_daemon.c new file mode 100644 index 00000000000..a1ba98d4cb4 --- /dev/null +++ b/contrib/hyperv/tools/hv_vss_daemon.c @@ -0,0 +1,274 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hv_snapshot.h" + +#define UNDEF_FREEZE_THAW (0) +#define FREEZE (1) +#define THAW (2) + +#define VSS_LOG(priority, format, args...) do { \ + if (is_debugging == 1) { \ + if (is_daemon == 1) \ + syslog(priority, format, ## args); \ + else \ + printf(format, ## args); \ + } else { \ + if (priority < LOG_DEBUG) { \ + if (is_daemon == 1) \ + syslog(priority, format, ## args); \ + else \ + printf(format, ## args); \ + } \ + } \ + } while(0) + +static int is_daemon = 1; +static int is_debugging = 0; +static int g_ufs_suspend_handle = -1; + +static const char *dev = "/dev"; + +static int +check(void) +{ + struct statfs *mntbuf, *statfsp; + int mntsize; + int i; + + mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); + if (mntsize == 0) { + VSS_LOG(LOG_ERR, "There is no mount information\n"); + return (EINVAL); + } + for (i = mntsize - 1; i >= 0; --i) + { + statfsp = &mntbuf[i]; + + if (strncmp(statfsp->f_mntonname, dev, strlen(dev)) == 0) { + continue; /* skip to freeze '/dev' */ + } else if (statfsp->f_flags & MNT_RDONLY) { + continue; /* skip to freeze RDONLY partition */ + } else if (strncmp(statfsp->f_fstypename, "ufs", 3) != 0) { + return (EPERM); /* only UFS can be freezed */ + } + } + + return (0); +} + +static int +freeze(void) +{ + struct statfs *mntbuf, *statfsp; + int mntsize; + int error = 0; + int i; + + g_ufs_suspend_handle = open(_PATH_UFSSUSPEND, O_RDWR); + if (g_ufs_suspend_handle == -1) { + VSS_LOG(LOG_ERR, "unable to open %s", _PATH_UFSSUSPEND); + return (errno); + } + + mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); + if (mntsize == 0) { + VSS_LOG(LOG_ERR, "There is no mount information\n"); + return (EINVAL); + } + for (i = mntsize - 1; i >= 0; --i) + { + statfsp = &mntbuf[i]; + + if (strncmp(statfsp->f_mntonname, dev, strlen(dev)) == 0) { + continue; /* skip to freeze '/dev' */ + } else if (statfsp->f_flags & MNT_RDONLY) { + continue; /* skip to freeze RDONLY partition */ + } else if (strncmp(statfsp->f_fstypename, "ufs", 3) != 0) { + continue; /* only UFS can be freezed */ + } + error = ioctl(g_ufs_suspend_handle, UFSSUSPEND, &statfsp->f_fsid); + if (error != 0) { + VSS_LOG(LOG_ERR, "error: %d\n", errno); + error = errno; + } else { + VSS_LOG(LOG_INFO, "Successfully suspend fs: %s\n", + statfsp->f_mntonname); + } + } + + return (error); +} + +/** + * close the opened handle will thaw the FS. + */ +static int +thaw(void) +{ + int error = 0; + if (g_ufs_suspend_handle != -1) { + error = close(g_ufs_suspend_handle); + if (!error) { + g_ufs_suspend_handle = -1; + VSS_LOG(LOG_INFO, "Successfully thaw the fs\n"); + } else { + error = errno; + VSS_LOG(LOG_ERR, "Fail to thaw the fs: " + "%d %s\n", errno, strerror(errno)); + } + } else { + VSS_LOG(LOG_INFO, "The fs has already been thawed\n"); + } + + return (error); +} + +static void +usage(const char* cmd) +{ + fprintf(stderr, "%s: daemon for UFS file system freeze/thaw\n" + " -d : enable debug log printing. Default is disabled.\n" + " -n : run as a regular process instead of a daemon. Default is a daemon.\n" + " -h : print usage.\n", cmd); + exit(1); +} + +int +main(int argc, char* argv[]) +{ + struct hv_vss_opt_msg userdata; + + struct pollfd hv_vss_poll_fd[1]; + uint32_t op; + int ch, r, error; + int hv_vss_dev_fd; + + while ((ch = getopt(argc, argv, "dnh")) != -1) { + switch (ch) { + case 'n': + /* Run as regular process for debugging purpose. */ + is_daemon = 0; + break; + case 'd': + /* Generate debugging output */ + is_debugging = 1; + break; + case 'h': + default: + usage(argv[0]); + break; + } + } + + openlog("HV_VSS", 0, LOG_USER); + + /* Become daemon first. */ + if (is_daemon == 1) + daemon(1, 0); + else + VSS_LOG(LOG_DEBUG, "Run as regular process.\n"); + + VSS_LOG(LOG_INFO, "HV_VSS starting; pid is: %d\n", getpid()); + + memset(&userdata, 0, sizeof(struct hv_vss_opt_msg)); + /* register the daemon */ + hv_vss_dev_fd = open(VSS_DEV(FS_VSS_DEV_NAME), O_RDWR); + + if (hv_vss_dev_fd < 0) { + VSS_LOG(LOG_ERR, "Fail to open %s, error: %d %s\n", + VSS_DEV(FS_VSS_DEV_NAME), errno, strerror(errno)); + exit(EXIT_FAILURE); + } + hv_vss_poll_fd[0].fd = hv_vss_dev_fd; + hv_vss_poll_fd[0].events = POLLIN | POLLRDNORM; + + while (1) { + r = poll(hv_vss_poll_fd, 1, INFTIM); + + VSS_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n", + r, hv_vss_poll_fd[0].revents); + + if (r == 0 || (r < 0 && errno == EAGAIN) || + (r < 0 && errno == EINTR)) { + /* Nothing to read */ + continue; + } + + if (r < 0) { + /* + * For poll return failure other than EAGAIN, + * we want to exit. + */ + VSS_LOG(LOG_ERR, "Poll failed.\n"); + perror("poll"); + exit(EIO); + } + + /* Read from character device */ + error = ioctl(hv_vss_dev_fd, IOCHVVSSREAD, &userdata); + if (error < 0) { + VSS_LOG(LOG_ERR, "Read failed.\n"); + perror("pread"); + exit(EIO); + } + + if (userdata.status != 0) { + VSS_LOG(LOG_ERR, "data read error\n"); + continue; + } + + /* + * We will use the KVP header information to pass back + * the error from this daemon. So, first save the op + * and pool info to local variables. + */ + + op = userdata.opt; + + switch (op) { + case HV_VSS_CHECK: + error = check(); + break; + case HV_VSS_FREEZE: + error = freeze(); + break; + case HV_VSS_THAW: + error = thaw(); + break; + default: + VSS_LOG(LOG_ERR, "Illegal operation: %d\n", op); + error = VSS_FAIL; + } + if (error) + userdata.status = VSS_FAIL; + else + userdata.status = VSS_SUCCESS; + error = ioctl(hv_vss_dev_fd, IOCHVVSSWRITE, &userdata); + if (error != 0) { + VSS_LOG(LOG_ERR, "Fail to write to device\n"); + exit(EXIT_FAILURE); + } else { + VSS_LOG(LOG_INFO, "Send response %d for %s to kernel\n", + userdata.status, op == HV_VSS_FREEZE ? "Freeze" : + (op == HV_VSS_THAW ? "Thaw" : "Check")); + } + } +} diff --git a/etc/devd/hyperv.conf b/etc/devd/hyperv.conf index bed7383d081..0abf284a9ce 100644 --- a/etc/devd/hyperv.conf +++ b/etc/devd/hyperv.conf @@ -17,3 +17,19 @@ notify 10 { match "cdev" "hv_kvp_dev"; action "pkill -x hv_kvp_daemon"; }; + +notify 11 { + match "system" "DEVFS"; + match "subsystem" "CDEV"; + match "type" "CREATE"; + match "cdev" "hv_fsvss_dev"; + action "/usr/sbin/hv_vss_daemon"; +}; + +notify 11 { + match "system" "DEVFS"; + match "subsystem" "CDEV"; + match "type" "DESTROY"; + match "cdev" "hv_fsvss_dev"; + action "pkill -x hv_vss_daemon"; +}; diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 5beaf3d2db6..8a9bbeabdb9 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -118,6 +118,8 @@ .. hwpmc .. + hyperv + .. ic .. iicbus diff --git a/etc/rc.subr b/etc/rc.subr index 0201f0595c6..7eaa13a9401 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -1206,22 +1206,17 @@ $command $rc_flags $command_args" case "$rc_arg" in start) # We cannot use protect(1) inside jails. - jailed="$(sysctl -n security.jail.jailed)" - if [ ${jailed} -eq 1 ]; then - return $_return - fi - if [ -n "$_oomprotect" ]; then - if [ -f "${PROTECT}" ]; then - pid=$(check_process $command) - case $_oomprotect in - [Aa][Ll][Ll]) - ${PROTECT} -i -p ${pid} - ;; - [Yy][Ee][Ss]) - ${PROTECT} -p ${pid} - ;; - esac - fi + if [ -n "$_oomprotect" ] && [ -f "${PROTECT}" ] && + [ "$(sysctl -n security.jail.jailed)" -eq 0 ]; then + pid=$(check_process $command) + case $_oomprotect in + [Aa][Ll][Ll]) + ${PROTECT} -i -p ${pid} + ;; + [Yy][Ee][Ss]) + ${PROTECT} -p ${pid} + ;; + esac fi ;; esac diff --git a/gnu/usr.bin/cc/Makefile.tgt b/gnu/usr.bin/cc/Makefile.tgt index 3acd4d7c929..eb8ee7b4db8 100644 --- a/gnu/usr.bin/cc/Makefile.tgt +++ b/gnu/usr.bin/cc/Makefile.tgt @@ -4,7 +4,7 @@ # MACHINE_CPUARCH, but there's no easy way to export make functions... .if defined(TARGET_ARCH) -TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/} +TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64(sf)?/riscv64/} .else TARGET_CPUARCH=${MACHINE_CPUARCH} .endif diff --git a/include/Makefile b/include/Makefile index f2d76b6af06..302d26957c3 100644 --- a/include/Makefile +++ b/include/Makefile @@ -44,7 +44,7 @@ LDIRS= bsm cam geom net net80211 netgraph netinet netinet6 \ LSUBDIRS= cam/ata cam/nvme cam/scsi \ dev/acpica dev/agp dev/an dev/bktr dev/ciss dev/filemon dev/firewire \ - dev/hwpmc \ + dev/hwpmc dev/hyperv \ dev/ic dev/iicbus dev/io dev/lmc dev/mfi dev/nvme \ dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/smbus \ dev/speaker dev/utopia dev/vkbd dev/wi \ @@ -155,7 +155,7 @@ copies: .PHONY .META done; \ fi .endfor -.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS} +.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS} cd ${.CURDIR}/../sys; \ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \ ${DESTDIR}${INCLUDEDIR}/$i @@ -185,6 +185,9 @@ copies: .PHONY .META ${DESTDIR}${INCLUDEDIR}/dev/evdev; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 uinput.h \ ${DESTDIR}${INCLUDEDIR}/dev/evdev + cd ${.CURDIR}/../sys/dev/hyperv/utilities; \ + ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 hv_snapshot.h \ + ${DESTDIR}${INCLUDEDIR}/dev/hyperv cd ${.CURDIR}/../sys/dev/pci; \ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 pcireg.h \ ${DESTDIR}${INCLUDEDIR}/dev/pci @@ -257,7 +260,7 @@ symlinks: .PHONY .META ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ done .endfor -.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/nand:Ndev/pci} +.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci} cd ${.CURDIR}/../sys/$i; \ for h in *.h; do \ ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \ @@ -290,6 +293,11 @@ symlinks: .PHONY .META ln -fs ../../../../sys/dev/evdev/$$h \ ${DESTDIR}${INCLUDEDIR}/dev/evdev; \ done + cd ${.CURDIR}/../sys/dev/hyperv/utilities; \ + for h in hv_snapshot.h; do \ + ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/hyperv/utilities/$$h \ + ${DESTDIR}${INCLUDEDIR}/dev/hyperv; \ + done cd ${.CURDIR}/../sys/dev/pci; \ for h in pcireg.h; do \ ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/pci/$$h \ diff --git a/lib/csu/mips/crti.S b/lib/csu/mips/crti.S index cada08d7d46..1553f9e13b9 100644 --- a/lib/csu/mips/crti.S +++ b/lib/csu/mips/crti.S @@ -1,6 +1,7 @@ #include __FBSDID("$FreeBSD$"); + .gnu_attribute 4, 0 .section .init,"ax",%progbits .align 4 .globl _init diff --git a/lib/csu/mips/crtn.S b/lib/csu/mips/crtn.S index 8d190f811e2..8cef67ffec0 100644 --- a/lib/csu/mips/crtn.S +++ b/lib/csu/mips/crtn.S @@ -1,6 +1,7 @@ #include __FBSDID("$FreeBSD$"); + .gnu_attribute 4, 0 .section .init,"ax",%progbits .align 4 .set noreorder diff --git a/lib/libc/Makefile b/lib/libc/Makefile index 99ddfc2e8f7..377a6ee6cd1 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -111,7 +111,8 @@ NOASM= .include "${LIBC_SRCTOP}/xdr/Makefile.inc" .if (${LIBC_ARCH} == "arm" && \ (${MACHINE_ARCH:Marmv6*} == "" || (defined(CPUTYPE) && ${CPUTYPE:M*soft*}))) || \ - (${LIBC_ARCH} == "mips" && ${MACHINE_ARCH:Mmips*hf} == "") + (${LIBC_ARCH} == "mips" && ${MACHINE_ARCH:Mmips*hf} == "") || \ + (${LIBC_ARCH} == "riscv" && ${MACHINE_ARCH:Mriscv*sf} != "") .include "${LIBC_SRCTOP}/softfloat/Makefile.inc" .endif .if ${LIBC_ARCH} == "i386" || ${LIBC_ARCH} == "amd64" diff --git a/lib/libc/riscv/Makefile.inc b/lib/libc/riscv/Makefile.inc index b22190353e3..105839021b9 100644 --- a/lib/libc/riscv/Makefile.inc +++ b/lib/libc/riscv/Makefile.inc @@ -3,6 +3,10 @@ # Machine dependent definitions for the RISC-V architecture. # +.if ${MACHINE_ARCH:Mriscv*sf} != "" +CFLAGS+=-DSOFTFLOAT +.endif + # Long double is quad precision GDTOASRCS+=strtorQ.c MDSRCS+=machdep_ldisQ.c diff --git a/lib/libc/riscv/Symbol.map b/lib/libc/riscv/Symbol.map index 669dad37983..b959072e7e0 100644 --- a/lib/libc/riscv/Symbol.map +++ b/lib/libc/riscv/Symbol.map @@ -35,4 +35,22 @@ FBSDprivate_1.0 { _set_tp; _end; __makecontext; + + /* softfloat */ + __addsf3; + __adddf3; + __subsf3; + __subdf3; + __mulsf3; + __muldf3; + __divsf3; + __divdf3; + __floatsisf; + __floatsidf; + __fixsfsi; + __fixdfsi; + __fixunssfsi; + __fixunsdfsi; + __extendsfdf2; + __truncdfsf2; }; diff --git a/lib/libc/riscv/gen/_setjmp.S b/lib/libc/riscv/gen/_setjmp.S index 1fa064d2ecf..4e82ae42085 100644 --- a/lib/libc/riscv/gen/_setjmp.S +++ b/lib/libc/riscv/gen/_setjmp.S @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2016 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -61,24 +61,21 @@ ENTRY(_setjmp) sd ra, (12 * 8)(a0) addi a0, a0, (13 * 8) -#ifndef _STANDALONE -#if 0 - /* RISCVTODO */ - /* Store the vfp registers */ - fsq fs0, (0 * 16)(a0) - fsq fs1, (1 * 16)(a0) - fsq fs2, (2 * 16)(a0) - fsq fs3, (3 * 16)(a0) - fsq fs4, (4 * 16)(a0) - fsq fs5, (5 * 16)(a0) - fsq fs6, (6 * 16)(a0) - fsq fs7, (7 * 16)(a0) - fsq fs8, (8 * 16)(a0) - fsq fs9, (9 * 16)(a0) - fsq fs10, (10 * 16)(a0) - fsq fs11, (11 * 16)(a0) +#if !defined(_STANDALONE) && !defined(SOFTFLOAT) + /* Store the fpe registers */ + fsd fs0, (0 * 16)(a0) + fsd fs1, (1 * 16)(a0) + fsd fs2, (2 * 16)(a0) + fsd fs3, (3 * 16)(a0) + fsd fs4, (4 * 16)(a0) + fsd fs5, (5 * 16)(a0) + fsd fs6, (6 * 16)(a0) + fsd fs7, (7 * 16)(a0) + fsd fs8, (8 * 16)(a0) + fsd fs9, (9 * 16)(a0) + fsd fs10, (10 * 16)(a0) + fsd fs11, (11 * 16)(a0) addi a0, a0, (12 * 16) -#endif #endif /* Return value */ @@ -117,24 +114,21 @@ ENTRY(_longjmp) ld ra, (12 * 8)(a0) addi a0, a0, (13 * 8) -#ifndef _STANDALONE -#if 0 - /* RISCVTODO */ - /* Restore the vfp registers */ - flq fs0, (0 * 16)(a0) - flq fs1, (1 * 16)(a0) - flq fs2, (2 * 16)(a0) - flq fs3, (3 * 16)(a0) - flq fs4, (4 * 16)(a0) - flq fs5, (5 * 16)(a0) - flq fs6, (6 * 16)(a0) - flq fs7, (7 * 16)(a0) - flq fs8, (8 * 16)(a0) - flq fs9, (9 * 16)(a0) - flq fs10, (10 * 16)(a0) - flq fs11, (11 * 16)(a0) +#if !defined(_STANDALONE) && !defined(SOFTFLOAT) + /* Restore the fpe registers */ + fld fs0, (0 * 16)(a0) + fld fs1, (1 * 16)(a0) + fld fs2, (2 * 16)(a0) + fld fs3, (3 * 16)(a0) + fld fs4, (4 * 16)(a0) + fld fs5, (5 * 16)(a0) + fld fs6, (6 * 16)(a0) + fld fs7, (7 * 16)(a0) + fld fs8, (8 * 16)(a0) + fld fs9, (9 * 16)(a0) + fld fs10, (10 * 16)(a0) + fld fs11, (11 * 16)(a0) addi a0, a0, (12 * 16) -#endif #endif /* Load the return value */ diff --git a/lib/libc/riscv/gen/flt_rounds.c b/lib/libc/riscv/gen/flt_rounds.c index 179963cfa29..13bb8b2a179 100644 --- a/lib/libc/riscv/gen/flt_rounds.c +++ b/lib/libc/riscv/gen/flt_rounds.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2016 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -40,23 +40,24 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef SOFTFLOAT +#include "softfloat-for-gcc.h" +#include "milieu.h" +#include "softfloat.h" +#endif + int __flt_rounds(void) { -#if 0 - uint64_t fcsr; -#endif - int mode; + uint64_t mode; -#if 0 - __asm __volatile("csrr %0, fcsr" : "=r" (fcsr)); - mode = (fcsr & _ROUND_MASK); +#ifdef SOFTFLOAT + mode = __softfloat_float_rounding_mode; +#else + __asm __volatile("csrr %0, fcsr" : "=r" (mode)); #endif - /* RISCVTODO */ - mode = FE_TOWARDZERO; /* softfloat rounding mode */ - - switch (mode) { + switch (mode & _ROUND_MASK) { case FE_TOWARDZERO: return (0); case FE_TONEAREST: diff --git a/lib/libc/riscv/gen/setjmp.S b/lib/libc/riscv/gen/setjmp.S index de8d7b5d519..9d97b51de6b 100644 --- a/lib/libc/riscv/gen/setjmp.S +++ b/lib/libc/riscv/gen/setjmp.S @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2016 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -75,21 +75,20 @@ ENTRY(setjmp) sd ra, (12 * 8)(a0) addi a0, a0, (13 * 8) -#if 0 - /* RISCVTODO */ - /* Store the vfp registers */ - fsq fs0, (0 * 16)(a0) - fsq fs1, (1 * 16)(a0) - fsq fs2, (2 * 16)(a0) - fsq fs3, (3 * 16)(a0) - fsq fs4, (4 * 16)(a0) - fsq fs5, (5 * 16)(a0) - fsq fs6, (6 * 16)(a0) - fsq fs7, (7 * 16)(a0) - fsq fs8, (8 * 16)(a0) - fsq fs9, (9 * 16)(a0) - fsq fs10, (10 * 16)(a0) - fsq fs11, (11 * 16)(a0) +#ifndef SOFTFLOAT + /* Store the fpe registers */ + fsd fs0, (0 * 16)(a0) + fsd fs1, (1 * 16)(a0) + fsd fs2, (2 * 16)(a0) + fsd fs3, (3 * 16)(a0) + fsd fs4, (4 * 16)(a0) + fsd fs5, (5 * 16)(a0) + fsd fs6, (6 * 16)(a0) + fsd fs7, (7 * 16)(a0) + fsd fs8, (8 * 16)(a0) + fsd fs9, (9 * 16)(a0) + fsd fs10, (10 * 16)(a0) + fsd fs11, (11 * 16)(a0) addi a0, a0, (12 * 16) #endif @@ -145,21 +144,20 @@ ENTRY(longjmp) ld ra, (12 * 8)(a0) addi a0, a0, (13 * 8) -#if 0 - /* RISCVTODO */ - /* Restore the vfp registers */ - flq fs0, (0 * 16)(a0) - flq fs1, (1 * 16)(a0) - flq fs2, (2 * 16)(a0) - flq fs3, (3 * 16)(a0) - flq fs4, (4 * 16)(a0) - flq fs5, (5 * 16)(a0) - flq fs6, (6 * 16)(a0) - flq fs7, (7 * 16)(a0) - flq fs8, (8 * 16)(a0) - flq fs9, (9 * 16)(a0) - flq fs10, (10 * 16)(a0) - flq fs11, (11 * 16)(a0) +#ifndef SOFTFLOAT + /* Restore the fpe registers */ + fld fs0, (0 * 16)(a0) + fld fs1, (1 * 16)(a0) + fld fs2, (2 * 16)(a0) + fld fs3, (3 * 16)(a0) + fld fs4, (4 * 16)(a0) + fld fs5, (5 * 16)(a0) + fld fs6, (6 * 16)(a0) + fld fs7, (7 * 16)(a0) + fld fs8, (8 * 16)(a0) + fld fs9, (9 * 16)(a0) + fld fs10, (10 * 16)(a0) + fld fs11, (11 * 16)(a0) addi a0, a0, (12 * 16) #endif diff --git a/lib/libc/riscv/softfloat/milieu.h b/lib/libc/riscv/softfloat/milieu.h new file mode 100644 index 00000000000..e97437bdc2d --- /dev/null +++ b/lib/libc/riscv/softfloat/milieu.h @@ -0,0 +1,48 @@ +/* $FreeBSD$ */ + +/* +=============================================================================== + +This C header file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +Include common integer types and flags. +------------------------------------------------------------------------------- +*/ +#include "riscv-gcc.h" + +/* +------------------------------------------------------------------------------- +Symbolic Boolean literals. +------------------------------------------------------------------------------- +*/ +enum { + FALSE = 0, + TRUE = 1 +}; diff --git a/lib/libc/riscv/softfloat/riscv-gcc.h b/lib/libc/riscv/softfloat/riscv-gcc.h new file mode 100644 index 00000000000..3fe1767e63c --- /dev/null +++ b/lib/libc/riscv/softfloat/riscv-gcc.h @@ -0,0 +1,86 @@ +/* $NetBSD: arm-gcc.h,v 1.2 2001/02/21 18:09:25 bjh21 Exp $ */ +/* $FreeBSD$ */ + +/* +------------------------------------------------------------------------------- +One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. +------------------------------------------------------------------------------- +*/ +#define LITTLEENDIAN + +/* +------------------------------------------------------------------------------- +The macro `BITS64' can be defined to indicate that 64-bit integer types are +supported by the compiler. +------------------------------------------------------------------------------- +*/ +#define BITS64 + +/* +------------------------------------------------------------------------------- +Each of the following `typedef's defines the most convenient type that holds +integers of at least as many bits as specified. For example, `uint8' should +be the most convenient type that can hold unsigned integers of as many as +8 bits. The `flag' type must be able to hold either a 0 or 1. For most +implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed +to the same as `int'. +------------------------------------------------------------------------------- +*/ +typedef int flag; +typedef int uint8; +typedef int int8; +typedef int uint16; +typedef int int16; +typedef unsigned int uint32; +typedef signed int int32; +#ifdef BITS64 +typedef unsigned long long int uint64; +typedef signed long long int int64; +#endif + +/* +------------------------------------------------------------------------------- +Each of the following `typedef's defines a type that holds integers +of _exactly_ the number of bits specified. For instance, for most +implementation of C, `bits16' and `sbits16' should be `typedef'ed to +`unsigned short int' and `signed short int' (or `short int'), respectively. +------------------------------------------------------------------------------- +*/ +typedef unsigned char bits8; +typedef signed char sbits8; +typedef unsigned short int bits16; +typedef signed short int sbits16; +typedef unsigned int bits32; +typedef signed int sbits32; +#ifdef BITS64 +typedef unsigned long long int bits64; +typedef signed long long int sbits64; +#endif + +#ifdef BITS64 +/* +------------------------------------------------------------------------------- +The `LIT64' macro takes as its argument a textual integer literal and +if necessary ``marks'' the literal as having a 64-bit integer type. +For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +appended with the letters `LL' standing for `long long', which is `gcc's +name for the 64-bit integer type. Some compilers may allow `LIT64' to be +defined as the identity macro: `#define LIT64( a ) a'. +------------------------------------------------------------------------------- +*/ +#define LIT64( a ) a##LL +#endif + +/* +------------------------------------------------------------------------------- +The macro `INLINE' can be used before functions that should be inlined. If +a compiler does not support explicit inlining, this macro should be defined +to be `static'. +------------------------------------------------------------------------------- +*/ +#define INLINE static __inline + +#if defined(SOFTFLOAT_FOR_GCC) +#define FLOAT64_DEMANGLE(a) (a) +#define FLOAT64_MANGLE(a) (a) +#endif diff --git a/lib/libc/riscv/softfloat/softfloat.h b/lib/libc/riscv/softfloat/softfloat.h new file mode 100644 index 00000000000..6aef49975a3 --- /dev/null +++ b/lib/libc/riscv/softfloat/softfloat.h @@ -0,0 +1,315 @@ +/* $NetBSD: softfloat.h,v 1.6 2002/05/12 13:12:46 bjh21 Exp $ */ +/* $FreeBSD$ */ + +/* This is a derivative work. */ + +/* +=============================================================================== + +This C header file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +The macro `FLOATX80' must be defined to enable the extended double-precision +floating-point format `floatx80'. If this macro is not defined, the +`floatx80' type will not be defined, and none of the functions that either +input or output the `floatx80' type will be defined. The same applies to +the `FLOAT128' macro and the quadruple-precision format `float128'. +------------------------------------------------------------------------------- +*/ +/* #define FLOATX80 */ +/* #define FLOAT128 */ + +#include + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point types. +------------------------------------------------------------------------------- +*/ +typedef unsigned int float32; +typedef unsigned long long float64; +#ifdef FLOATX80 +typedef struct { + unsigned short high; + unsigned long long low; +} floatx80; +#endif +#ifdef FLOAT128 +typedef struct { + unsigned long long high, low; +} float128; +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point underflow tininess-detection mode. +------------------------------------------------------------------------------- +*/ +#ifndef SOFTFLOAT_FOR_GCC +extern int float_detect_tininess; +#endif +enum { + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 +}; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point rounding mode. +------------------------------------------------------------------------------- +*/ +extern int float_rounding_mode; +enum { + float_round_nearest_even = FE_TONEAREST, + float_round_to_zero = FE_TOWARDZERO, + float_round_down = FE_DOWNWARD, + float_round_up = FE_UPWARD +}; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point exception flags. +------------------------------------------------------------------------------- +*/ +extern int float_exception_flags; +extern int float_exception_mask; +enum { + float_flag_inexact = FE_INEXACT, + float_flag_underflow = FE_UNDERFLOW, + float_flag_overflow = FE_OVERFLOW, + float_flag_divbyzero = FE_DIVBYZERO, + float_flag_invalid = FE_INVALID +}; + +/* +------------------------------------------------------------------------------- +Routine to raise any or all of the software IEC/IEEE floating-point +exception flags. +------------------------------------------------------------------------------- +*/ +void float_raise( int ); + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE integer-to-floating-point conversion routines. +------------------------------------------------------------------------------- +*/ +float32 int32_to_float32( int ); +float64 int32_to_float64( int ); +#ifdef FLOATX80 +floatx80 int32_to_floatx80( int ); +#endif +#ifdef FLOAT128 +float128 int32_to_float128( int ); +#endif +#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */ +float32 int64_to_float32( long long ); +float64 int64_to_float64( long long ); +#ifdef FLOATX80 +floatx80 int64_to_floatx80( long long ); +#endif +#ifdef FLOAT128 +float128 int64_to_float128( long long ); +#endif +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE single-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float32_to_int32( float32 ); +int float32_to_int32_round_to_zero( float32 ); +#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS) +unsigned int float32_to_uint32_round_to_zero( float32 ); +#endif +#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */ +long long float32_to_int64( float32 ); +long long float32_to_int64_round_to_zero( float32 ); +#endif +float64 float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 float32_to_float128( float32 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE single-precision operations. +------------------------------------------------------------------------------- +*/ +float32 float32_round_to_int( float32 ); +float32 float32_add( float32, float32 ); +float32 float32_sub( float32, float32 ); +float32 float32_mul( float32, float32 ); +float32 float32_div( float32, float32 ); +float32 float32_rem( float32, float32 ); +float32 float32_sqrt( float32 ); +int float32_eq( float32, float32 ); +int float32_le( float32, float32 ); +int float32_lt( float32, float32 ); +int float32_eq_signaling( float32, float32 ); +int float32_le_quiet( float32, float32 ); +int float32_lt_quiet( float32, float32 ); +#ifndef SOFTFLOAT_FOR_GCC +int float32_is_signaling_nan( float32 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE double-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float64_to_int32( float64 ); +int float64_to_int32_round_to_zero( float64 ); +#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS) +unsigned int float64_to_uint32_round_to_zero( float64 ); +#endif +#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */ +long long float64_to_int64( float64 ); +long long float64_to_int64_round_to_zero( float64 ); +#endif +float32 float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 float64_to_float128( float64 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE double-precision operations. +------------------------------------------------------------------------------- +*/ +float64 float64_round_to_int( float64 ); +float64 float64_add( float64, float64 ); +float64 float64_sub( float64, float64 ); +float64 float64_mul( float64, float64 ); +float64 float64_div( float64, float64 ); +float64 float64_rem( float64, float64 ); +float64 float64_sqrt( float64 ); +int float64_eq( float64, float64 ); +int float64_le( float64, float64 ); +int float64_lt( float64, float64 ); +int float64_eq_signaling( float64, float64 ); +int float64_le_quiet( float64, float64 ); +int float64_lt_quiet( float64, float64 ); +#ifndef SOFTFLOAT_FOR_GCC +int float64_is_signaling_nan( float64 ); +#endif + +#ifdef FLOATX80 + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int floatx80_to_int32( floatx80 ); +int floatx80_to_int32_round_to_zero( floatx80 ); +long long floatx80_to_int64( floatx80 ); +long long floatx80_to_int64_round_to_zero( floatx80 ); +float32 floatx80_to_float32( floatx80 ); +float64 floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 floatx80_to_float128( floatx80 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision rounding precision. Valid +values are 32, 64, and 80. +------------------------------------------------------------------------------- +*/ +extern int floatx80_rounding_precision; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision operations. +------------------------------------------------------------------------------- +*/ +floatx80 floatx80_round_to_int( floatx80 ); +floatx80 floatx80_add( floatx80, floatx80 ); +floatx80 floatx80_sub( floatx80, floatx80 ); +floatx80 floatx80_mul( floatx80, floatx80 ); +floatx80 floatx80_div( floatx80, floatx80 ); +floatx80 floatx80_rem( floatx80, floatx80 ); +floatx80 floatx80_sqrt( floatx80 ); +int floatx80_eq( floatx80, floatx80 ); +int floatx80_le( floatx80, floatx80 ); +int floatx80_lt( floatx80, floatx80 ); +int floatx80_eq_signaling( floatx80, floatx80 ); +int floatx80_le_quiet( floatx80, floatx80 ); +int floatx80_lt_quiet( floatx80, floatx80 ); +int floatx80_is_signaling_nan( floatx80 ); + +#endif + +#ifdef FLOAT128 + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE quadruple-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float128_to_int32( float128 ); +int float128_to_int32_round_to_zero( float128 ); +long long float128_to_int64( float128 ); +long long float128_to_int64_round_to_zero( float128 ); +float32 float128_to_float32( float128 ); +float64 float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 float128_to_floatx80( float128 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE quadruple-precision operations. +------------------------------------------------------------------------------- +*/ +float128 float128_round_to_int( float128 ); +float128 float128_add( float128, float128 ); +float128 float128_sub( float128, float128 ); +float128 float128_mul( float128, float128 ); +float128 float128_div( float128, float128 ); +float128 float128_rem( float128, float128 ); +float128 float128_sqrt( float128 ); +int float128_eq( float128, float128 ); +int float128_le( float128, float128 ); +int float128_lt( float128, float128 ); +int float128_eq_signaling( float128, float128 ); +int float128_le_quiet( float128, float128 ); +int float128_lt_quiet( float128, float128 ); +int float128_is_signaling_nan( float128 ); + +#endif + diff --git a/lib/libc/softfloat/Makefile.inc b/lib/libc/softfloat/Makefile.inc index f15e4d2a5a4..fa0ee9d2977 100644 --- a/lib/libc/softfloat/Makefile.inc +++ b/lib/libc/softfloat/Makefile.inc @@ -12,8 +12,11 @@ CFLAGS+= -DSOFTFLOAT_FOR_GCC SRCS+= softfloat.c +# Deprecated FPU control interface +.if ${LIBC_ARCH} != "riscv" SRCS+= fpgetround.c fpsetround.c fpgetmask.c fpsetmask.c \ fpgetsticky.c +.endif SRCS+= eqsf2.c nesf2.c gtsf2.c gesf2.c ltsf2.c lesf2.c negsf2.c \ eqdf2.c nedf2.c gtdf2.c gedf2.c ltdf2.c ledf2.c negdf2.c \ diff --git a/lib/libc/sys/sendfile.2 b/lib/libc/sys/sendfile.2 index 2b52dd9c883..313c349ee9f 100644 --- a/lib/libc/sys/sendfile.2 +++ b/lib/libc/sys/sendfile.2 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 7, 2016 +.Dd November 17, 2016 .Dt SENDFILE 2 .Os .Sh NAME @@ -155,8 +155,33 @@ sleeps until the network stack no longer references the VM pages of the file, making subsequent modifications to it safe. Please note that this is not a guarantee that the data has actually been sent. +.It Dv SF_USER_READAHEAD +.Nm +has some internal heuristics to do readahead when sending data. +This flag forces +.Nm +to override any heuristically calculated readahead and use exactly the +application specified readahead. +See +.Sx SETTING READAHEAD +for more details on readahead. .El .Pp +When using a socket marked for non-blocking I/O, +.Fn sendfile +may send fewer bytes than requested. +In this case, the number of bytes successfully +written is returned in +.Fa *sbytes +(if specified), +and the error +.Er EAGAIN +is returned. +.Sh SETTING READAHEAD +.Nm +uses internal heuristics based on request size and file system layout +to do readahead. +Additionally application may request extra readahead. The most significant 16 bits of .Fa flags specify amount of pages that @@ -173,16 +198,13 @@ flag: SF_FLAGS(16, SF_NOCACHE) .Ed .Pp -When using a socket marked for non-blocking I/O, -.Fn sendfile -may send fewer bytes than requested. -In this case, the number of bytes successfully -written is returned in -.Fa *sbytes -(if specified), -and the error -.Er EAGAIN -is returned. +.Nm +will use either application specified readahead or internally calculated, +whichever is bigger. +Setting flag +.Dv SF_USER_READAHEAD +would turn off any heuristics and set maximum possible readahead length to +the number of pages specified via flags. .Sh IMPLEMENTATION NOTES The .Fx diff --git a/lib/libcapsicum/Makefile.depend b/lib/libcapsicum/Makefile.depend new file mode 100644 index 00000000000..f80275d86ab --- /dev/null +++ b/lib/libcapsicum/Makefile.depend @@ -0,0 +1,11 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + + +.include + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/lib/libcompiler_rt/Makefile.inc b/lib/libcompiler_rt/Makefile.inc index f77fc84aaa6..48116d60dc2 100644 --- a/lib/libcompiler_rt/Makefile.inc +++ b/lib/libcompiler_rt/Makefile.inc @@ -130,7 +130,7 @@ SRCF+= cpu_model # # 128-bit quad precision long double support, -# only used on arm64 and riscv. +# only used on some architectures. # .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "riscv" SRCF+= addtf3 @@ -151,8 +151,9 @@ SRCF+= trunctfdf2 SRCF+= trunctfsf2 .endif -# These are already shipped by libc.a on arm and mips -.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips" +# These are already shipped by libc.a on some architectures. +.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips" && \ + ${MACHINE_CPUARCH} != "riscv" SRCF+= adddf3 SRCF+= addsf3 SRCF+= divdf3 diff --git a/lib/libefivar/Makefile.depend b/lib/libefivar/Makefile.depend new file mode 100644 index 00000000000..3646e2e2b1a --- /dev/null +++ b/lib/libefivar/Makefile.depend @@ -0,0 +1,18 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + gnu/lib/libgcc \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + + +.include + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/lib/libgcc_eh/Makefile b/lib/libgcc_eh/Makefile index 04f99d9e85c..9909e73c937 100644 --- a/lib/libgcc_eh/Makefile +++ b/lib/libgcc_eh/Makefile @@ -5,6 +5,7 @@ PACKAGE= clibs LIB= gcc_eh NO_PIC= +MK_SSP= no WARNS?= 2 .include "Makefile.inc" diff --git a/lib/libgcc_s/Makefile b/lib/libgcc_s/Makefile index 6c57741e4d0..e4887a631de 100644 --- a/lib/libgcc_s/Makefile +++ b/lib/libgcc_s/Makefile @@ -1,9 +1,10 @@ # $FreeBSD$ -PKG= clibs +PACKAGE= clibs SHLIB_NAME= libgcc_s.so.1 SHLIBDIR?= /lib +MK_SSP= no WARNS?= 2 LDFLAGS+= -nodefaultlibs diff --git a/lib/libsysdecode/Makefile b/lib/libsysdecode/Makefile index 5e0590e912f..b84ef4e615b 100644 --- a/lib/libsysdecode/Makefile +++ b/lib/libsysdecode/Makefile @@ -110,10 +110,16 @@ CFLAGS.gcc.ioctl.c+= -Wno-unused CFLAGS.gcc+= ${CFLAGS.gcc.${.IMPSRC}} +DEPENDOBJS+= tables.h tables.h: mktables - sh ${.CURDIR}/mktables ${DESTDIR}${INCLUDEDIR} > ${.TARGET} + sh ${.CURDIR}/mktables ${DESTDIR}${INCLUDEDIR} ${.TARGET} -ioctl.c: mkioctls +# mkioctls runs find(1) for headers so needs to rebuild every time. This used +# to be a hack only done in buildworld. +.if !defined(_SKIP_BUILD) +ioctl.c: .PHONY +.endif +ioctl.c: mkioctls .META env MACHINE=${MACHINE} CPP="${CPP}" \ /bin/sh ${.CURDIR}/mkioctls ${DESTDIR}${INCLUDEDIR} > ${.TARGET} diff --git a/lib/libsysdecode/mktables b/lib/libsysdecode/mktables index 0cc2ff3dc77..e51ffe36602 100644 --- a/lib/libsysdecode/mktables +++ b/lib/libsysdecode/mktables @@ -37,11 +37,16 @@ LC_ALL=C; export LC_ALL if [ -z "$1" ] then - echo "usage: sh $0 include-dir" + echo "usage: sh $0 include-dir [output-file]" exit 1 fi include_dir=$1 +if [ -n "$2" ]; then + output_file="$2" + exec > "$output_file" +fi +all_headers= # # Generate a table C #definitions. The including file can define the # TABLE_NAME(n), TABLE_ENTRY(x), and TABLE_END macros to define what @@ -60,6 +65,7 @@ gen_table() else filter="egrep -v" fi + all_headers="${all_headers:+${all_headers} }${file}" cat <<_EOF_ TABLE_START(${name}) _EOF_ @@ -142,3 +148,12 @@ gen_table "sigcode" "SI_[A-Z]+[[:space:]]+0(x[0-9abcdef]+)?" "sys/ gen_table "umtxcvwaitflags" "CVWAIT_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/umtx.h" gen_table "umtxrwlockflags" "URWLOCK_PREFER_READER[[:space:]]+0x[0-9]+" "sys/umtx.h" gen_table "caprights" "CAP_[A-Z_]+[[:space:]]+CAPRIGHT\([0-9],[[:space:]]+0x[0-9]{16}ULL\)" "sys/capsicum.h" + +# Generate a .depend file for our output file +if [ -n "$output_file" ]; then + echo "$output_file: \\" > ".depend.$output_file" + echo "$all_headers" | tr ' ' '\n' | sort -u | + sed -e "s,^, $include_dir/," -e 's,$, \\,' >> \ + ".depend.$output_file" + echo >> ".depend.$output_file" +fi diff --git a/lib/libutil/gr_util.c b/lib/libutil/gr_util.c index 93b3eb2f92f..6153209eb2d 100644 --- a/lib/libutil/gr_util.c +++ b/lib/libutil/gr_util.c @@ -141,7 +141,7 @@ gr_tmp(int mfd) errno = ENAMETOOLONG; return (-1); } - if ((tfd = mkostemp(tempname, O_SYNC)) == -1) + if ((tfd = mkostemp(tempname, 0)) == -1) return (-1); if (mfd != -1) { while ((nr = read(mfd, buf, sizeof(buf))) > 0) diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c index 2838871d93f..d7903281d7c 100644 --- a/lib/libutil/pw_util.c +++ b/lib/libutil/pw_util.c @@ -225,7 +225,7 @@ pw_tmp(int mfd) errno = ENAMETOOLONG; return (-1); } - if ((tfd = mkostemp(tempname, O_SYNC)) == -1) + if ((tfd = mkostemp(tempname, 0)) == -1) return (-1); if (mfd != -1) { while ((nr = read(mfd, buf, sizeof(buf))) > 0) diff --git a/lib/msun/riscv/Makefile.inc b/lib/msun/riscv/Makefile.inc index 97d3302b96d..cd624918bed 100644 --- a/lib/msun/riscv/Makefile.inc +++ b/lib/msun/riscv/Makefile.inc @@ -1,3 +1,8 @@ # $FreeBSD$ +.if ${MACHINE_ARCH:Mriscv*sf} != "" +CFLAGS+=-DSOFTFLOAT +.endif + LDBL_PREC = 113 +SYM_MAPS += ${.CURDIR}/riscv/Symbol.map diff --git a/lib/msun/riscv/Symbol.map b/lib/msun/riscv/Symbol.map new file mode 100644 index 00000000000..081294cf556 --- /dev/null +++ b/lib/msun/riscv/Symbol.map @@ -0,0 +1,21 @@ +/* + * $FreeBSD$ + */ +FBSD_1.0 { +}; + +FBSD_1.3 { + feclearexcept; + fegetexceptflag; + fesetexceptflag; + feraiseexcept; + fetestexcept; + fegetround; + fesetround; + fegetenv; + feholdexcept; + feupdateenv; + feenableexcept; + fedisableexcept; + fegetexcept; +}; diff --git a/lib/msun/riscv/fenv.c b/lib/msun/riscv/fenv.c index a5a5c03d3a7..9bc0d7e3574 100644 --- a/lib/msun/riscv/fenv.c +++ b/lib/msun/riscv/fenv.c @@ -39,6 +39,14 @@ */ const fenv_t __fe_dfl_env = 0; +#ifdef SOFTFLOAT +#define __set_env(env, flags, mask, rnd) env = ((flags) | (rnd) << 5) +#define __env_flags(env) ((env) & FE_ALL_EXCEPT) +#define __env_mask(env) (0) /* No exception traps. */ +#define __env_round(env) (((env) >> 5) & _ROUND_MASK) +#include "fenv-softfloat.h" +#endif + extern inline int feclearexcept(int __excepts); extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts); extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts); @@ -50,3 +58,6 @@ extern inline int fegetenv(fenv_t *__envp); extern inline int feholdexcept(fenv_t *__envp); extern inline int fesetenv(const fenv_t *__envp); extern inline int feupdateenv(const fenv_t *__envp); +extern inline int feenableexcept(int __mask); +extern inline int fedisableexcept(int __mask); +extern inline int fegetexcept(void); diff --git a/lib/msun/riscv/fenv.h b/lib/msun/riscv/fenv.h index 3eae6c2ed16..e66aa1c5775 100644 --- a/lib/msun/riscv/fenv.h +++ b/lib/msun/riscv/fenv.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2004-2005 David Schultz - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2016 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -59,11 +59,11 @@ typedef __uint64_t fexcept_t; /* * RISC-V Rounding modes */ -#define FE_TONEAREST (0x00 << 5) -#define FE_TOWARDZERO (0x01 << 5) -#define FE_DOWNWARD (0x02 << 5) -#define FE_UPWARD (0x03 << 5) #define _ROUND_SHIFT 5 +#define FE_TONEAREST (0x00 << _ROUND_SHIFT) +#define FE_TOWARDZERO (0x01 << _ROUND_SHIFT) +#define FE_DOWNWARD (0x02 << _ROUND_SHIFT) +#define FE_UPWARD (0x03 << _ROUND_SHIFT) #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ FE_UPWARD | FE_TOWARDZERO) @@ -73,96 +73,117 @@ __BEGIN_DECLS extern const fenv_t __fe_dfl_env; #define FE_DFL_ENV (&__fe_dfl_env) -/* We need to be able to map status flag positions to mask flag positions */ -#define _FPUSW_SHIFT 0 -#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) - -#define __rfs(__fpsr) __asm __volatile("csrr %0, fcsr" : "=r" (*(__fpsr))) -#define __wfs(__fpsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fpsr)) +#ifndef SOFTFLOAT +#define __rfs(__fcsr) __asm __volatile("csrr %0, fcsr" : "=r" (__fcsr)) +#define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr)) +#endif +#ifdef SOFTFLOAT +int feclearexcept(int __excepts); +int fegetexceptflag(fexcept_t *__flagp, int __excepts); +int fesetexceptflag(const fexcept_t *__flagp, int __excepts); +int feraiseexcept(int __excepts); +int fetestexcept(int __excepts); +int fegetround(void); +int fesetround(int __round); +int fegetenv(fenv_t *__envp); +int feholdexcept(fenv_t *__envp); +int fesetenv(const fenv_t *__envp); +int feupdateenv(const fenv_t *__envp); +#else __fenv_static inline int feclearexcept(int __excepts) { - fexcept_t __fpsr; - __rfs(&__fpsr); - __fpsr &= ~__excepts; - __wfs(__fpsr); + __asm __volatile("csrc fflags, %0" :: "r"(__excepts)); + return (0); } __fenv_static inline int fegetexceptflag(fexcept_t *__flagp, int __excepts) { - fexcept_t __fpsr; + fexcept_t __fcsr; + + __rfs(__fcsr); + *__flagp = __fcsr & __excepts; - __rfs(&__fpsr); - *__flagp = __fpsr & __excepts; return (0); } __fenv_static inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts) { - fexcept_t __fpsr; + fexcept_t __fcsr; + + __fcsr = *__flagp; + __asm __volatile("csrc fflags, %0" :: "r"(__excepts)); + __asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts)); - __rfs(&__fpsr); - __fpsr &= ~__excepts; - __fpsr |= *__flagp & __excepts; - __wfs(__fpsr); return (0); } __fenv_static inline int feraiseexcept(int __excepts) { - fexcept_t __ex = __excepts; - fesetexceptflag(&__ex, __excepts); /* XXX */ + __asm __volatile("csrs fflags, %0" :: "r"(__excepts)); + return (0); } __fenv_static inline int fetestexcept(int __excepts) { - fexcept_t __fpsr; + fexcept_t __fcsr; - __rfs(&__fpsr); - return (__fpsr & __excepts); + __rfs(__fcsr); + + return (__fcsr & __excepts); } __fenv_static inline int fegetround(void) { + fexcept_t __fcsr; - return (-1); + __rfs(__fcsr); + + return (__fcsr & _ROUND_MASK); } __fenv_static inline int fesetround(int __round) { + fexcept_t __fcsr; - return (-1); + if (__round & ~_ROUND_MASK) + return (-1); + + __rfs(__fcsr); + __fcsr &= ~_ROUND_MASK; + __fcsr |= __round; + __wfs(__fcsr); + + return (0); } __fenv_static inline int fegetenv(fenv_t *__envp) { - __rfs(__envp); + __rfs(*__envp); + return (0); } __fenv_static inline int feholdexcept(fenv_t *__envp) { - fenv_t __env; - __rfs(&__env); - *__envp = __env; - __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); - __wfs(__env); - return (0); + /* No exception traps. */ + + return (-1); } __fenv_static inline int @@ -170,56 +191,59 @@ fesetenv(const fenv_t *__envp) { __wfs(*__envp); + return (0); } __fenv_static inline int feupdateenv(const fenv_t *__envp) { - fexcept_t __fpsr; + fexcept_t __fcsr; - __rfs(&__fpsr); + __rfs(__fcsr); __wfs(*__envp); - feraiseexcept(__fpsr & FE_ALL_EXCEPT); + feraiseexcept(__fcsr & FE_ALL_EXCEPT); + return (0); } +#endif /* !SOFTFLOAT */ #if __BSD_VISIBLE /* We currently provide no external definitions of the functions below. */ +#ifdef SOFTFLOAT +int feenableexcept(int __mask); +int fedisableexcept(int __mask); +int fegetexcept(void); +#else static inline int feenableexcept(int __mask) { - fenv_t __old_fpsr; - fenv_t __new_fpsr; - __rfs(&__old_fpsr); - __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT; - __wfs(__new_fpsr); - return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); + /* No exception traps. */ + + return (-1); } static inline int fedisableexcept(int __mask) { - fenv_t __old_fpsr; - fenv_t __new_fpsr; - __rfs(&__old_fpsr); - __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); - __wfs(__new_fpsr); - return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); + /* No exception traps. */ + + return (0); } static inline int fegetexcept(void) { - fenv_t __fpsr; - __rfs(&__fpsr); - return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); + /* No exception traps. */ + + return (0); } +#endif /* !SOFTFLOAT */ #endif /* __BSD_VISIBLE */ diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 95682d5ceb5..5756c28b81a 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -93,10 +93,7 @@ __FBSDID("$FreeBSD$"); #include #endif -#ifdef USE_BLACKLIST #include "blacklist_client.h" -#endif - #include "pathnames.h" #include "extern.h" diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile index de98da2553a..7efe2f2cc92 100644 --- a/libexec/rtld-elf/Makefile +++ b/libexec/rtld-elf/Makefile @@ -2,7 +2,7 @@ # Use the following command to build local debug version of dynamic # linker: -# make DEBUG_FLAGS=-g DEBUG=-DDEBUG MK_TESTS=no all +# make DEBUG_FLAGS=-g DEBUG=-DDEBUG WITHOUT_TESTS=yes all .include PACKAGE= clibs @@ -47,7 +47,7 @@ CFLAGS+= -DPIC $(DEBUG) .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" CFLAGS+= -fvisibility=hidden .endif -LDFLAGS+= -shared -Wl,-Bsymbolic +LDFLAGS+= -shared -Wl,-Bsymbolic -Wl,-z,defs LIBADD= c_pic .if ${MK_TOOLCHAIN} == "no" LDFLAGS+= -L${LIBCDIR} diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c index de7ffd59482..cff813ac805 100644 --- a/libexec/rtld-elf/aarch64/reloc.c +++ b/libexec/rtld-elf/aarch64/reloc.c @@ -299,6 +299,11 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj, return target; } +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ +} + /* * Process non-PLT relocations */ diff --git a/libexec/rtld-elf/aarch64/rtld_machdep.h b/libexec/rtld-elf/aarch64/rtld_machdep.h index a2fc74af73e..46101432567 100644 --- a/libexec/rtld-elf/aarch64/rtld_machdep.h +++ b/libexec/rtld-elf/aarch64/rtld_machdep.h @@ -61,7 +61,10 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) -#define round(size, align) \ +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(void))ptr)()) + +#define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ round(16, align) diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c index 80a3c35d659..43e3ce969c5 100644 --- a/libexec/rtld-elf/amd64/reloc.c +++ b/libexec/rtld-elf/amd64/reloc.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -406,7 +407,7 @@ reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate) ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); where = (Elf_Addr *)(obj->relocbase + rela->r_offset); lock_release(rtld_bind_lock, lockstate); - target = ((Elf_Addr (*)(void))ptr)(); + target = call_ifunc_resolver(ptr); wlock_acquire(rtld_bind_lock, lockstate); *where = target; break; @@ -450,6 +451,25 @@ reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate) return (0); } +uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2; + +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ + u_int p[4], cpu_high; + + do_cpuid(1, p); + cpu_feature = p[3]; + cpu_feature2 = p[2]; + do_cpuid(0, p); + cpu_high = p[0]; + if (cpu_high >= 7) { + cpuid_count(7, 0, p); + cpu_stdext_feature = p[1]; + cpu_stdext_feature2 = p[2]; + } +} + void allocate_initial_tls(Obj_Entry *objs) { diff --git a/libexec/rtld-elf/amd64/rtld_machdep.h b/libexec/rtld-elf/amd64/rtld_machdep.h index a8696feb37a..df6fc339132 100644 --- a/libexec/rtld-elf/amd64/rtld_machdep.h +++ b/libexec/rtld-elf/amd64/rtld_machdep.h @@ -61,6 +61,14 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) +extern uint32_t cpu_feature; +extern uint32_t cpu_feature2; +extern uint32_t cpu_stdext_feature; +extern uint32_t cpu_stdext_feature2; +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(uint32_t, uint32_t, uint32_t, uint32_t))ptr)( \ + cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2)) + #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c index b6d0babfc87..94a9bf0e021 100644 --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -479,6 +479,11 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj, return target; } +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ +} + void allocate_initial_tls(Obj_Entry *objs) { diff --git a/libexec/rtld-elf/arm/rtld_machdep.h b/libexec/rtld-elf/arm/rtld_machdep.h index c61bce0cdd2..2c1a2b80c89 100644 --- a/libexec/rtld-elf/arm/rtld_machdep.h +++ b/libexec/rtld-elf/arm/rtld_machdep.h @@ -51,6 +51,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(void))ptr)()) + #define TLS_TCB_SIZE 8 typedef struct { unsigned long ti_module; diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c index 2d6021c9779..8a405fbccb6 100644 --- a/libexec/rtld-elf/i386/reloc.c +++ b/libexec/rtld-elf/i386/reloc.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -359,7 +360,7 @@ reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate) case R_386_IRELATIVE: where = (Elf_Addr *)(obj->relocbase + rel->r_offset); lock_release(rtld_bind_lock, lockstate); - target = ((Elf_Addr (*)(void))(obj->relocbase + *where))(); + target = call_ifunc_resolver(obj->relocbase + *where); wlock_acquire(rtld_bind_lock, lockstate); *where = target; break; @@ -404,6 +405,45 @@ reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate) return (0); } +uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2; + +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ + u_int p[4], cpu_high; + int cpuid_supported; + + __asm __volatile( + " pushfl\n" + " popl %%eax\n" + " movl %%eax,%%ecx\n" + " xorl $0x200000,%%eax\n" + " pushl %%eax\n" + " popfl\n" + " pushfl\n" + " popl %%eax\n" + " xorl %%eax,%%ecx\n" + " je 1f\n" + " movl $1,%0\n" + " jmp 2f\n" + "1: movl $0,%0\n" + "2:\n" + : "=r" (cpuid_supported) : : "eax", "ecx"); + if (!cpuid_supported) + return; + + do_cpuid(1, p); + cpu_feature = p[3]; + cpu_feature2 = p[2]; + do_cpuid(0, p); + cpu_high = p[0]; + if (cpu_high >= 7) { + cpuid_count(7, 0, p); + cpu_stdext_feature = p[1]; + cpu_stdext_feature2 = p[2]; + } +} + void allocate_initial_tls(Obj_Entry *objs) { diff --git a/libexec/rtld-elf/i386/rtld_machdep.h b/libexec/rtld-elf/i386/rtld_machdep.h index 5237d4fce04..1ffdca411c7 100644 --- a/libexec/rtld-elf/i386/rtld_machdep.h +++ b/libexec/rtld-elf/i386/rtld_machdep.h @@ -61,6 +61,14 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) +extern uint32_t cpu_feature; +extern uint32_t cpu_feature2; +extern uint32_t cpu_stdext_feature; +extern uint32_t cpu_stdext_feature2; +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(uint32_t, uint32_t, uint32_t, uint32_t))ptr)( \ + cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2)) + #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ diff --git a/libexec/rtld-elf/mips/reloc.c b/libexec/rtld-elf/mips/reloc.c index 0f4a5d66bd1..4f3d5c450d1 100644 --- a/libexec/rtld-elf/mips/reloc.c +++ b/libexec/rtld-elf/mips/reloc.c @@ -617,6 +617,11 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj, return target; } +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ +} + void allocate_initial_tls(Obj_Entry *objs) { diff --git a/libexec/rtld-elf/mips/rtld_machdep.h b/libexec/rtld-elf/mips/rtld_machdep.h index 34e8f3c591f..484af1b4133 100644 --- a/libexec/rtld-elf/mips/rtld_machdep.h +++ b/libexec/rtld-elf/mips/rtld_machdep.h @@ -52,6 +52,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(void))ptr)()) + typedef struct { unsigned long ti_module; unsigned long ti_offset; diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c index 79d41f21fb6..e76da987f21 100644 --- a/libexec/rtld-elf/powerpc/reloc.c +++ b/libexec/rtld-elf/powerpc/reloc.c @@ -619,6 +619,11 @@ init_pltgot(Obj_Entry *obj) */ } +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ +} + void allocate_initial_tls(Obj_Entry *list) { diff --git a/libexec/rtld-elf/powerpc/rtld_machdep.h b/libexec/rtld-elf/powerpc/rtld_machdep.h index 3e39c8231c0..92bbf9a3de0 100644 --- a/libexec/rtld-elf/powerpc/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc/rtld_machdep.h @@ -51,6 +51,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(void))ptr)()) + /* * Lazy binding entry point, called via PLT. */ diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c index 3db5fd25441..6a09185b73a 100644 --- a/libexec/rtld-elf/powerpc64/reloc.c +++ b/libexec/rtld-elf/powerpc64/reloc.c @@ -523,6 +523,11 @@ init_pltgot(Obj_Entry *obj) #endif } +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ +} + void allocate_initial_tls(Obj_Entry *list) { diff --git a/libexec/rtld-elf/powerpc64/rtld_machdep.h b/libexec/rtld-elf/powerpc64/rtld_machdep.h index 32c7d12d449..90253d70d92 100644 --- a/libexec/rtld-elf/powerpc64/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc64/rtld_machdep.h @@ -51,6 +51,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(void))ptr)()) + /* * Lazy binding entry point, called via PLT. */ diff --git a/libexec/rtld-elf/riscv/reloc.c b/libexec/rtld-elf/riscv/reloc.c index 92c4276df08..5da0bd17566 100644 --- a/libexec/rtld-elf/riscv/reloc.c +++ b/libexec/rtld-elf/riscv/reloc.c @@ -366,6 +366,11 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, return (0); } +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ +} + void allocate_initial_tls(Obj_Entry *objs) { diff --git a/libexec/rtld-elf/riscv/rtld_machdep.h b/libexec/rtld-elf/riscv/rtld_machdep.h index 660787f5d16..46387e7bcdd 100644 --- a/libexec/rtld-elf/riscv/rtld_machdep.h +++ b/libexec/rtld-elf/riscv/rtld_machdep.h @@ -78,6 +78,9 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, __asm __volatile("mv gp, %0" :: "r"(old1)); \ }) +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(void))ptr)()) + /* * Lazy binding entry point, called via PLT. */ diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 6c8aff44bf9..874f80bdd35 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -642,6 +642,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ map_stacks_exec(NULL); + ifunc_init(aux); dbg("resolving ifuncs"); if (resolve_objects_ifunc(obj_main, @@ -690,7 +691,7 @@ rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def) Elf_Addr target; ptr = (void *)make_function_pointer(def, obj); - target = ((Elf_Addr (*)(void))ptr)(); + target = call_ifunc_resolver(ptr); return ((void *)target); } diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 8b7024b841a..99b56c12959 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -367,6 +367,7 @@ void dump_Elf_Rela(Obj_Entry *, const Elf_Rela *, u_long); unsigned long elf_hash(const char *); const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *, const Obj_Entry **, int, SymCache *, struct Struct_RtldLockState *); +void ifunc_init(Elf_Auxinfo[static AT_COUNT]); void init_pltgot(Obj_Entry *); void lockdflt_init(void); void digest_notes(Obj_Entry *, Elf_Addr, Elf_Addr); diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c index f8534e8712f..981eea502b8 100644 --- a/libexec/rtld-elf/sparc64/reloc.c +++ b/libexec/rtld-elf/sparc64/reloc.c @@ -786,6 +786,11 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *obj, return (target); } +void +ifunc_init(Elf_Auxinfo aux_info[static AT_COUNT] __unused) +{ +} + /* * Install rtld function call into this PLT slot. */ diff --git a/libexec/rtld-elf/sparc64/rtld_machdep.h b/libexec/rtld-elf/sparc64/rtld_machdep.h index 9df63b8bb1f..b53f79795e1 100644 --- a/libexec/rtld-elf/sparc64/rtld_machdep.h +++ b/libexec/rtld-elf/sparc64/rtld_machdep.h @@ -53,7 +53,10 @@ Elf_Addr reloc_jmpslot(Elf_Addr *, Elf_Addr, #define call_init_pointer(obj, target) \ (((InitArrFunc)(target))(main_argc, main_argv, environ)) -#define round(size, align) \ +#define call_ifunc_resolver(ptr) \ + (((Elf_Addr (*)(void))ptr)()) + +#define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ round(size, align) diff --git a/release/Makefile.vm b/release/Makefile.vm index 1c6a1936058..caca7cfa657 100644 --- a/release/Makefile.vm +++ b/release/Makefile.vm @@ -55,7 +55,7 @@ ${_CW:tu}CONF?= ${.CURDIR}/tools/${_CW:tl}.conf cw-${_CW:tl}: mkdir -p ${.OBJDIR}/${.TARGET} - env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ + env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} SWAPSIZE=${SWAPSIZE} \ ${.CURDIR}/scripts/mk-vmimage.sh \ -C ${.CURDIR}/tools/vmimage.subr -d ${.OBJDIR}/${.TARGET} \ -i ${.OBJDIR}/${_CW:tl}.img -s ${VMSIZE} -f ${${_CW}_FORMAT} \ @@ -89,7 +89,7 @@ vm-image: .if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) . for FORMAT in ${VMFORMATS} mkdir -p ${.OBJDIR}/${.TARGET} - env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ + env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} SWAPSIZE=${SWAPSIZE} \ ${.CURDIR}/scripts/mk-vmimage.sh \ -C ${.CURDIR}/tools/vmimage.subr -d ${.OBJDIR}/${.TARGET} \ -i ${.OBJDIR}/${FORMAT}.img -s ${VMSIZE} -f ${FORMAT} \ diff --git a/release/doc/en_US.ISO8859-1/hardware/article.xml b/release/doc/en_US.ISO8859-1/hardware/article.xml index 5d644385866..d70d2408907 100644 --- a/release/doc/en_US.ISO8859-1/hardware/article.xml +++ b/release/doc/en_US.ISO8859-1/hardware/article.xml @@ -800,6 +800,8 @@ &hwlist.bge; + &hwlist.bnxt; + &hwlist.bxe; &hwlist.cas; diff --git a/rescue/rescue/Makefile.depend b/rescue/rescue/Makefile.depend index 38219b53ac8..5debdae2f66 100644 --- a/rescue/rescue/Makefile.depend +++ b/rescue/rescue/Makefile.depend @@ -24,6 +24,7 @@ DIRDEPS = \ lib/libbz2 \ lib/libc \ lib/libcam \ + lib/libcapsicum \ lib/libcompiler_rt \ lib/libcrypt \ lib/libdevstat \ diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c index 2f9ccf9c6fe..ee56ff9106d 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.c +++ b/sbin/etherswitchcfg/etherswitchcfg.c @@ -308,7 +308,8 @@ set_vlangroup_vid(struct cfg *cfg, char *argv[]) { int v; etherswitch_vlangroup_t vg; - + + memset(&vg, 0, sizeof(vg)); v = strtol(argv[1], NULL, 0); if (v < 0 || v > IEEE802DOT1Q_VID_MAX) errx(EX_USAGE, "vlan must be between 0 and %d", IEEE802DOT1Q_VID_MAX); @@ -327,8 +328,9 @@ set_vlangroup_members(struct cfg *cfg, char *argv[]) int member, untagged; char *c, *d; int v; - + member = untagged = 0; + memset(&vg, 0, sizeof(vg)); if (strcmp(argv[1], "none") != 0) { for (c=argv[1]; *c; c=d) { v = strtol(c, &d, 0); diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index f91888702cd..c7017f074b0 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -3785,12 +3785,6 @@ list_keys(int s) { } -#define IEEE80211_C_BITS \ - "\20\1STA\002803ENCAP\7FF\10TURBOP\11IBSS\12PMGT" \ - "\13HOSTAP\14AHDEMO\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE" \ - "\21MONITOR\22DFS\23MBSS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \ - "\37TXFRAG\40TDMA" - static void list_capabilities(int s) { diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index b3218d5ed38..2834a0b664d 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -2910,8 +2910,9 @@ pack_table(struct tidx *tstate, char *name) return (pack_object(tstate, name, IPFW_TLV_TBL_NAME)); } -static void -fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate) +void +fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode, + struct tidx *tstate) { uint32_t *d = ((ipfw_insn_u32 *)cmd)->d; uint16_t uidx; @@ -3570,7 +3571,7 @@ add_src(ipfw_insn *cmd, char *av, u_char proto, int cblen, struct tidx *tstate) if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) - ret = add_srcip6(cmd, av, cblen); + ret = add_srcip6(cmd, av, cblen, tstate); /* XXX: should check for IPv4, not !IPv6 */ if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || inet_pton(AF_INET6, host, &a) != 1)) @@ -3601,7 +3602,7 @@ add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen, struct tidx *tstate) if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) - ret = add_dstip6(cmd, av, cblen); + ret = add_dstip6(cmd, av, cblen, tstate); /* XXX: should check for IPv4, not !IPv6 */ if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || inet_pton(AF_INET6, host, &a) != 1)) @@ -4670,14 +4671,14 @@ read_options: case TOK_SRCIP6: NEED1("missing source IP6"); - if (add_srcip6(cmd, *av, cblen)) { + if (add_srcip6(cmd, *av, cblen, tstate)) { av++; } break; case TOK_DSTIP6: NEED1("missing destination IP6"); - if (add_dstip6(cmd, *av, cblen)) { + if (add_dstip6(cmd, *av, cblen, tstate)) { av++; } break; diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index 0768b2f37a9..efcdde9c422 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -396,8 +396,11 @@ void print_flow6id(struct buf_pr *bp, struct _ipfw_insn_u32 *cmd); void print_icmp6types(struct buf_pr *bp, struct _ipfw_insn_u32 *cmd); void print_ext6hdr(struct buf_pr *bp, struct _ipfw_insn *cmd ); -struct _ipfw_insn *add_srcip6(struct _ipfw_insn *cmd, char *av, int cblen); -struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av, int cblen); +struct tidx; +struct _ipfw_insn *add_srcip6(struct _ipfw_insn *cmd, char *av, int cblen, + struct tidx *tstate); +struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av, int cblen, + struct tidx *tstate); void fill_flow6(struct _ipfw_insn_u32 *cmd, char *av, int cblen); void fill_unreach6_code(u_short *codep, char *str); @@ -406,6 +409,8 @@ int fill_ext6hdr(struct _ipfw_insn *cmd, char *av); /* ipfw2.c */ void bp_flush(struct buf_pr *b); +void fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode, + struct tidx *tstate); /* tables.c */ struct _ipfw_obj_ctlv; diff --git a/sbin/ipfw/ipv6.c b/sbin/ipfw/ipv6.c index e54ad512d94..fca666d394b 100644 --- a/sbin/ipfw/ipv6.c +++ b/sbin/ipfw/ipv6.c @@ -335,7 +335,7 @@ lookup_host6 (char *host, struct in6_addr *ip6addr) * Return 1 on success, 0 on failure. */ static int -fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen) +fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen, struct tidx *tstate) { int len = 0; struct in6_addr *d = &(cmd->addr6); @@ -361,18 +361,7 @@ fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen) } if (strncmp(av, "table(", 6) == 0) { - char *p = strchr(av + 6, ','); - uint32_t *dm = ((ipfw_insn_u32 *)cmd)->d; - - if (p) - *p++ = '\0'; - cmd->o.opcode = O_IP_DST_LOOKUP; - cmd->o.arg1 = strtoul(av + 6, NULL, 0); - if (p) { - cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32); - dm[0] = strtoul(p, NULL, 0); - } else - cmd->o.len |= F_INSN_SIZE(ipfw_insn); + fill_table(&cmd->o, av, O_IP_DST_LOOKUP, tstate); return (1); } @@ -498,10 +487,10 @@ fill_flow6( ipfw_insn_u32 *cmd, char *av, int cblen) } ipfw_insn * -add_srcip6(ipfw_insn *cmd, char *av, int cblen) +add_srcip6(ipfw_insn *cmd, char *av, int cblen, struct tidx *tstate) { - fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen); + fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen, tstate); if (cmd->opcode == O_IP_DST_SET) /* set */ cmd->opcode = O_IP_SRC_SET; else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */ @@ -520,10 +509,10 @@ add_srcip6(ipfw_insn *cmd, char *av, int cblen) } ipfw_insn * -add_dstip6(ipfw_insn *cmd, char *av, int cblen) +add_dstip6(ipfw_insn *cmd, char *av, int cblen, struct tidx *tstate) { - fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen); + fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen, tstate); if (cmd->opcode == O_IP_DST_SET) /* set */ ; else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */ diff --git a/sbin/md5/Makefile.depend b/sbin/md5/Makefile.depend index 064e492dd3e..8aac374844e 100644 --- a/sbin/md5/Makefile.depend +++ b/sbin/md5/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ lib/libmd \ diff --git a/sbin/zfsbootcfg/Makefile.depend b/sbin/zfsbootcfg/Makefile.depend new file mode 100644 index 00000000000..b1a2eff6cb4 --- /dev/null +++ b/sbin/zfsbootcfg/Makefile.depend @@ -0,0 +1,32 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + cddl/lib/libavl \ + cddl/lib/libnvpair \ + cddl/lib/libumem \ + cddl/lib/libuutil \ + cddl/lib/libzfs \ + cddl/lib/libzfs_core \ + gnu/lib/csu \ + gnu/lib/libgcc \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + lib/libexpat \ + lib/libgeom \ + lib/libmd \ + lib/libsbuf \ + lib/libthr \ + lib/libutil \ + lib/libz \ + lib/msun \ + + +.include + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/share/examples/jails/rc.conf.jails b/share/examples/jails/rc.conf.jails index 674dce538ea..6906b7a2eeb 100644 --- a/share/examples/jails/rc.conf.jails +++ b/share/examples/jails/rc.conf.jails @@ -5,7 +5,7 @@ ############################################################################### jail_enable="YES" -jail_list="xxx" +jail_list="XXX" # # Global presets for all jails @@ -57,19 +57,19 @@ jail_devfs_enable="YES" # mount devfs # # XXX # -jail_xxx_hostname="xxx.yyy" # hostname -jail_xxx_rootdir="/vm/xxx" # root directory +jail_XXX_hostname="XXX.YYY" # hostname +jail_XXX_rootdir="/vm/XXX" # root directory # netgraph -jail_xxx_vnet_interface="ng0_xxx" # vnet interface(s) -jail_xxx_exec_prestart0="jng bridge xxx em0" # bridge interface(s) -jail_xxx_exec_poststop0="jng shutdown xxx" # destroy interface(s) +jail_XXX_vnet_interface="ng0_XXX" # vnet interface(s) +jail_XXX_exec_prestart0="jng bridge XXX em0" # bridge interface(s) +jail_XXX_exec_poststop0="jng shutdown XXX" # destroy interface(s) # if_bridge -#jail_xxx_vnet_interface="e0b_xxx" # vnet interface(s) -#jail_xxx_exec_prestart0="jib addm xxx em0" # bridge interface(s) -#jail_xxx_exec_poststop0="jib destroy xxx" # destroy interface(s) +#jail_XXX_vnet_interface="e0b_XXX" # vnet interface(s) +#jail_XXX_exec_prestart0="jib addm XXX em0" # bridge interface(s) +#jail_XXX_exec_poststop0="jib destroy XXX" # destroy interface(s) # Optional (default off) -#jail_xxx_devfs_ruleset="11" # rule to unhide bpf for DHCP -#jail_xxx_mount_enable="YES" # mount /etc/fstab.xxx +#jail_XXX_devfs_ruleset="11" # rule to unhide bpf for DHCP +#jail_XXX_mount_enable="YES" # mount /etc/fstab.XXX ################################################################################ # END diff --git a/share/examples/jails/rcjail.xxx.conf b/share/examples/jails/rcjail.xxx.conf index a292905109c..be711833e29 100644 --- a/share/examples/jails/rcjail.xxx.conf +++ b/share/examples/jails/rcjail.xxx.conf @@ -1,25 +1,25 @@ # $FreeBSD$ -jail_xxx_hostname="xxx.yyy" # hostname -jail_xxx_rootdir="/vm/xxx" # root directory +jail_XXX_hostname="XXX.YYY" # hostname +jail_XXX_rootdir="/vm/XXX" # root directory # # NB: Below 3 lines required # # netgraph -jail_xxx_vnet_interface="ng0_xxx" # vnet interface(s) -jail_xxx_exec_prestart0="jng bridge xxx em0" # bridge interface(s) -jail_xxx_exec_poststop0="jng shutdown xxx" # destroy interface(s) +jail_XXX_vnet_interface="ng0_XXX" # vnet interface(s) +jail_XXX_exec_prestart0="jng bridge XXX em0" # bridge interface(s) +jail_XXX_exec_poststop0="jng shutdown XXX" # destroy interface(s) # if_bridge -#jail_xxx_vnet_interface="e0b_xxx" # vnet interface(s) -#jail_xxx_exec_prestart0="jib addm xxx em0" # bridge interface(s) -#jail_xxx_exec_poststop0="jib destroy xxx" # destroy interface(s) +#jail_XXX_vnet_interface="e0b_XXX" # vnet interface(s) +#jail_XXX_exec_prestart0="jib addm XXX em0" # bridge interface(s) +#jail_XXX_exec_poststop0="jib destroy XXX" # destroy interface(s) # Standard recipe -jail_xxx_devfs_enable="YES" # mount devfs +jail_XXX_devfs_enable="YES" # mount devfs # Optional (default off) -#jail_xxx_devfs_ruleset="11" # rule to unhide bpf for DHCP -#jail_xxx_mount_enable="YES" # mount /etc/fstab.xxx -#jail_xxx_set_hostname_allow="YES" # Allow hostname to change -#jail_xxx_sysvipc_allow="YES" # Allow SysV Interprocess Comm. +#jail_XXX_devfs_ruleset="11" # rule to unhide bpf for DHCP +#jail_XXX_mount_enable="YES" # mount /etc/fstab.XXX +#jail_XXX_set_hostname_allow="YES" # Allow hostname to change +#jail_XXX_sysvipc_allow="YES" # Allow SysV Interprocess Comm. diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 61f1a89c5f2..98697541983 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -79,6 +79,7 @@ MAN= aac.4 \ bhndb.4 \ bktr.4 \ blackhole.4 \ + bnxt.4 \ bpf.4 \ bridge.4 \ bt.4 \ @@ -186,12 +187,12 @@ MAN= aac.4 \ ${_hptmv.4} \ ${_hptnr.4} \ ${_hptrr.4} \ - hv_ata_pci_disengage.4 \ hv_kvp.4 \ hv_netvsc.4 \ hv_storvsc.4 \ hv_utils.4 \ hv_vmbus.4 \ + hv_vss.4 \ hwpmc.4 \ ichsmb.4 \ ${_ichwd.4} \ @@ -591,6 +592,7 @@ MLINKS+=bce.4 if_bce.4 MLINKS+=bfe.4 if_bfe.4 MLINKS+=bge.4 if_bge.4 MLINKS+=bktr.4 brooktree.4 +MLINKS+=bnxt.4 if_bnxt.4 MLINKS+=bridge.4 if_bridge.4 MLINKS+=bwi.4 if_bwi.4 MLINKS+=bwn.4 if_bwn.4 diff --git a/share/man/man4/bnxt.4 b/share/man/man4/bnxt.4 new file mode 100644 index 00000000000..4b8f6e3e7f9 --- /dev/null +++ b/share/man/man4/bnxt.4 @@ -0,0 +1,224 @@ +.\" Copyright (c) 2016 Broadcom, All Rights Reserved. +.\" The term Broadcom refers to Broadcom Limited and/or its subsidiaries +.\" +.\" 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' +.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +.\" THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd November 16, 2016 +.Dt BNXT 4 +.Os +.Sh NAME +.Nm bnxt +.Nd "Broadcom NetXtreme-C/NetXtreme-E Family Ethernet driver" +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device bnxt" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +if_bnxt_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides support for various NICs based on the Broadcom BCM57301/2/4, +and BCM57402/4/6 Ethernet controller chips. +.Pp +For more information on configuring this device, see +.Xr ifconfig 8 . +.Sh HARDWARE +The +.Nm +driver provides support for various NICs based on the Broadcom NetXtreme-C and +NetXtreme-E families of Gigabit Ethernet controller chips, including the +following: +.Pp +.Bl -bullet -compact +.It +Broadcom BCM57301 NetXtreme-C 10Gb Ethernet Controller +.It +Broadcom BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller +.It +Broadcom BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller +.It +Broadcom BCM57402 NetXtreme-E 10Gb Ethernet Controller +.It +Broadcom BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller +.It +Broadcom BCM57406 NetXtreme-E 10GBase-T Ethernet Controller +.It +Broadcom BCM57402 NetXtreme-E Partition +.It +Broadcom BCM57407 NetXtreme-E 10GBase-T Ethernet Controller +.It +Broadcom BCM57404 NetXtreme-E Partition +.It +Broadcom BCM57406 NetXtreme-E Partition +.It +Broadcom BCM57407 NetXtreme-E 25Gb Ethernet Controller +.It +Broadcom BCM57304 NetXtreme-C Virtual Function +.It +Broadcom BCM57404 NetXtreme-E Virtual Function +.El +.Sh SYSCTL VARIABLES +These variables must be set before loading the driver, either via +.Xr loader.conf 5 +or through the use of +.Xr kenv 1 . +These are provided by the +.Xr iflib 9 +framework, and might be better documented there. +.Bl -tag -width indent +.It Va dev.bnxt.X.iflib.override_nrxds +Override the number of RX descriptors for each queue. +The value is a comma separated list of three positive integers: the size of the +completion ring, +the size of the receive ring, and the size of the aggregation ring respectively. +The completion ring should be at least the size of the aggregation ring plus +four times the size of the receive ring. +These numbers must be powers of two, and zero means to use the default. +Defaults to 0,0,0. +.It Va dev.bnxt.X.iflib.override_ntxds +Override the number of TX descriptors for each queue. +The value is a comma separated list of two positive integers: the size of the +completion ring, and the size of the transmit ring respectively. +The completion ring should be at least twice the size of the transmit ring. +These numbers must be powers of two, and zero means to use the default. +Defaults to 0,0. +.It Va override_qs_enable +When set, allows the number of transmit and receive queues to be different. +If not set, the lower of the number of TX or RX queues will be used for both. +.It Va override_nrxqs +Set the number of RX queues. +If zero, the number of RX queues is derived from the number of cores on the +socket connected to the controller. +Defaults to 0. +.It Va override_ntxqs +Set the number of TX queues. +If zero, the number of TX queues is derived from the number of cores on the +socket connected to the controller. +.El +.Pp +These +.Xr sysctl 8 +variables can be changed at any time: +.Bl -tag -width indent +.It Va dev.bnxt.X.vlan_only +Require that incoming frames must have a VLAN tag on them that matches one that +is configured for the NIC. +Normally, both frames that have a matching VLAN tag and frames that have no +VLAN tag are accepted. +Defaults to 0. +.It Va dev.bnxt.X.vlan_strip +When non-zero the NIC strips VLAN tags on receive. +Defaults to 0. +.It Va dev.bnxt.X.rx_stall +Enable buffering rather than dropping frames when there are no available host +RX buffers for DMA. +Defaults to 0. +.It Va dev.bnxt.X.rss_type +Comma-separated list of RSS hash types to support. +Default is all types. +Defaults to ipv4,tcp_ipv4,udp_ipv4,ipv6,tcp_ipv6,udp_ipv6. +.It Va dev.bnxt.X.rss_key +Current RSS key. +Defaults to a randomly generated value which is generated for each device +during attach. +.It Va dev.bnxt.X.ver.hwrm_min_ver +Minimum HWRM (HardWare Resource Manager) firmware API to support. +If the firmware implements an older version, a warning will be printed, and the +firmware should be upgraded. +Defaults to 1.2.2. +.El +.Pp +These +.Xr sysctl 8 +variables are read-only: +.Bl -tag -width indent +.It Va dev.bnxt.X.if_name +Current interface name of the device. +This will normally be +.Va bnxtX , +but this can be changed using +.Cm ifconfig name . +This sysctl allows correlating an interface with a child of +.Va dev.bnxt . +.It Va dev.bnxt.X.nvram.* +Information about the NVRAM device which contains the device firmware. +.It Va dev.bnxt.X.ver.* +Version-related information about the device and firmware: +.It Va dev.bnxt.X.ver.hwrm_if +Supported HWRM API version of the currently running firmware. +.It Va dev.bnxt.X.ver.driver_hwrm_if +HWRM API version the driver was built to support. +.It Va dev.bnxt.X.hwstats.* +Per-queue statistics tracked by the hardware. +.It Va dev.bnxt.X.hwstats.rxq0.drop_pkts +Number of packets dropped by hardware on queue zero. +This number might seem high, but the count includes packets dropped due to +incorrect destination MAC, unsubscribed multicast address, and other normal +reasons to ignore Ethernet frames. +.El +.Sh DIAGNOSTICS +.Bl -diag +.It "bnxt%d: %s command returned %s error." +Device firmware rejected a command from the driver. +There might be a driver/firmware HWRM API mismatch. +.It "bnxt%d: Timeout sending %s (timeout: %d) seq %d" +Device firmware unresponsive. +A PCI device reset is likely needed. +.It "bnxt%d: Timeout sending %s (timeout: %d) msg {0x%x 0x%x} len:%d v: %d" +Partial firmware response. +A PCI device reset is likely needed. +.Pp +As of this writing, the system must be rebooted to initiate a PCI device reset. +.El +.Sh SEE ALSO +.Xr altq 4 , +.Xr arp 4 , +.Xr iflib 4 , +.Xr netintro 4 , +.Xr ng_ether 4 , +.Xr vlan 4 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Fx 12.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Jack Vogel Aq Mt jfvogel@gmail.com , +and is currently maintained by +.An Stephen Hurd Aq Mt stephen.hurd@broadcom.com . diff --git a/share/man/man4/hv_vmbus.4 b/share/man/man4/hv_vmbus.4 index d992be521b4..eb661b8c26e 100644 --- a/share/man/man4/hv_vmbus.4 +++ b/share/man/man4/hv_vmbus.4 @@ -35,6 +35,7 @@ To compile this driver into the kernel, place the following lines in the system kernel configuration file: .Bd -ragged -offset indent .Cd "device hyperv" +.Cd "device pci" .Ed .Sh DESCRIPTION The @@ -73,7 +74,6 @@ the interface that facilitate high performance bi-directional communication between the VSCs and VSPs. All VSCs utilize the VMBus driver. .Sh SEE ALSO -.Xr hv_ata_pci_disengage 4 , .Xr hv_netvsc 4 , .Xr hv_storvsc 4 , .Xr hv_utils 4 diff --git a/share/man/man4/hv_vss.4 b/share/man/man4/hv_vss.4 new file mode 100644 index 00000000000..4db54e364d9 --- /dev/null +++ b/share/man/man4/hv_vss.4 @@ -0,0 +1,366 @@ +.\" Copyright (c) 2016 Microsoft Corp. +.\" 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 October 12, 2016 +.Dt HV_VSS 4 +.Os +.Sh NAME +.Nm hv_vss +.Nd Hyper-V Volume Shadow Copy Service API +.Sh SYNOPSIS +.In dev/hyperv/hv_snapshot.h +.Bd -literal +#define VSS_SUCCESS 0x00000000 +#define VSS_FAIL 0x00000001 + +enum hv_vss_op_t { + HV_VSS_NONE = 0, + HV_VSS_CHECK, + HV_VSS_FREEZE, + HV_VSS_THAW, + HV_VSS_COUNT +}; + +struct hv_vss_opt_msg { + uint32_t opt; /* operation */ + uint32_t status; /* 0 for success, 1 for error */ + uint64_t msgid; /* an ID used to identify the transaction */ + uint8_t reserved[48]; /* reserved values are all zeroes */ +}; +.Ed +.Sh DESCRIPTION +The freeze or thaw functionality of application is important to guarantee +the application consistent backup. On windows platform, VSS is defined to do +live backup. But for VM guest running on Hyper-V, the corresponding VSS is +not defined yet. For example, a running database server instance, it knows when the +applications' freeze/thaw should start or finish. But it is not aware of +the freeze/thaw notification from Hyper-V host. The +.Nm +is designed to notify application freeze/thaw request. +Thus, it plays a role of broker to forward the freeze/thaw command from Hyper-V host +to userland application if it registered VSS service on +.Fx +VM, and sends the result back to Hyper-V host. +.Pp +Generally, +.Xr hv_vss_daemon 8 +takes the responsiblity to freeze/thaw UFS file system, +and it is automatically launched after system boots. When Hyper-V host wants to +take a snapshot of the +.Fx +VM, it will first send VSS capability check to +.Fx +VM. The +.Nm +received the request and forward the request to userland application if it is +registered. Only after +.Nm +received the VSS_SUCCESS response from application, the +.Xr hv_vss_daemon 8 +will be informed to check whether file system freeze/thaw is supported. Any error +occurs during this period, +.Nm +will inform Hyper-V host that VSS is not supported. In addition, there is a default +timeout limit before sending response to Hyper-V host. +If the total response time from application and +.Xr hv_vss_daemon 8 +exceeds this value, timeout +will occurs and VSS unsupported is responsed to Hyper-V host. +.Pp +After Hyper-V host confirmed the +.Fx +VM supports VSS, it will send freeze request to VM, and +.Nm +will first forward it to application. After application finished freezing, it should +inform +.Nm +and file system level freezing will be triggered by +.Xr hv_vss_daemon 8 . After all freezing +on both application and +.Xr hv_vss_daemon 8 +were finished, the +.Nm +will inform Hyper-V host that freezing is done. Of course, there is a timeout limit as +same as VSS capability is set to make sure freezing on +.Fx +VM is not hang. If there is any error occurs or timeout happened, the freezing is failed +on Hyper-V side. +.Pp +Hyper-V host will send thaw request after taking the snapshot, typically, this period is +very short in order not to block the running application. +.Nm +firstly thaw the file system by notifying +.Xr hv_vss_daemon 8 , +then notifies user registered +application. There is also a timeout check before sending response to Hyper-V host. +.Pp +All the default timeout limit used in VSS capability check, freeze or thaw is the same. +It is 15 seconds currently. +.Sh NOTES +.Nm +only support UFS currently. If any of file system partition is non UFS, the VSS capability +check will fail. If application does not register VSS, +.Nm +only support backup for file system level consistent. The device should be closed before it +was opened again. If you want to simultaneously open "/dev/hv_appvss_dev" two or more times, +an error (-1) will be returned, and errno was set. +.Pp +If +.Xr hv_vss_daemon 8 +was killed after system boots, the VSS functionality will not work. +.Sh EXAMPLES +The following is a complete example which does nothing except for waiting 2 seconds when +receiving those notifications from +.Nm +.Bd -literal +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define UNDEF_FREEZE_THAW (0) +#define FREEZE (1) +#define THAW (2) +#define CHECK (3) + +#define VSS_LOG(priority, format, args...) do { \\ + if (is_debugging == 1) { \\ + if (is_daemon == 1) \\ + syslog(priority, format, ## args); \\ + else \\ + printf(format, ## args); \\ + } else { \\ + if (priority < LOG_DEBUG) { \\ + if (is_daemon == 1) \\ + syslog(priority, format, ## args); \\ + else \\ + printf(format, ## args); \\ + } \\ + } \\ + } while(0) + +#define CHECK_TIMEOUT 1 +#define CHECK_FAIL 2 +#define FREEZE_TIMEOUT 1 +#define FREEZE_FAIL 2 +#define THAW_TIMEOUT 1 +#define THAW_FAIL 2 + +static int is_daemon = 1; +static int is_debugging = 0; +static int simu_opt_waiting = 2; // seconds + +#define GENERIC_OPT(TIMEOUT, FAIL) \\ + do { \\ + sleep(simu_opt_waiting); \\ + if (opt == CHECK_TIMEOUT) { \\ + sleep(simu_opt_waiting * 10); \\ + VSS_LOG(LOG_INFO, "%s timeout simulation\\n", \\ + __func__); \\ + return (0); \\ + } else if (opt == CHECK_FAIL) { \\ + VSS_LOG(LOG_INFO, "%s failure simulation\\n", \\ + __func__); \\ + return (CHECK_FAIL); \\ + } else { \\ + VSS_LOG(LOG_INFO, "%s success simulation\\n", \\ + __func__); \\ + return (0); \\ + } \\ + } while (0) + +static int +check(int opt) +{ + GENERIC_OPT(CHECK_TIMEOUT, CHECK_FAIL); +} + +static int +freeze(int opt) +{ + GENERIC_OPT(FREEZE_TIMEOUT, FREEZE_FAIL); +} + +static int +thaw(int opt) +{ + GENERIC_OPT(THAW_TIMEOUT, THAW_FAIL); +} + +static void usage(const char* cmd) { + fprintf(stderr, + "%s -f <0|1|2>: simulate app freeze." + " 0: successful, 1: freeze timeout, 2: freeze failed\\n" + " -c <0|1|2>: simulate vss feature check" + " -t <0|1|2>: simulate app thaw." + " 0: successful, 1: freeze timeout, 2: freeze failed\\n" + " -d : enable debug mode\\n" + " -n : run this tool under non-daemon mode\\n", cmd); +} + +int +main(int argc, char* argv[]) { + int ch, freezesimuop = 0, thawsimuop = 0, checksimuop = 0, fd, r, error; + uint32_t op; + struct pollfd app_vss_fd[1]; + struct hv_vss_opt_msg userdata; + + while ((ch = getopt(argc, argv, "f:c:t:dnh")) != -1) { + switch (ch) { + case 'f': + /* Run as regular process for debugging purpose. */ + freezesimuop = (int)strtol(optarg, NULL, 10); + break; + case 't': + thawsimuop = (int)strtol(optarg, NULL, 10); + break; + case 'c': + checksimuop = (int)strtol(optarg, NULL, 10); + break; + case 'd': + is_debugging = 1; + break; + case 'n': + is_daemon = 0; + break; + case 'h': + default: + usage(argv[0]); + exit(0); + } + } + + openlog("APPVSS", 0, LOG_USER); + /* Become daemon first. */ + if (is_daemon == 1) + daemon(1, 0); + else + VSS_LOG(LOG_DEBUG, "Run as regular process.\\n"); + + VSS_LOG(LOG_INFO, "HV_VSS starting; pid is: %d\\n", getpid()); + + fd = open(VSS_DEV(APP_VSS_DEV_NAME), O_RDWR); + if (fd < 0) { + VSS_LOG(LOG_ERR, "Fail to open %s, error: %d %s\\n", + VSS_DEV(APP_VSS_DEV_NAME), errno, strerror(errno)); + exit(EXIT_FAILURE); + } + app_vss_fd[0].fd = fd; + app_vss_fd[0].events = POLLIN | POLLRDNORM; + + while (1) { + r = poll(app_vss_fd, 1, INFTIM); + + VSS_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\\n", + r, app_vss_fd[0].revents); + + if (r == 0 || (r < 0 && errno == EAGAIN) || + (r < 0 && errno == EINTR)) { + /* Nothing to read */ + continue; + } + + if (r < 0) { + /* + * For poll return failure other than EAGAIN, + * we want to exit. + */ + VSS_LOG(LOG_ERR, "Poll failed.\\n"); + perror("poll"); + exit(EIO); + } + + /* Read from character device */ + error = ioctl(fd, IOCHVVSSREAD, &userdata); + if (error < 0) { + VSS_LOG(LOG_ERR, "Read failed.\\n"); + perror("pread"); + exit(EIO); + } + + if (userdata.status != 0) { + VSS_LOG(LOG_ERR, "data read error\\n"); + continue; + } + + op = userdata.opt; + + switch (op) { + case HV_VSS_CHECK: + error = check(checksimuop); + break; + case HV_VSS_FREEZE: + error = freeze(freezesimuop); + break; + case HV_VSS_THAW: + error = thaw(thawsimuop); + break; + default: + VSS_LOG(LOG_ERR, "Illegal operation: %d\\n", op); + error = VSS_FAIL; + } + if (error) + userdata.status = VSS_FAIL; + else + userdata.status = VSS_SUCCESS; + error = ioctl(fd, IOCHVVSSWRITE, &userdata); + if (error != 0) { + VSS_LOG(LOG_ERR, "Fail to write to device\\n"); + exit(EXIT_FAILURE); + } else { + VSS_LOG(LOG_INFO, "Send response %d for %s to kernel\\n", + userdata.status, op == HV_VSS_FREEZE ? "Freeze" : + (op == HV_VSS_THAW ? "Thaw" : "Check")); + } + } + return 0; +} +.Sh SEE ALSO +.Xr hv_vss_daemon 8 , +.Xr hv_utils 4 +.Sh HISTORY +The daemon was introduced in October 2016 and developed by Microsoft Corp. +.Sh AUTHORS +.An -nosplit +.Fx +support for +.Nm +was first added by +.An Microsoft BSD Integration Services Team Aq Mt bsdic@microsoft.com . diff --git a/share/man/man4/rtwn_pci.4 b/share/man/man4/rtwn_pci.4 index 71fa1669233..f86a6968939 100644 --- a/share/man/man4/rtwn_pci.4 +++ b/share/man/man4/rtwn_pci.4 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\"/ -.Dd October 17, 2016 +.Dd November 12, 2016 .Dt RTWN_PCI 4 .Os .Sh NAME @@ -58,6 +58,3 @@ It operates in the 2GHz spectrum only. .Xr rtwnfw 4 , .Xr rtwn_usb 4 , .Xr pci 4 -.Sh CAVEATS -Most 802.11 capabilities were turned off; some more testing -is required to re-enable them. diff --git a/share/man/man4/smb.4 b/share/man/man4/smb.4 index 82202a48051..53e809da306 100644 --- a/share/man/man4/smb.4 +++ b/share/man/man4/smb.4 @@ -141,26 +141,25 @@ in .Em BlockWrite first sends the byte from .Fa cmd -to the device, followed by +to the device, then the byte from +.Fa wcount +followed by .Fa wcount bytes of data that are taken from the buffer pointed to by .Fa wbuf . The SMBus specification mandates that no more than 32 bytes of -data can be transferred in a single block read or write command, -but since -.Xr smbus 4 -is also used to access I2C devices, the limit has been increased -to 1024. +data can be transferred in a single block read or write command. This value can be read from the constant .Dv SMB_MAXBLOCKSIZE . .It Dv SMB_BREAD Ta .Em BlockRead first sends the byte from .Fa cmd -to the device, then reads -.Fa rcount -bytes of data that from the device. -This data is returned in the buffer pointed to by +to the device, then reads a count of data bytes that the device +is going to provide and then reads that many bytes. +The count is returned in +.Fa rcount. +The data is returned in the buffer pointed to by .Fa rbuf . .El .Pp diff --git a/share/man/man4/snd_uaudio.4 b/share/man/man4/snd_uaudio.4 index 5166f08f6d3..17780692a66 100644 --- a/share/man/man4/snd_uaudio.4 +++ b/share/man/man4/snd_uaudio.4 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 19, 2015 +.Dd November 12, 2016 .Dt SND_UAUDIO 4 .Os .Sh NAME @@ -73,7 +73,7 @@ for more information. .Xr usb 4 .Rs .%T "USB Audio Class Specifications" -.%U http://www.usb.org/developers/devclass_docs/ +.%U http://www.usb.org/developers/docs/devclass_docs/ .Re .Sh HISTORY The diff --git a/share/man/man9/usbdi.9 b/share/man/man9/usbdi.9 index 588c79e501b..640222b8067 100644 --- a/share/man/man9/usbdi.9 +++ b/share/man/man9/usbdi.9 @@ -24,7 +24,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd June 24, 2009 +.Dd November 14, 2016 .Dt USBDI 9 .Os .Sh NAME @@ -84,6 +84,33 @@ .In dev/usb/usb.h .In dev/usb/usbdi.h .In dev/usb/usbdi_util.h +.Ft "usb_error_t" +.Fo "usbd_transfer_setup" +.Fa "struct usb_device *udev" +.Fa "const uint8_t *ifaces" +.Fa "struct usb_xfer **pxfer" +.Fa "const struct usb_config *setup_start" +.Fa "uint16_t n_setup" +.Fa "void *priv_sc" +.Fa "struct mtx *priv_mtx" +.Fc +.Ft "void" +.Fo "usbd_transfer_unsetup" +.Fa "struct usb_xfer **pxfer" +.Fa "uint16_t n_setup" +.Fc +.Ft "void" +.Fo "usbd_transfer_start" +.Fa "struct usb_xfer *xfer" +.Fc +.Ft "void" +.Fo "usbd_transfer_stop" +.Fa "struct usb_xfer *xfer" +.Fc +.Ft "void" +.Fo "usbd_transfer_drain" +.Fa "struct usb_xfer *xfer" +.Fc .Sh DESCRIPTION The Universal Serial Bus (USB) driver programming interface provides USB peripheral drivers with a host controller independent API for @@ -91,53 +118,6 @@ controlling and communicating with USB peripherals. The .Nm usb module supports both USB Host and USB Device side mode. -. -.Sh USB KERNEL PROGRAMMING -Here is a list of commonly used functions: -.Pp -. -.Ft "usb_error_t" -.Fo "usbd_transfer_setup" -.Fa "udev" -.Fa "ifaces" -.Fa "pxfer" -.Fa "setup_start" -.Fa "n_setup" -.Fa "priv_sc" -.Fa "priv_mtx" -.Fc -. -.Pp -. -.Ft "void" -.Fo "usbd_transfer_unsetup" -.Fa "pxfer" -.Fa "n_setup" -.Fc -. -.Pp -. -.Ft "void" -.Fo "usbd_transfer_start" -.Fa "xfer" -.Fc -. -.Pp -. -.Ft "void" -.Fo "usbd_transfer_stop" -.Fa "xfer" -.Fc -. -.Pp -. -.Ft "void" -.Fo "usbd_transfer_drain" -.Fa "xfer" -.Fc -. -. -. .Sh USB TRANSFER MANAGEMENT FUNCTIONS The USB standard defines four types of USB transfers. . @@ -552,7 +532,7 @@ for the 8-bytes of SETUP header. These 8-bytes are not counted by the "xfer->max_data_length" variable. . -This flag can not be changed during operation. +This flag cannot be changed during operation. . . .It ext_buffer @@ -561,7 +541,7 @@ allocated. . Instead the USB client must supply a data buffer. . -This flag can not be changed during operation. +This flag cannot be changed during operation. . . .It manual_status @@ -579,7 +559,7 @@ This flag can be changed during operation. . .It no_pipe_ok Setting this flag causes the USB_ERR_NO_PIPE error to be ignored. -This flag can not be changed during operation. +This flag cannot be changed during operation. . . .It stall_pipe diff --git a/share/man/man9/vm_page_alloc.9 b/share/man/man9/vm_page_alloc.9 index 082574f4d15..aa3854b47ae 100644 --- a/share/man/man9/vm_page_alloc.9 +++ b/share/man/man9/vm_page_alloc.9 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 28, 2012 +.Dd November 16, 2016 .Dt VM_PAGE_ALLOC 9 .Os .Sh NAME @@ -52,8 +52,6 @@ The page returned is inserted into the object, unless .Dv VM_ALLOC_NOOBJ is specified in the .Fa req . -The page may exist in the vm object cache, in which case it will -be reactivated instead, moving from the cache into the object page list. .Pp .Fn vm_page_alloc will not sleep. @@ -89,7 +87,7 @@ than zero. .El .Pp The optional flags are: -.Bl -tag -width ".Dv VM_ALLOC_IFNOTCACHED" +.Bl -tag -width ".Dv VM_ALLOC_NOBUSY" .It Dv VM_ALLOC_NOBUSY The returned page will not be exclusive busy. .It Dv VM_ALLOC_NODUMP @@ -100,16 +98,6 @@ Do not associate the allocated page with a vm object. The .Fa object argument is ignored. -.It Dv VM_ALLOC_IFCACHED -Allocate the page only if it is cached. -Otherwise, return -.Dv NULL . -.It Dv VM_ALLOC_IFNOTCACHED -Only allocate the page if it is not cached in the -.Fa object . -If the page at the specified -.Fa pindex -is cached, NULL is returned instead. .It Dv VM_ALLOC_SBUSY The returned page will be shared busy. .It Dv VM_ALLOC_WIRED diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot index bab00b0a485..59565c15050 100644 --- a/share/misc/committers-src.dot +++ b/share/misc/committers-src.dot @@ -143,8 +143,10 @@ csjp [label="Christian S.J. Peron\ncsjp@FreeBSD.org\n2004/05/04"] das [label="David Schultz\ndas@FreeBSD.org\n2003/02/21"] davide [label="Davide Italiano\ndavide@FreeBSD.org\n2012/01/27"] dchagin [label="Dmitry Chagin\ndchagin@FreeBSD.org\n2009/02/28"] +def [label="Konrad Witaszczyk\ndef@FreeBSD.org\n2016/11/02"] delphij [label="Xin Li\ndelphij@FreeBSD.org\n2004/09/14"] des [label="Dag-Erling Smorgrav\ndes@FreeBSD.org\n1998/04/03"] +dexuan [label="Dexuan Cui\ndexuan@FreeBSD.org\n2016/10/24"] dfr [label="Doug Rabson\ndfr@FreeBSD.org\n????/??/??"] dg [label="David Greenman\ndg@FreeBSD.org\n1993/06/14"] dim [label="Dimitry Andric\ndim@FreeBSD.org\n2010/08/30"] @@ -683,6 +685,7 @@ philip -> kp phk -> jkoshy phk -> mux +pjd -> def pjd -> kib pjd -> lulf pjd -> oshogbo @@ -753,6 +756,8 @@ scottl -> sbruno scottl -> slm scottl -> yongari +sephe -> dexuan + sheldonh -> dwmalone sheldonh -> iedowse diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk index ae29f14aebe..79c37664849 100644 --- a/share/mk/bsd.cpu.mk +++ b/share/mk/bsd.cpu.mk @@ -155,8 +155,6 @@ _CPUCFLAGS = -march=${CPUTYPE} # sb1, xlp, xlr _CPUCFLAGS = -march=${CPUTYPE:S/^mips//} . endif -. elif ${MACHINE_CPUARCH} == "riscv" -_CPUCFLAGS = -mno-float -march="IMAFD" . elif ${MACHINE_ARCH} == "sparc64" . if ${CPUTYPE} == "v9" _CPUCFLAGS = -mcpu=v9 @@ -303,9 +301,22 @@ MACHINE_CPU = v9 ultrasparc ultrasparc3 .if ${MACHINE_CPUARCH} == "mips" CFLAGS += -G0 -.if ${MACHINE_ARCH:Mmips*hf} +. if ${MACHINE_ARCH:Mmips*el*} != "" +ACFLAGS += -EL +AFLAGS += -EL +CFLAGS += -EL +LDFLAGS += -EL +. else +ACFLAGS += -EB +AFLAGS += -EB +CFLAGS += -EB +LDFLAGS += -EB +. endif +. if ${MACHINE_ARCH:Mmips*hf} CFLAGS += -mhard-float -.endif +. else +CFLAGS += -msoft-float +. endif .endif ########## arm @@ -337,9 +348,11 @@ CFLAGS += -mcpu=8540 -Wa,-me500 -mspe=yes -mabi=spe -mfloat-gprs=double .endif .if ${MACHINE_CPUARCH} == "riscv" +.if ${TARGET_ARCH:Mriscv*sf} CFLAGS += -mno-float ACFLAGS += -mno-float .endif +.endif # NB: COPTFLAGS is handled in /usr/src/sys/conf/kern.pre.mk diff --git a/share/mk/bsd.dep.mk b/share/mk/bsd.dep.mk index c5d242f166e..acc66991619 100644 --- a/share/mk/bsd.dep.mk +++ b/share/mk/bsd.dep.mk @@ -77,14 +77,13 @@ _meta_filemon= 1 .endif # Skip reading .depend when not needed to speed up tree-walks and simple -# lookups. For install, only do this if no other targets are specified. +# lookups. See _SKIP_BUILD logic in bsd.init.mk for more details. # Also skip generating or including .depend.* files if in meta+filemon mode # since it will track dependencies itself. OBJS_DEPEND_GUESS is still used. -.if !empty(.MAKEFLAGS:M-V${_V_READ_DEPEND}) || make(obj) || make(clean*) || \ - ${.TARGETS:M*install*} == ${.TARGETS} || \ - make(analyze) || defined(_meta_filemon) || make(print-dir) +.if defined(_SKIP_BUILD) || defined(_meta_filemon) _SKIP_READ_DEPEND= 1 -.if ${MK_DIRDEPS_BUILD} == "no" || make(analyze) || make(print-dir) +.if ${MK_DIRDEPS_BUILD} == "no" || make(analyze) || make(print-dir) || \ + make(obj) || make(clean*) || make(destroy*) .MAKE.DEPENDFILE= /dev/null .endif .endif @@ -198,7 +197,7 @@ CFLAGS+= ${DEPEND_CFLAGS} .endif # !defined(_meta_filemon) .endif # defined(SRCS) -.if ${MK_DIRDEPS_BUILD} == "yes" && !make(analyze) && !make(print-dir) +.if ${MK_DIRDEPS_BUILD} == "yes" && ${.MAKE.DEPENDFILE} != "/dev/null" # Prevent meta.autodep.mk from tracking "local dependencies". .depend: .include diff --git a/share/mk/bsd.init.mk b/share/mk/bsd.init.mk index b7a45d9ac43..5e8951a6e60 100644 --- a/share/mk/bsd.init.mk +++ b/share/mk/bsd.init.mk @@ -15,19 +15,36 @@ ____: .endif .include .MAIN: all + +# Some targets need to know when something may build. This is used to +# optimize targets that are only needed when building something, such as +# (not) reading in depend files. For DIRDEPS_BUILD, it will only calculate +# the dependency graph at .MAKE.LEVEL==0, so nothing should be built there. +# Skip "build" logic if: +# - DIRDEPS_BUILD at MAKELEVEL 0 +# - make -V is used without an override +# - make install is used without other targets. This is to avoid breaking +# things like 'make all install' or 'make foo install'. +# - non-build targets are called +.if ${MK_DIRDEPS_BUILD} == "yes" && ${.MAKE.LEVEL:U1} == 0 && \ + ${BUILD_AT_LEVEL0:Uyes:tl} == "no" && !make(clean*) +_SKIP_BUILD= not building at level 0 +.elseif !empty(.MAKEFLAGS:M-V${_V_DO_BUILD}) || \ + ${.TARGETS:M*install*} == ${.TARGETS} || \ + make(clean*) || make(obj) || make(analyze) || make(print-dir) || \ + make(destroy*) +# Skip building, but don't show a warning. +_SKIP_BUILD= +.endif +.if ${MK_DIRDEPS_BUILD} == "yes" && ${.MAKE.LEVEL} > 0 && !empty(_SKIP_BUILD) +.warning ${_SKIP_BUILD} +.endif + beforebuild: .PHONY .NOTMAIN .if !defined(_SKIP_BUILD) all: beforebuild .WAIT .endif -.if ${.MAKE.LEVEL:U1} == 0 && ${BUILD_AT_LEVEL0:Uyes:tl} == "no" && !make(clean*) -# this tells lib.mk and prog.mk to not actually build anything -_SKIP_BUILD = not building at level 0 -.endif -.if ${.MAKE.LEVEL} > 0 && !empty(_SKIP_BUILD) -.warning ${_SKIP_BUILD} -.endif - .if ${MK_META_MODE} == "yes" .if !exists(/dev/filemon) && \ ${UPDATE_DEPENDFILE:Uyes:tl} != "no" && !defined(NO_FILEMON) && \ diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index 1fab97cf9e8..67a5630996b 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -304,7 +304,6 @@ all: .else .if defined(_LIBS) && !empty(_LIBS) all: ${_LIBS} -CLEANFILES+= ${_LIBS} .endif .if ${MK_MAN} != "no" && !defined(LIBRARIES_ONLY) @@ -312,6 +311,8 @@ all: all-man .endif .endif +CLEANFILES+= ${_LIBS} + _EXTRADEPEND: .if !defined(NO_EXTRADEPEND) && defined(SHLIB_NAME) .if defined(DPADD) && !empty(DPADD) diff --git a/share/mk/bsd.subdir.mk b/share/mk/bsd.subdir.mk index 9d1fed72073..e5c73ac8355 100644 --- a/share/mk/bsd.subdir.mk +++ b/share/mk/bsd.subdir.mk @@ -70,7 +70,10 @@ print-dir: .PHONY .endif .if !defined(NEED_SUBDIR) -.if ${.MAKE.LEVEL} == 0 && ${MK_DIRDEPS_BUILD} == "yes" && !empty(SUBDIR) && !(make(clean*) || make(destroy*)) +# .MAKE.DEPENDFILE==/dev/null is set by bsd.dep.mk to avoid reading +# Makefile.depend +.if ${.MAKE.LEVEL} == 0 && ${MK_DIRDEPS_BUILD} == "yes" && !empty(SUBDIR) && \ + ${.MAKE.DEPENDFILE} != "/dev/null" .include # ignore this _SUBDIR: diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk index e94977c43cf..7a4ed45a8a6 100644 --- a/share/mk/bsd.sys.mk +++ b/share/mk/bsd.sys.mk @@ -209,7 +209,7 @@ CXXFLAGS+= ${CXXFLAGS.${.IMPSRC:T}} .if defined(SRCTOP) # Prevent rebuilding during install to support read-only objdirs. -.if !make(all) && make(install) && empty(.MAKE.MODE:Mmeta) +.if ${.TARGETS:M*install*} == ${.TARGETS} && empty(.MAKE.MODE:Mmeta) CFLAGS+= ERROR-tried-to-rebuild-during-make-install .endif .endif diff --git a/share/mk/local.meta.sys.mk b/share/mk/local.meta.sys.mk index 49f625ccefa..3a4e8f1352b 100644 --- a/share/mk/local.meta.sys.mk +++ b/share/mk/local.meta.sys.mk @@ -48,7 +48,7 @@ TARGET_ARCHES_arm64?= aarch64 TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32 mipsn32el TARGET_ARCHES_powerpc?= powerpc powerpc64 powerpcspe TARGET_ARCHES_pc98?= i386 -TARGET_ARCHES_riscv?= riscv64 +TARGET_ARCHES_riscv?= riscv64 riscv64sf # some corner cases BOOT_MACHINE_DIR.amd64 = boot/i386 diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index a0fd48b2d7f..51b79f3d609 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -236,16 +236,16 @@ __DEFAULT_YES_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX __DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC .endif # In-tree binutils/gcc are older versions without modern architecture support. -.if ${__T} == "aarch64" || ${__T} == "riscv64" +.if ${__T} == "aarch64" || ${__T:Mriscv*} != "" BROKEN_OPTIONS+=BINUTILS BINUTILS_BOOTSTRAP GCC GCC_BOOTSTRAP GDB .endif -.if ${__T} == "riscv64" +.if ${__T:Mriscv*} != "" BROKEN_OPTIONS+=PROFILE # "sorry, unimplemented: profiler support for RISC-V" BROKEN_OPTIONS+=TESTS # "undefined reference to `_Unwind_Resume'" BROKEN_OPTIONS+=CXX # "libcxxrt.so: undefined reference to `_Unwind_Resume_or_Rethrow'" .endif .if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "i386" || \ - ${__T} == "riscv64" + ${__T:Mriscv*} != "" __DEFAULT_YES_OPTIONS+=LLVM_LIBUNWIND .else __DEFAULT_NO_OPTIONS+=LLVM_LIBUNWIND diff --git a/share/mk/sys.mk b/share/mk/sys.mk index 2c374334201..04c342c134f 100644 --- a/share/mk/sys.mk +++ b/share/mk/sys.mk @@ -13,7 +13,7 @@ unix ?= We run FreeBSD, not UNIX. # and/or endian. This is called MACHINE_CPU in NetBSD, but that's used # for something different in FreeBSD. # -MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64/riscv/} +MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64(sf)?/riscv/} .endif diff --git a/share/zoneinfo/Makefile b/share/zoneinfo/Makefile index 2269b1f40bc..701a02a579f 100644 --- a/share/zoneinfo/Makefile +++ b/share/zoneinfo/Makefile @@ -67,6 +67,10 @@ TZBUILDSUBDIRS= \ Pacific \ SystemV +.if defined(OLDTIMEZONES) +TZBUILDSUBDIRS+= US Mexico Chile Canada Brazil +.endif + .if !defined(_SKIP_BUILD) all: zoneinfo .endif diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 024c1b34a6c..aa98fbd381e 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -761,11 +761,11 @@ trap_fatal(frame, eva) #endif if (type == T_PAGEFLT) { printf("fault virtual address = 0x%lx\n", eva); - printf("fault code = %s %s %s%s, %s\n", + printf("fault code = %s %s %s, %s\n", code & PGEX_U ? "user" : "supervisor", code & PGEX_W ? "write" : "read", code & PGEX_I ? "instruction" : "data", - code & PGEX_RSV ? " rsv" : "", + code & PGEX_RSV ? "reserved bits in PTE" : code & PGEX_P ? "protection violation" : "page not present"); } printf("instruction pointer = 0x%lx:0x%lx\n", diff --git a/sys/arm/allwinner/a10/a10_intc.c b/sys/arm/allwinner/a10/a10_intc.c index fd6c4073fb3..996d28a950d 100644 --- a/sys/arm/allwinner/a10/a10_intc.c +++ b/sys/arm/allwinner/a10/a10_intc.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c index 1ea55357c14..85c26504058 100644 --- a/sys/arm/allwinner/a10_gpio.c +++ b/sys/arm/allwinner/a10_gpio.c @@ -44,11 +44,10 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include #include #include +#include #include #include diff --git a/sys/arm/allwinner/a10_hdmi.c b/sys/arm/allwinner/a10_hdmi.c index 1b7cbd2145a..96613719e2e 100644 --- a/sys/arm/allwinner/a10_hdmi.c +++ b/sys/arm/allwinner/a10_hdmi.c @@ -581,7 +581,7 @@ a10hdmi_get_tcon_config(struct a10hdmi_softc *sc, int *div, int *dbl) /* Detect LCD CH1 special clock using a 1X or 2X source */ /* XXX */ pname = clk_get_name(clk_lcd_parent); - if (strcmp(pname, "pll3-1x") == 0 || strcmp(pname, "pll7-1x") == 0) + if (strcmp(pname, "pll3") == 0 || strcmp(pname, "pll7") == 0) *dbl = 0; else *dbl = 1; diff --git a/sys/arm/allwinner/a10_mmc.c b/sys/arm/allwinner/a10_mmc.c index a5eecb80de1..3c94bba9f12 100644 --- a/sys/arm/allwinner/a10_mmc.c +++ b/sys/arm/allwinner/a10_mmc.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #define A10_MMC_DMA_SEGS ((MAXPHYS / PAGE_SIZE) + 1) #define A10_MMC_DMA_MAX_SIZE 0x2000 #define A10_MMC_DMA_FTRGLEVEL 0x20070008 +#define A10_MMC_RESET_RETRY 1000 #define CARD_ID_FREQUENCY 400000 @@ -229,7 +230,7 @@ a10_mmc_attach(device_t dev) bus_width = 4; sc->a10_host.f_min = 400000; - sc->a10_host.f_max = 50000000; + sc->a10_host.f_max = 52000000; sc->a10_host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; sc->a10_host.mode = mode_sd; sc->a10_host.caps = MMC_CAP_HSPEED; @@ -449,11 +450,27 @@ a10_mmc_req_done(struct a10_mmc_softc *sc) { struct mmc_command *cmd; struct mmc_request *req; + uint32_t val, mask; + int retry; cmd = sc->a10_req->cmd; if (cmd->error != MMC_ERR_NONE) { - /* Reset the controller. */ - a10_mmc_reset(sc); + /* Reset the FIFO and DMA engines. */ + mask = A10_MMC_CTRL_FIFO_RST | A10_MMC_CTRL_DMA_RST; + val = A10_MMC_READ_4(sc, A10_MMC_GCTL); + A10_MMC_WRITE_4(sc, A10_MMC_GCTL, val | mask); + + retry = A10_MMC_RESET_RETRY; + while (--retry > 0) { + val = A10_MMC_READ_4(sc, A10_MMC_GCTL); + if ((val & mask) == 0) + break; + DELAY(10); + } + if (retry == 0) + device_printf(sc->a10_dev, + "timeout resetting DMA/FIFO\n"); + a10_mmc_update_clock(sc, 1); } req = sc->a10_req; diff --git a/sys/arm/allwinner/a10_sramc.c b/sys/arm/allwinner/a10_sramc.c index 22ba1f7c4ad..ea9654518e5 100644 --- a/sys/arm/allwinner/a10_sramc.c +++ b/sys/arm/allwinner/a10_sramc.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/allwinner/a20/a20_cpu_cfg.c b/sys/arm/allwinner/a20/a20_cpu_cfg.c index a0bdb5a0b46..3fe53349b4d 100644 --- a/sys/arm/allwinner/a20/a20_cpu_cfg.c +++ b/sys/arm/allwinner/a20/a20_cpu_cfg.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/allwinner/aw_ccu.c b/sys/arm/allwinner/aw_ccu.c index 52d9cdacbfe..fca85b85bd5 100644 --- a/sys/arm/allwinner/aw_ccu.c +++ b/sys/arm/allwinner/aw_ccu.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -195,7 +194,7 @@ aw_ccu_search_compatible(void) root = OF_finddevice("/"); for (compat = compat_data; compat->ocd_str != NULL; compat++) - if (fdt_is_compatible(root, compat->ocd_str)) + if (ofw_bus_node_is_compatible(root, compat->ocd_str)) break; return (compat); diff --git a/sys/arm/allwinner/aw_cir.c b/sys/arm/allwinner/aw_cir.c index 926109a4d12..2c6c275b1fb 100644 --- a/sys/arm/allwinner/aw_cir.c +++ b/sys/arm/allwinner/aw_cir.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/allwinner/aw_machdep.c b/sys/arm/allwinner/aw_machdep.c index 73b1e58f949..d9effb8eec9 100644 --- a/sys/arm/allwinner/aw_machdep.c +++ b/sys/arm/allwinner/aw_machdep.c @@ -48,8 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include #include diff --git a/sys/arm/allwinner/aw_nmi.c b/sys/arm/allwinner/aw_nmi.c index 67be72d6b05..86c122f5300 100644 --- a/sys/arm/allwinner/aw_nmi.c +++ b/sys/arm/allwinner/aw_nmi.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/allwinner/aw_thermal.c b/sys/arm/allwinner/aw_thermal.c index 12146afd968..5143cda95fb 100644 --- a/sys/arm/allwinner/aw_thermal.c +++ b/sys/arm/allwinner/aw_thermal.c @@ -109,10 +109,13 @@ __FBSDID("$FreeBSD$"); #define H3_ADC_ACQUIRE_TIME 0x3f #define H3_FILTER 0x6 #define H3_INTC 0x191000 -#define H3_TEMP_BASE 1794000 +#define H3_TEMP_BASE 217 #define H3_TEMP_MUL 1000 -#define H3_TEMP_DIV -8253 +#define H3_TEMP_DIV 8253 +#define H3_TEMP_MINUS 1794000 #define H3_CLK_RATE 4000000 +#define H3_INIT_ALARM 90 /* degC */ +#define H3_INIT_SHUT 105 /* degC */ #define TEMP_C_TO_K 273 #define SENSOR_ENABLE_ALL (SENSOR0_EN|SENSOR1_EN|SENSOR2_EN) @@ -131,6 +134,8 @@ TUNABLE_INT("hw.aw_thermal.throttle_enable", &aw_thermal_throttle_enable); struct aw_thermal_sensor { const char *name; const char *desc; + int init_alarm; + int init_shut; }; struct aw_thermal_config { @@ -142,6 +147,7 @@ struct aw_thermal_config { uint32_t filter; uint32_t intc; int (*to_temp)(uint32_t); + uint32_t (*to_reg)(int); int temp_base; int temp_mul; int temp_div; @@ -177,9 +183,7 @@ static const struct aw_thermal_config a83t_config = { .filter = A83T_FILTER, .intc = A83T_INTC, .to_temp = a83t_to_temp, - .calib0 = 1, .calib0_mask = 0xffffffff, - .calib1 = 1, .calib1_mask = 0xffffffff, }; @@ -215,7 +219,13 @@ static const struct aw_thermal_config a64_config = { static int h3_to_temp(uint32_t val) { - return (((int)(val * H3_TEMP_MUL) - H3_TEMP_BASE) / H3_TEMP_DIV); + return (H3_TEMP_BASE - ((val * H3_TEMP_MUL) / H3_TEMP_DIV)); +} + +static uint32_t +h3_to_reg(int val) +{ + return ((H3_TEMP_MINUS - (val * H3_TEMP_DIV)) / H3_TEMP_MUL); } static const struct aw_thermal_config h3_config = { @@ -224,6 +234,8 @@ static const struct aw_thermal_config h3_config = { [0] = { .name = "cpu", .desc = "CPU temperature", + .init_alarm = H3_INIT_ALARM, + .init_shut = H3_INIT_SHUT, }, }, .clk_rate = H3_CLK_RATE, @@ -231,7 +243,7 @@ static const struct aw_thermal_config h3_config = { .filter = H3_FILTER, .intc = H3_INTC, .to_temp = h3_to_temp, - .calib0 = 1, + .to_reg = h3_to_reg, .calib0_mask = 0xfff, }; @@ -272,7 +284,7 @@ aw_thermal_init(struct aw_thermal_softc *sc) uint32_t calib0, calib1; int error; - if (sc->conf->calib0 != 0 || sc->conf->calib1 != 0) { + if (sc->conf->calib0_mask != 0 || sc->conf->calib1_mask != 0) { /* Read calibration settings from SRAM */ error = aw_sid_read_tscalib(&calib0, &calib1); if (error != 0) @@ -282,9 +294,9 @@ aw_thermal_init(struct aw_thermal_softc *sc) calib1 &= sc->conf->calib1_mask; /* Write calibration settings to thermal controller */ - if (sc->conf->calib0 != 0 && calib0 != 0) + if (calib0 != 0) WR4(sc, THS_CALIB0, calib0); - if (sc->conf->calib1 != 0 && calib1 != 0) + if (calib1 != 0) WR4(sc, THS_CALIB1, calib1); } @@ -313,7 +325,7 @@ aw_thermal_gettemp(struct aw_thermal_softc *sc, int sensor) val = RD4(sc, THS_DATA0 + (sensor * 4)); - return (sc->conf->to_temp(val) + TEMP_C_TO_K); + return (sc->conf->to_temp(val)); } static int @@ -324,7 +336,18 @@ aw_thermal_getshut(struct aw_thermal_softc *sc, int sensor) val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4)); val = (val >> SHUT_T_HOT_SHIFT) & SHUT_T_HOT_MASK; - return (sc->conf->to_temp(val) + TEMP_C_TO_K); + return (sc->conf->to_temp(val)); +} + +static void +aw_thermal_setshut(struct aw_thermal_softc *sc, int sensor, int temp) +{ + uint32_t val; + + val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4)); + val &= ~(SHUT_T_HOT_MASK << SHUT_T_HOT_SHIFT); + val |= (sc->conf->to_reg(temp) << SHUT_T_HOT_SHIFT); + WR4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4), val); } static int @@ -335,7 +358,7 @@ aw_thermal_gethyst(struct aw_thermal_softc *sc, int sensor) val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4)); val = (val >> ALARM_T_HYST_SHIFT) & ALARM_T_HYST_MASK; - return (sc->conf->to_temp(val) + TEMP_C_TO_K); + return (sc->conf->to_temp(val)); } static int @@ -346,7 +369,18 @@ aw_thermal_getalarm(struct aw_thermal_softc *sc, int sensor) val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4)); val = (val >> ALARM_T_HOT_SHIFT) & ALARM_T_HOT_MASK; - return (sc->conf->to_temp(val) + TEMP_C_TO_K); + return (sc->conf->to_temp(val)); +} + +static void +aw_thermal_setalarm(struct aw_thermal_softc *sc, int sensor, int temp) +{ + uint32_t val; + + val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4)); + val &= ~(ALARM_T_HOT_MASK << ALARM_T_HOT_SHIFT); + val |= (sc->conf->to_reg(temp) << ALARM_T_HOT_SHIFT); + WR4(sc, THS_ALARM0_CTRL + (sensor * 4), val); } static int @@ -358,7 +392,7 @@ aw_thermal_sysctl(SYSCTL_HANDLER_ARGS) sc = arg1; sensor = arg2; - val = aw_thermal_gettemp(sc, sensor); + val = aw_thermal_gettemp(sc, sensor) + TEMP_C_TO_K; return sysctl_handle_opaque(oidp, &val, sizeof(val), req); } @@ -514,6 +548,15 @@ aw_thermal_attach(device_t dev) goto fail; } + for (i = 0; i < sc->conf->nsensors; i++) { + if (sc->conf->sensors[i].init_alarm > 0) + aw_thermal_setalarm(sc, i, + sc->conf->sensors[i].init_alarm); + if (sc->conf->sensors[i].init_shut > 0) + aw_thermal_setshut(sc, i, + sc->conf->sensors[i].init_shut); + } + if (aw_thermal_init(sc) != 0) goto fail; @@ -529,9 +572,9 @@ aw_thermal_attach(device_t dev) for (i = 0; i < sc->conf->nsensors; i++) { device_printf(dev, "#%d: alarm %dC hyst %dC shut %dC\n", i, - aw_thermal_getalarm(sc, i) - TEMP_C_TO_K, - aw_thermal_gethyst(sc, i) - TEMP_C_TO_K, - aw_thermal_getshut(sc, i) - TEMP_C_TO_K); + aw_thermal_getalarm(sc, i), + aw_thermal_gethyst(sc, i), + aw_thermal_getshut(sc, i)); } sc->cf_pre_tag = EVENTHANDLER_REGISTER(cpufreq_pre_change, diff --git a/sys/arm/allwinner/aw_ts.c b/sys/arm/allwinner/aw_ts.c index e010ac469b0..2963fb84ce6 100644 --- a/sys/arm/allwinner/aw_ts.c +++ b/sys/arm/allwinner/aw_ts.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/allwinner/aw_wdog.c b/sys/arm/allwinner/aw_wdog.c index 4dcefd432b6..ca1ac0d98a7 100644 --- a/sys/arm/allwinner/aw_wdog.c +++ b/sys/arm/allwinner/aw_wdog.c @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/allwinner/clk/aw_gate.c b/sys/arm/allwinner/clk/aw_gate.c index f26b7c2d1b9..078a5e8031f 100644 --- a/sys/arm/allwinner/clk/aw_gate.c +++ b/sys/arm/allwinner/clk/aw_gate.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include diff --git a/sys/arm/allwinner/clk/aw_mmcclk.c b/sys/arm/allwinner/clk/aw_mmcclk.c index 52ed231a952..44377a8ced7 100644 --- a/sys/arm/allwinner/clk/aw_mmcclk.c +++ b/sys/arm/allwinner/clk/aw_mmcclk.c @@ -185,7 +185,7 @@ aw_mmcclk_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, ophase = 0; phase = 5; n = 2; - } else if (*fout <= 50000000) { + } else if (*fout <= 52000000) { parent_idx = CLK_SRC_SEL_PLL6; ophase = 3; phase = 5; diff --git a/sys/arm/allwinner/clk/aw_pll.c b/sys/arm/allwinner/clk/aw_pll.c index ab12dfa94de..6d8226399c5 100644 --- a/sys/arm/allwinner/clk/aw_pll.c +++ b/sys/arm/allwinner/clk/aw_pll.c @@ -180,9 +180,6 @@ __FBSDID("$FreeBSD$"); #define H3_PLL2_PRE_DIV (0x1f << 0) #define H3_PLL2_PRE_DIV_SHIFT 0 -#define CLKID_A10_PLL3_1X 0 -#define CLKID_A10_PLL3_2X 1 - #define CLKID_A10_PLL5_DDR 0 #define CLKID_A10_PLL5_OTHER 1 @@ -476,9 +473,6 @@ a10_pll3_recalc(struct aw_pll_sc *sc, uint64_t *freq) *freq = 297000000; } - if (sc->id == CLKID_A10_PLL3_2X) - *freq *= 2; - return (0); } @@ -489,14 +483,10 @@ a10_pll3_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout, uint32_t val, m, mode, func; m = *fout / A10_PLL3_REF_FREQ; - if (sc->id == CLKID_A10_PLL3_2X) - m /= 2; mode = A10_PLL3_MODE_SEL_INT; func = 0; *fout = m * A10_PLL3_REF_FREQ; - if (sc->id == CLKID_A10_PLL3_2X) - *fout *= 2; DEVICE_LOCK(sc); PLL_READ(sc, &val); diff --git a/sys/arm/allwinner/if_emac.c b/sys/arm/allwinner/if_emac.c index 097e4911037..a500f7b64e7 100644 --- a/sys/arm/allwinner/if_emac.c +++ b/sys/arm/allwinner/if_emac.c @@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/allwinner/timer.c b/sys/arm/allwinner/timer.c index 2b4ec843d77..fec5f9a1eb3 100644 --- a/sys/arm/allwinner/timer.c +++ b/sys/arm/allwinner/timer.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/altera/socfpga/socfpga_common.c b/sys/arm/altera/socfpga/socfpga_common.c index 9944b90e8b5..12a2cc5c471 100644 --- a/sys/arm/altera/socfpga/socfpga_common.c +++ b/sys/arm/altera/socfpga/socfpga_common.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -47,7 +46,7 @@ __FBSDID("$FreeBSD$"); void cpu_reset(void) { - uint32_t addr, paddr; + uint32_t paddr; bus_addr_t vaddr; phandle_t node; @@ -58,9 +57,8 @@ cpu_reset(void) if (node == -1) goto end; - if ((OF_getprop(node, "reg", &paddr, sizeof(paddr))) > 0) { - addr = fdt32_to_cpu(paddr); - if (bus_space_map(fdtbus_bs_tag, addr, 0x8, 0, &vaddr) == 0) { + if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) { + if (bus_space_map(fdtbus_bs_tag, paddr, 0x8, 0, &vaddr) == 0) { bus_space_write_4(fdtbus_bs_tag, vaddr, RSTMGR_CTRL, CTRL_SWWARMRSTREQ); } @@ -69,24 +67,3 @@ cpu_reset(void) end: while (1); } - -#ifndef INTRNG -static int -fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, - int *pol) -{ - - if (!fdt_is_compatible(node, "arm,gic")) - return (ENXIO); - - *interrupt = fdt32_to_cpu(intr[0]); - *trig = INTR_TRIGGER_CONFORM; - *pol = INTR_POLARITY_CONFORM; - return (0); -} - -fdt_pic_decode_t fdt_pic_table[] = { - &fdt_pic_decode_ic, - NULL -}; -#endif diff --git a/sys/arm/altera/socfpga/socfpga_gpio.c b/sys/arm/altera/socfpga/socfpga_gpio.c index 0e71d18cc48..2c064147414 100644 --- a/sys/arm/altera/socfpga/socfpga_gpio.c +++ b/sys/arm/altera/socfpga/socfpga_gpio.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/altera/socfpga/socfpga_manager.c b/sys/arm/altera/socfpga/socfpga_manager.c index 3b63f79bbce..33e4c74e494 100644 --- a/sys/arm/altera/socfpga/socfpga_manager.c +++ b/sys/arm/altera/socfpga/socfpga_manager.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/altera/socfpga/socfpga_rstmgr.c b/sys/arm/altera/socfpga/socfpga_rstmgr.c index 49db05ef4a1..d5f773f5bfe 100644 --- a/sys/arm/altera/socfpga/socfpga_rstmgr.c +++ b/sys/arm/altera/socfpga/socfpga_rstmgr.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -84,7 +83,7 @@ enum { static int l3remap(struct rstmgr_softc *sc, int remap, int enable) { - uint32_t addr, paddr; + uint32_t paddr; bus_addr_t vaddr; phandle_t node; int reg; @@ -106,9 +105,8 @@ l3remap(struct rstmgr_softc *sc, int remap, int enable) return (1); } - if ((OF_getprop(node, "reg", &paddr, sizeof(paddr))) > 0) { - addr = fdt32_to_cpu(paddr); - if (bus_space_map(fdtbus_bs_tag, addr, 0x4, 0, &vaddr) == 0) { + if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) { + if (bus_space_map(fdtbus_bs_tag, paddr, 0x4, 0, &vaddr) == 0) { bus_space_write_4(fdtbus_bs_tag, vaddr, L3REGS_REMAP, reg); return (0); diff --git a/sys/arm/amlogic/aml8726/aml8726_ccm.c b/sys/arm/amlogic/aml8726/aml8726_ccm.c index fb2c9a56f60..1c804c3ecda 100644 --- a/sys/arm/amlogic/aml8726/aml8726_ccm.c +++ b/sys/arm/amlogic/aml8726/aml8726_ccm.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_fb.c b/sys/arm/amlogic/aml8726/aml8726_fb.c index 94d39065afc..f2fc36de5ca 100644 --- a/sys/arm/amlogic/aml8726/aml8726_fb.c +++ b/sys/arm/amlogic/aml8726/aml8726_fb.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_gpio.c b/sys/arm/amlogic/aml8726/aml8726_gpio.c index afc6f5b7ce0..df26d91ee49 100644 --- a/sys/arm/amlogic/aml8726/aml8726_gpio.c +++ b/sys/arm/amlogic/aml8726/aml8726_gpio.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_i2c.c b/sys/arm/amlogic/aml8726/aml8726_i2c.c index c47bb6eec80..7fd8d71cea4 100644 --- a/sys/arm/amlogic/aml8726/aml8726_i2c.c +++ b/sys/arm/amlogic/aml8726/aml8726_i2c.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_mmc.c b/sys/arm/amlogic/aml8726/aml8726_mmc.c index 3cc074442f6..b14dab00589 100644 --- a/sys/arm/amlogic/aml8726/aml8726_mmc.c +++ b/sys/arm/amlogic/aml8726/aml8726_mmc.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_pic.c b/sys/arm/amlogic/aml8726/aml8726_pic.c index 70257f747cd..fd296ea63ca 100644 --- a/sys/arm/amlogic/aml8726/aml8726_pic.c +++ b/sys/arm/amlogic/aml8726/aml8726_pic.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_pinctrl.c b/sys/arm/amlogic/aml8726/aml8726_pinctrl.c index a71c25ae82f..5465b1cbe04 100644 --- a/sys/arm/amlogic/aml8726/aml8726_pinctrl.c +++ b/sys/arm/amlogic/aml8726/aml8726_pinctrl.c @@ -45,10 +45,9 @@ __FBSDID("$FreeBSD$"); #include -#include -#include #include #include +#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_rng.c b/sys/arm/amlogic/aml8726/aml8726_rng.c index e3397aa117a..9c38e3c8c06 100644 --- a/sys/arm/amlogic/aml8726/aml8726_rng.c +++ b/sys/arm/amlogic/aml8726/aml8726_rng.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_rtc.c b/sys/arm/amlogic/aml8726/aml8726_rtc.c index 5af51ce4d34..6ed8d7b7752 100644 --- a/sys/arm/amlogic/aml8726/aml8726_rtc.c +++ b/sys/arm/amlogic/aml8726/aml8726_rtc.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c index fc225352ed5..563eb573801 100644 --- a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c +++ b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_timer.c b/sys/arm/amlogic/aml8726/aml8726_timer.c index 60617035ab0..2fa4db8f398 100644 --- a/sys/arm/amlogic/aml8726/aml8726_timer.c +++ b/sys/arm/amlogic/aml8726/aml8726_timer.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c b/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c index 3a108e46154..3c6b796ead3 100644 --- a/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c +++ b/sys/arm/amlogic/aml8726/aml8726_usb_phy-m6.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/aml8726_wdt.c b/sys/arm/amlogic/aml8726/aml8726_wdt.c index cd78c9321bf..46bafccab95 100644 --- a/sys/arm/amlogic/aml8726/aml8726_wdt.c +++ b/sys/arm/amlogic/aml8726/aml8726_wdt.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c index 5d21fb05569..162e2eb2a9a 100644 --- a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c +++ b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/annapurna/alpine/alpine_machdep.c b/sys/arm/annapurna/alpine/alpine_machdep.c index 3d35834f1ca..7f87c7d6898 100644 --- a/sys/arm/annapurna/alpine/alpine_machdep.c +++ b/sys/arm/annapurna/alpine/alpine_machdep.c @@ -45,8 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include "opt_ddb.h" #include "opt_platform.h" diff --git a/sys/arm/annapurna/alpine/alpine_machdep_mp.c b/sys/arm/annapurna/alpine/alpine_machdep_mp.c index e48a1a3c577..4ef2db1ba0f 100644 --- a/sys/arm/annapurna/alpine/alpine_machdep_mp.c +++ b/sys/arm/annapurna/alpine/alpine_machdep_mp.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -81,7 +82,7 @@ static boolean_t alpine_validate_cpu(u_int, phandle_t, u_int, pcell_t *); static boolean_t alpine_validate_cpu(u_int id, phandle_t child, u_int addr_cell, pcell_t *reg) { - return fdt_is_compatible(child, "arm,cortex-a15"); + return ofw_bus_node_is_compatible(child, "arm,cortex-a15"); } static int diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index d91eee14ee4..e42a699986c 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #endif #ifdef FDT -#include #include #include #include diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c index 91ccf31635f..ff97f5cde88 100644 --- a/sys/arm/arm/gic.c +++ b/sys/arm/arm/gic.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -312,7 +311,7 @@ gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt, if (self == 0) { for (ocd = compat_data; ocd->ocd_str != NULL; ocd++) { - if (fdt_is_compatible(iparent, ocd->ocd_str)) { + if (ofw_bus_node_is_compatible(iparent, ocd->ocd_str)) { self = iparent; break; } diff --git a/sys/arm/arm/gic_fdt.c b/sys/arm/arm/gic_fdt.c index 1ababce6e0f..bd361c928c7 100644 --- a/sys/arm/arm/gic_fdt.c +++ b/sys/arm/arm/gic_fdt.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include #include diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 2dc71718e06..25a9fcaebe1 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #endif #ifdef CPU_MV_PJ4B #include -#include #endif extern struct pcpu __pcpu[]; diff --git a/sys/arm/arm/mpcore_timer.c b/sys/arm/arm/mpcore_timer.c index 03f8e4bad6a..e68a5e921ba 100644 --- a/sys/arm/arm/mpcore_timer.c +++ b/sys/arm/arm/mpcore_timer.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/arm/pl190.c b/sys/arm/arm/pl190.c index 8cd744e6c99..9817fa5ac17 100644 --- a/sys/arm/arm/pl190.c +++ b/sys/arm/arm/pl190.c @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/arm/pl310.c b/sys/arm/arm/pl310.c index c269b47a8be..18adabbd97c 100644 --- a/sys/arm/arm/pl310.c +++ b/sys/arm/arm/pl310.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index 5ac2fa8fd41..805a09d5f13 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -2739,31 +2739,25 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0, /* * Is given page managed? */ -static __inline boolean_t +static __inline bool is_managed(vm_paddr_t pa) { - vm_offset_t pgnum; vm_page_t m; - pgnum = atop(pa); - if (pgnum >= first_page) { - m = PHYS_TO_VM_PAGE(pa); - if (m == NULL) - return (FALSE); - if ((m->oflags & VPO_UNMANAGED) == 0) - return (TRUE); - } - return (FALSE); + m = PHYS_TO_VM_PAGE(pa); + if (m == NULL) + return (false); + return ((m->oflags & VPO_UNMANAGED) == 0); } -static __inline boolean_t +static __inline bool pte1_is_managed(pt1_entry_t pte1) { return (is_managed(pte1_pa(pte1))); } -static __inline boolean_t +static __inline bool pte2_is_managed(pt2_entry_t pte2) { @@ -6103,7 +6097,7 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa) pt1_entry_t *pte1p, pte1; pt2_entry_t *pte2p, pte2; vm_paddr_t pa; - boolean_t managed; + bool managed; int val; PMAP_LOCK(pmap); @@ -6130,7 +6124,7 @@ retry: if (pte2 & PTE2_A) val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER; } else { - managed = FALSE; + managed = false; val = 0; } if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) != diff --git a/sys/arm/arm/pmu.c b/sys/arm/arm/pmu.c index c98d6c98874..ad785ca960e 100644 --- a/sys/arm/arm/pmu.c +++ b/sys/arm/arm/pmu.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/at91/at91_aic.c b/sys/arm/at91/at91_aic.c index 92d6eada203..a6756da1dfa 100644 --- a/sys/arm/at91/at91_aic.c +++ b/sys/arm/at91/at91_aic.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_cfata.c b/sys/arm/at91/at91_cfata.c index 890029c13e3..8c6049d5b01 100644 --- a/sys/arm/at91/at91_cfata.c +++ b/sys/arm/at91/at91_cfata.c @@ -114,7 +114,7 @@ at91_cfata_detach(device_t dev) static struct resource * ata_at91_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct at91_cfata_softc *sc = device_get_softc(dev); diff --git a/sys/arm/at91/at91_common.c b/sys/arm/at91/at91_common.c index 696161f3400..8ef16fe7bc9 100644 --- a/sys/arm/at91/at91_common.c +++ b/sys/arm/at91/at91_common.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include @@ -56,7 +57,7 @@ fdt_aic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, { int offset; - if (fdt_is_compatible(node, "atmel,at91rm9200-aic")) + if (ofw_bus_node_is_compatible(node, "atmel,at91rm9200-aic")) offset = 0; else return (ENXIO); diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c index 2049fc74f93..477ce9dcc3c 100644 --- a/sys/arm/at91/at91_mci.c +++ b/sys/arm/at91/at91_mci.c @@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_ohci_fdt.c b/sys/arm/at91/at91_ohci_fdt.c index 51d9509fedc..091cd98305f 100644 --- a/sys/arm/at91/at91_ohci_fdt.c +++ b/sys/arm/at91/at91_ohci_fdt.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/sys/arm/at91/at91_pinctrl.c b/sys/arm/at91/at91_pinctrl.c index 7ca379be930..f2c3824f2d5 100644 --- a/sys/arm/at91/at91_pinctrl.c +++ b/sys/arm/at91/at91_pinctrl.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/at91/at91_pio.c b/sys/arm/at91/at91_pio.c index 0d9bd46a421..20f5002db2d 100644 --- a/sys/arm/at91/at91_pio.c +++ b/sys/arm/at91/at91_pio.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_pit.c b/sys/arm/at91/at91_pit.c index 7f7890b0178..a48af882391 100644 --- a/sys/arm/at91/at91_pit.c +++ b/sys/arm/at91/at91_pit.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_pmc.c b/sys/arm/at91/at91_pmc.c index 3784bada941..572bfa0de2b 100644 --- a/sys/arm/at91/at91_pmc.c +++ b/sys/arm/at91/at91_pmc.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_rst.c b/sys/arm/at91/at91_rst.c index 77ace5fbe61..48f781ac053 100644 --- a/sys/arm/at91/at91_rst.c +++ b/sys/arm/at91/at91_rst.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #define FDT_HACKS 1 diff --git a/sys/arm/at91/at91_sdramc.c b/sys/arm/at91/at91_sdramc.c index 99787ba7a71..3136db6a091 100644 --- a/sys/arm/at91/at91_sdramc.c +++ b/sys/arm/at91/at91_sdramc.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_shdwc.c b/sys/arm/at91/at91_shdwc.c index f3fa491dad8..92d56440e76 100644 --- a/sys/arm/at91/at91_shdwc.c +++ b/sys/arm/at91/at91_shdwc.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_spi.c b/sys/arm/at91/at91_spi.c index cdbc7b8e298..bbe80ab1d36 100644 --- a/sys/arm/at91/at91_spi.c +++ b/sys/arm/at91/at91_spi.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_tcb.c b/sys/arm/at91/at91_tcb.c index 42491ed74bd..5db1d3c4f74 100644 --- a/sys/arm/at91/at91_tcb.c +++ b/sys/arm/at91/at91_tcb.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_twi.c b/sys/arm/at91/at91_twi.c index 28676fc7cd8..8549406c57c 100644 --- a/sys/arm/at91/at91_twi.c +++ b/sys/arm/at91/at91_twi.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include "iicbus_if.h" #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/at91_wdt.c b/sys/arm/at91/at91_wdt.c index 95332025e2f..dd0887dd905 100644 --- a/sys/arm/at91/at91_wdt.c +++ b/sys/arm/at91/at91_wdt.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c index fdca46bf95f..8f742048b07 100644 --- a/sys/arm/at91/if_ate.c +++ b/sys/arm/at91/if_ate.c @@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/at91/if_macb.c b/sys/arm/at91/if_macb.c index c62184d2803..f0709a3335a 100644 --- a/sys/arm/at91/if_macb.c +++ b/sys/arm/at91/if_macb.c @@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$"); #include #ifdef FDT -#include #include #include #endif diff --git a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c index ea4b6f604ee..f20d5204828 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c @@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include @@ -1261,7 +1259,7 @@ bcm2835_cpufreq_identify(driver_t *driver, device_t parent) root = OF_finddevice("/"); for (compat = compat_data; compat->ocd_str != NULL; compat++) - if (fdt_is_compatible(root, compat->ocd_str)) + if (ofw_bus_node_is_compatible(root, compat->ocd_str)) break; if (compat->ocd_data == 0) diff --git a/sys/arm/broadcom/bcm2835/bcm2835_dma.c b/sys/arm/broadcom/bcm2835/bcm2835_dma.c index 3b6c03201fa..acb6e3afa97 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_dma.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_dma.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c index 58caac2cd88..d8c25b5a6e8 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -474,15 +473,15 @@ bcmfb_configure(int flags) if ((root != 0) && (display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) { if (sc->width == 0) { - if ((OF_getprop(display, "broadcom,width", + if ((OF_getencprop(display, "broadcom,width", &cell, sizeof(cell))) > 0) - sc->width = (int)fdt32_to_cpu(cell); + sc->width = cell; } if (sc->height == 0) { - if ((OF_getprop(display, "broadcom,height", + if ((OF_getencprop(display, "broadcom,height", &cell, sizeof(cell))) > 0) - sc->height = (int)fdt32_to_cpu(cell); + sc->height = cell; } } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c index 04cc83a42c8..f26b5c19697 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c b/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c index 86432cfca4a..026d4c574f6 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_ft5406.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/broadcom/bcm2835/bcm2835_intr.c b/sys/arm/broadcom/bcm2835/bcm2835_intr.c index f3a5a283284..249b86703fd 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_intr.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_intr.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c index 56413beb628..bd1762f8896 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c @@ -78,13 +78,15 @@ bcm2835_late_init(platform_t plat) system = OF_finddevice("/system"); if (system != 0) { - len = OF_getprop(system, "linux,serial", &cells, sizeof(cells)); + len = OF_getencprop(system, "linux,serial", cells, + sizeof(cells)); if (len > 0) - board_set_serial(fdt64_to_cpu(*((uint64_t *)cells))); + board_set_serial(((uint64_t)cells[0]) << 32 | cells[1]); - len = OF_getprop(system, "linux,revision", &cells, sizeof(cells)); + len = OF_getencprop(system, "linux,revision", cells, + sizeof(cells)); if (len > 0) - board_set_revision(fdt32_to_cpu(*((uint32_t *)cells))); + board_set_revision(cells[0]); } } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index b74fefd958e..f98d07df193 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/sys/arm/broadcom/bcm2835/bcm2835_spi.c b/sys/arm/broadcom/bcm2835/bcm2835_spi.c index b30fac7819c..dbfec6ea4f9 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_spi.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_spi.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/broadcom/bcm2835/bcm2835_systimer.c b/sys/arm/broadcom/bcm2835/bcm2835_systimer.c index 3fbaa903c59..724e5efbc86 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_systimer.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_systimer.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/broadcom/bcm2835/bcm2835_wdog.c b/sys/arm/broadcom/bcm2835/bcm2835_wdog.c index 39b16e34c5c..7a11b660a4e 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_wdog.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_wdog.c @@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC index f32f2e5fd17..93a9b802e82 100644 --- a/sys/arm/conf/GENERIC +++ b/sys/arm/conf/GENERIC @@ -43,6 +43,7 @@ files "../nvidia/tegra124/files.tegra124" files "../qemu/files.qemu" files "../ti/files.ti" files "../ti/am335x/files.am335x" +files "../ti/omap4/files.omap4" options SOC_ALLWINNER_A10 options SOC_ALLWINNER_A13 @@ -53,6 +54,7 @@ options SOC_ALLWINNER_A83T options SOC_ALLWINNER_H3 options SOC_BCM2836 options SOC_TI_AM335X +options SOC_OMAP4 options SCHED_ULE # ULE scheduler options SMP # Enable multiple cores @@ -80,6 +82,7 @@ device pmu # ARM Generic Timer device generic_timer +device mpcore_timer # MMC/SD/SDIO Card slot support device sdhci # SD controller @@ -129,6 +132,9 @@ device ti_i2c device am335x_pmic # AM335x Power Management IC (TPC65217) device am335x_rtc # RTC support (power management only) #define am335x_dmtpps # Pulse Per Second capture driver +device twl # TI TWLX0X0/TPS659x0 Power Management +device twl_vreg # twl voltage regulation +device twl_clks # twl external clocks # GPIO device gpio @@ -182,18 +188,18 @@ device usfs device loop device ether device vlan # 802.1Q VLAN support -device mii device bpf -device emac # 10/100 integrated EMAC controller -device dwc # 10/100/1000 integrated GMAC controller -device awg # 10/100/1000 integrated EMAC controller - -# USB ethernet support, requires miibus -device smcphy -device smsc +# Ethernet NICs that use the common MII bus controller code. +# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! device miibus +device awg # 10/100/1000 integrated EMAC controller +device cpsw # TI Common Platform Ethernet Switch (CPSW) +device dwc # 10/100/1000 integrated GMAC controller +device emac # 10/100 integrated EMAC controller +device smsc # SMSC LAN91C111 + # Sound support device sound @@ -214,9 +220,12 @@ device ti_pruss # Mailbox support device ti_mbox +# DMA controller +device ti_sdma + # Extensible Firmware Interface options EFI # Flattened Device Tree options FDT # Configure using FDT/DTB data -makeoptions MODULES_EXTRA="dtb/allwinner dtb/nvidia dtb/rpi" +makeoptions MODULES_EXTRA="dtb/allwinner dtb/am335x dtb/nvidia dtb/rpi dtb/omap4" diff --git a/sys/arm/conf/PANDABOARD b/sys/arm/conf/PANDABOARD index 4848cea6b03..2a0170d71ab 100644 --- a/sys/arm/conf/PANDABOARD +++ b/sys/arm/conf/PANDABOARD @@ -28,12 +28,13 @@ ident PANDABOARD hints "PANDABOARD.hints" include "std.armv6" -include "../ti/omap4/pandaboard/std.pandaboard" +include "../ti/omap4/std.omap4" makeoptions MODULES_EXTRA=dtb/omap4 options SCHED_ULE # ULE scheduler options PLATFORM +options PLATFORM_SMP options SMP # Enable multiple cores # NFS root from boopt/dhcp diff --git a/sys/arm/freescale/imx/imx51_ccm.c b/sys/arm/freescale/imx/imx51_ccm.c index 7a05d1e6830..e58c7abcae8 100644 --- a/sys/arm/freescale/imx/imx51_ccm.c +++ b/sys/arm/freescale/imx/imx51_ccm.c @@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/imx/imx51_ipuv3.c b/sys/arm/freescale/imx/imx51_ipuv3.c index a96b1852eb6..b88bb3fdb5d 100644 --- a/sys/arm/freescale/imx/imx51_ipuv3.c +++ b/sys/arm/freescale/imx/imx51_ipuv3.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -313,10 +312,10 @@ ipu3_fb_attach(device_t dev) * On i.MX53, the offset is 0. */ node = ofw_bus_get_node(dev); - if ((OF_getprop(node, "reg", ®, sizeof(reg))) <= 0) + if ((OF_getencprop(node, "reg", ®, sizeof(reg))) <= 0) base = 0; else - base = fdt32_to_cpu(reg) - IPU_CM_BASE(0); + base = reg - IPU_CM_BASE(0); /* map controller registers */ err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh); if (err) diff --git a/sys/arm/freescale/imx/imx51_ipuv3_fbd.c b/sys/arm/freescale/imx/imx51_ipuv3_fbd.c index 800244a80cd..ee6833fc392 100644 --- a/sys/arm/freescale/imx/imx51_ipuv3_fbd.c +++ b/sys/arm/freescale/imx/imx51_ipuv3_fbd.c @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -222,10 +221,10 @@ ipu3_fb_attach(device_t dev) * On i.MX53, the offset is 0. */ node = ofw_bus_get_node(dev); - if ((OF_getprop(node, "reg", ®, sizeof(reg))) <= 0) + if ((OF_getencprop(node, "reg", ®, sizeof(reg))) <= 0) base = 0; else - base = fdt32_to_cpu(reg) - IPU_CM_BASE(0); + base = reg - IPU_CM_BASE(0); /* map controller registers */ err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh); if (err) diff --git a/sys/arm/freescale/imx/imx6_audmux.c b/sys/arm/freescale/imx/imx6_audmux.c index 3b08a142a43..61ec0b6da51 100644 --- a/sys/arm/freescale/imx/imx6_audmux.c +++ b/sys/arm/freescale/imx/imx6_audmux.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/imx/imx6_ipu.c b/sys/arm/freescale/imx/imx6_ipu.c index f561fa77ffd..426ef474ef7 100644 --- a/sys/arm/freescale/imx/imx6_ipu.c +++ b/sys/arm/freescale/imx/imx6_ipu.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include #include diff --git a/sys/arm/freescale/imx/imx6_sdma.c b/sys/arm/freescale/imx/imx6_sdma.c index 4839270e7cc..aa39ea93289 100644 --- a/sys/arm/freescale/imx/imx6_sdma.c +++ b/sys/arm/freescale/imx/imx6_sdma.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/imx/imx6_ssi.c b/sys/arm/freescale/imx/imx6_ssi.c index 9000ae3ec9d..4f4dadb99c8 100644 --- a/sys/arm/freescale/imx/imx6_ssi.c +++ b/sys/arm/freescale/imx/imx6_ssi.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -447,12 +446,12 @@ find_sdma_controller(struct sc_info *sc) if ((len = OF_getproplen(node, "dmas")) <= 0) return (ENXIO); - OF_getprop(node, "dmas", &dts_value, len); + OF_getencprop(node, "dmas", &dts_value, len); - sc->sdma_ev_rx = fdt32_to_cpu(dts_value[1]); - sc->sdma_ev_tx = fdt32_to_cpu(dts_value[5]); + sc->sdma_ev_rx = dts_value[1]; + sc->sdma_ev_tx = dts_value[5]; - sdma_node = OF_node_from_xref(fdt32_to_cpu(dts_value[0])); + sdma_node = OF_node_from_xref(dts_value[0]); sdma_sc = NULL; diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c index 922548e33cb..1c308dbbd68 100644 --- a/sys/arm/freescale/imx/imx_gpio.c +++ b/sys/arm/freescale/imx/imx_gpio.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/imx/imx_gpt.c b/sys/arm/freescale/imx/imx_gpt.c index 8da0b2e0791..f0eb7665dc0 100644 --- a/sys/arm/freescale/imx/imx_gpt.c +++ b/sys/arm/freescale/imx/imx_gpt.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/imx/imx_i2c.c b/sys/arm/freescale/imx/imx_i2c.c index 2e453dacc32..c679c2fc56f 100644 --- a/sys/arm/freescale/imx/imx_i2c.c +++ b/sys/arm/freescale/imx/imx_i2c.c @@ -63,7 +63,6 @@ __FBSDID("$FreeBSD$"); #include #include "iicbus_if.h" -#include #include #include #include diff --git a/sys/arm/freescale/imx/imx_iomux.c b/sys/arm/freescale/imx/imx_iomux.c index be3a3e81b22..c9de2a31f8d 100644 --- a/sys/arm/freescale/imx/imx_iomux.c +++ b/sys/arm/freescale/imx/imx_iomux.c @@ -59,11 +59,10 @@ #include -#include -#include #include #include #include +#include #include #include diff --git a/sys/arm/freescale/imx/imx_wdog.c b/sys/arm/freescale/imx/imx_wdog.c index cbf9343b1c6..f1e450102a8 100644 --- a/sys/arm/freescale/imx/imx_wdog.c +++ b/sys/arm/freescale/imx/imx_wdog.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/imx/tzic.c b/sys/arm/freescale/imx/tzic.c index 0f3cf5cc075..e1b0635418d 100644 --- a/sys/arm/freescale/imx/tzic.c +++ b/sys/arm/freescale/imx/tzic.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_adc.c b/sys/arm/freescale/vybrid/vf_adc.c index 0a806fb96c7..7a506b89300 100644 --- a/sys/arm/freescale/vybrid/vf_adc.c +++ b/sys/arm/freescale/vybrid/vf_adc.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_anadig.c b/sys/arm/freescale/vybrid/vf_anadig.c index 3a2cbc4e481..411c3a1cd9f 100644 --- a/sys/arm/freescale/vybrid/vf_anadig.c +++ b/sys/arm/freescale/vybrid/vf_anadig.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_common.c b/sys/arm/freescale/vybrid/vf_common.c index d5774817282..9c3082b6800 100644 --- a/sys/arm/freescale/vybrid/vf_common.c +++ b/sys/arm/freescale/vybrid/vf_common.c @@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -44,16 +43,15 @@ void cpu_reset(void) { phandle_t src; - uint32_t addr, paddr; + uint32_t paddr; bus_addr_t vaddr; if (src_swreset() == 0) goto end; src = OF_finddevice("src"); - if ((src != 0) && (OF_getprop(src, "reg", &paddr, sizeof(paddr))) > 0) { - addr = fdt32_to_cpu(paddr); - if (bus_space_map(fdtbus_bs_tag, addr, 0x10, 0, &vaddr) == 0) { + if ((src != 0) && (OF_getencprop(src, "reg", &paddr, sizeof(paddr))) > 0) { + if (bus_space_map(fdtbus_bs_tag, paddr, 0x10, 0, &vaddr) == 0) { bus_space_write_4(fdtbus_bs_tag, vaddr, 0x00, SW_RST); } } @@ -61,24 +59,3 @@ cpu_reset(void) end: while (1); } - -#ifndef INTRNG -static int -fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, - int *pol) -{ - - if (!fdt_is_compatible(node, "arm,gic")) - return (ENXIO); - - *interrupt = fdt32_to_cpu(intr[0]); - *trig = INTR_TRIGGER_CONFORM; - *pol = INTR_POLARITY_CONFORM; - return (0); -} - -fdt_pic_decode_t fdt_pic_table[] = { - &fdt_pic_decode_ic, - NULL -}; -#endif diff --git a/sys/arm/freescale/vybrid/vf_dcu4.c b/sys/arm/freescale/vybrid/vf_dcu4.c index 34dea4600a9..7fbf4a36ebb 100644 --- a/sys/arm/freescale/vybrid/vf_dcu4.c +++ b/sys/arm/freescale/vybrid/vf_dcu4.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -246,37 +245,37 @@ get_panel_info(struct dcu_softc *sc, struct panel_info *panel) /* panel size */ if ((len = OF_getproplen(node, "panel-size")) <= 0) return (ENXIO); - OF_getprop(node, "panel-size", &dts_value, len); - panel->width = fdt32_to_cpu(dts_value[0]); - panel->height = fdt32_to_cpu(dts_value[1]); + OF_getencprop(node, "panel-size", dts_value, len); + panel->width = dts_value[0]; + panel->height = dts_value[1]; /* hsync */ if ((len = OF_getproplen(node, "panel-hsync")) <= 0) return (ENXIO); - OF_getprop(node, "panel-hsync", &dts_value, len); - panel->h_back_porch = fdt32_to_cpu(dts_value[0]); - panel->h_pulse_width = fdt32_to_cpu(dts_value[1]); - panel->h_front_porch = fdt32_to_cpu(dts_value[2]); + OF_getencprop(node, "panel-hsync", dts_value, len); + panel->h_back_porch = dts_value[0]; + panel->h_pulse_width = dts_value[1]; + panel->h_front_porch = dts_value[2]; /* vsync */ if ((len = OF_getproplen(node, "panel-vsync")) <= 0) return (ENXIO); - OF_getprop(node, "panel-vsync", &dts_value, len); - panel->v_back_porch = fdt32_to_cpu(dts_value[0]); - panel->v_pulse_width = fdt32_to_cpu(dts_value[1]); - panel->v_front_porch = fdt32_to_cpu(dts_value[2]); + OF_getencprop(node, "panel-vsync", dts_value, len); + panel->v_back_porch = dts_value[0]; + panel->v_pulse_width = dts_value[1]; + panel->v_front_porch = dts_value[2]; /* clk divider */ if ((len = OF_getproplen(node, "panel-clk-div")) <= 0) return (ENXIO); - OF_getprop(node, "panel-clk-div", &dts_value, len); - panel->clk_div = fdt32_to_cpu(dts_value[0]); + OF_getencprop(node, "panel-clk-div", dts_value, len); + panel->clk_div = dts_value[0]; /* backlight pin */ if ((len = OF_getproplen(node, "panel-backlight-pin")) <= 0) return (ENXIO); - OF_getprop(node, "panel-backlight-pin", &dts_value, len); - panel->backlight_pin = fdt32_to_cpu(dts_value[0]); + OF_getencprop(node, "panel-backlight-pin", dts_value, len); + panel->backlight_pin = dts_value[0]; return (0); } diff --git a/sys/arm/freescale/vybrid/vf_dmamux.c b/sys/arm/freescale/vybrid/vf_dmamux.c index a887ffa16d9..3e6b84e1ef5 100644 --- a/sys/arm/freescale/vybrid/vf_dmamux.c +++ b/sys/arm/freescale/vybrid/vf_dmamux.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_edma.c b/sys/arm/freescale/vybrid/vf_edma.c index 93179216a5b..eb6e514840d 100644 --- a/sys/arm/freescale/vybrid/vf_edma.c +++ b/sys/arm/freescale/vybrid/vf_edma.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -284,8 +283,8 @@ edma_attach(device_t dev) if ((len = OF_getproplen(node, "device-id")) <= 0) return (ENXIO); - OF_getprop(node, "device-id", &dts_value, len); - sc->device_id = fdt32_to_cpu(dts_value); + OF_getencprop(node, "device-id", &dts_value, len); + sc->device_id = dts_value; sc->dma_stop = dma_stop; sc->dma_setup = dma_setup; diff --git a/sys/arm/freescale/vybrid/vf_ehci.c b/sys/arm/freescale/vybrid/vf_ehci.c index 0a7dc941fef..9ac26d0513c 100644 --- a/sys/arm/freescale/vybrid/vf_ehci.c +++ b/sys/arm/freescale/vybrid/vf_ehci.c @@ -55,8 +55,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include diff --git a/sys/arm/freescale/vybrid/vf_gpio.c b/sys/arm/freescale/vybrid/vf_gpio.c index 0c1cf82303d..9cab805c287 100644 --- a/sys/arm/freescale/vybrid/vf_gpio.c +++ b/sys/arm/freescale/vybrid/vf_gpio.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_i2c.c b/sys/arm/freescale/vybrid/vf_i2c.c index 8008d1af897..6c634c069a9 100644 --- a/sys/arm/freescale/vybrid/vf_i2c.c +++ b/sys/arm/freescale/vybrid/vf_i2c.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include "iicbus_if.h" -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_iomuxc.c b/sys/arm/freescale/vybrid/vf_iomuxc.c index 95711d67647..c4e29fe89cc 100644 --- a/sys/arm/freescale/vybrid/vf_iomuxc.c +++ b/sys/arm/freescale/vybrid/vf_iomuxc.c @@ -148,12 +148,12 @@ pinmux_set(struct iomuxc_softc *sc) continue; if ((len = OF_getproplen(child, "iomux_config")) > 0) { - OF_getprop(child, "iomux_config", &iomux_config, len); + OF_getencprop(child, "iomux_config", iomux_config, len); values = len / (sizeof(uint32_t)); for (i = 0; i < values; i += 2) { - pin = fdt32_to_cpu(iomux_config[i]); - pin_cfg = fdt32_to_cpu(iomux_config[i+1]); + pin = iomux_config[i]; + pin_cfg = iomux_config[i+1]; #if 0 device_printf(sc->dev, "Set pin %d to 0x%08x\n", pin, pin_cfg); diff --git a/sys/arm/freescale/vybrid/vf_machdep.c b/sys/arm/freescale/vybrid/vf_machdep.c index 15566a4f383..6628a7608a4 100644 --- a/sys/arm/freescale/vybrid/vf_machdep.c +++ b/sys/arm/freescale/vybrid/vf_machdep.c @@ -42,8 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - vm_offset_t platform_lastaddr(void) { diff --git a/sys/arm/freescale/vybrid/vf_mscm.c b/sys/arm/freescale/vybrid/vf_mscm.c index 02850e58936..1f78b45f309 100644 --- a/sys/arm/freescale/vybrid/vf_mscm.c +++ b/sys/arm/freescale/vybrid/vf_mscm.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_port.c b/sys/arm/freescale/vybrid/vf_port.c index 6ff8bfcccb1..2c2be2907e5 100644 --- a/sys/arm/freescale/vybrid/vf_port.c +++ b/sys/arm/freescale/vybrid/vf_port.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_sai.c b/sys/arm/freescale/vybrid/vf_sai.c index 83f689f87d2..8ff802a37f3 100644 --- a/sys/arm/freescale/vybrid/vf_sai.c +++ b/sys/arm/freescale/vybrid/vf_sai.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -424,19 +423,19 @@ find_edma_controller(struct sc_info *sc) if ((len = OF_getproplen(node, "edma-mux-group")) <= 0) return (ENXIO); - OF_getprop(node, "edma-src-transmit", &dts_value, len); - edma_src_transmit = fdt32_to_cpu(dts_value); - OF_getprop(node, "edma-mux-group", &dts_value, len); - edma_mux_group = fdt32_to_cpu(dts_value); - OF_getprop(node, "edma-controller", &dts_value, len); - edma_node = OF_node_from_xref(fdt32_to_cpu(dts_value)); + OF_getencprop(node, "edma-src-transmit", &dts_value, len); + edma_src_transmit = dts_value; + OF_getencprop(node, "edma-mux-group", &dts_value, len); + edma_mux_group = dts_value; + OF_getencprop(node, "edma-controller", &dts_value, len); + edma_node = OF_node_from_xref(dts_value); if ((len = OF_getproplen(edma_node, "device-id")) <= 0) { return (ENXIO); } - OF_getprop(edma_node, "device-id", &dts_value, len); - edma_device_id = fdt32_to_cpu(dts_value); + OF_getencprop(edma_node, "device-id", &dts_value, len); + edma_device_id = dts_value; edma_sc = NULL; diff --git a/sys/arm/freescale/vybrid/vf_spi.c b/sys/arm/freescale/vybrid/vf_spi.c index 8fa466bf83b..c089d01bfd3 100644 --- a/sys/arm/freescale/vybrid/vf_spi.c +++ b/sys/arm/freescale/vybrid/vf_spi.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include "spibus_if.h" -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_src.c b/sys/arm/freescale/vybrid/vf_src.c index 83d7e969e09..20fc59f6df0 100644 --- a/sys/arm/freescale/vybrid/vf_src.c +++ b/sys/arm/freescale/vybrid/vf_src.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/freescale/vybrid/vf_tcon.c b/sys/arm/freescale/vybrid/vf_tcon.c index 31f85b58b46..8bc256b1cc1 100644 --- a/sys/arm/freescale/vybrid/vf_tcon.c +++ b/sys/arm/freescale/vybrid/vf_tcon.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/lpc/lpc_fb.c b/sys/arm/lpc/lpc_fb.c index b2eab8b526a..e4969159a45 100644 --- a/sys/arm/lpc/lpc_fb.c +++ b/sys/arm/lpc/lpc_fb.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -280,10 +279,9 @@ lpc_fb_intr(void *arg) static int lpc_fb_fdt_read(phandle_t node, const char *name, uint32_t *ret) { - if (OF_getprop(node, name, ret, sizeof(uint32_t)) <= 0) + if (OF_getencprop(node, name, ret, sizeof(uint32_t)) <= 0) return (ENOENT); - *ret = fdt32_to_cpu(*ret); return (0); } diff --git a/sys/arm/lpc/lpc_intc.c b/sys/arm/lpc/lpc_intc.c index d26ef9099c7..a5ee160b9f1 100644 --- a/sys/arm/lpc/lpc_intc.c +++ b/sys/arm/lpc/lpc_intc.c @@ -232,7 +232,7 @@ static int fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) { - if (!fdt_is_compatible(node, "lpc,pic")) + if (!ofw_bus_node_is_compatible(node, "lpc,pic")) return (ENXIO); *interrupt = fdt32_to_cpu(intr[0]); diff --git a/sys/arm/lpc/lpc_machdep.c b/sys/arm/lpc/lpc_machdep.c index d193ac9f8d0..7a3c4b5b6c2 100644 --- a/sys/arm/lpc/lpc_machdep.c +++ b/sys/arm/lpc/lpc_machdep.c @@ -58,8 +58,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - vm_offset_t platform_lastaddr(void) { diff --git a/sys/arm/lpc/lpc_timer.c b/sys/arm/lpc/lpc_timer.c index ded53fa9931..f745cf01b39 100644 --- a/sys/arm/lpc/lpc_timer.c +++ b/sys/arm/lpc/lpc_timer.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -158,7 +157,7 @@ lpc_timer_attach(device_t dev) /* Get PERIPH_CLK encoded in parent bus 'bus-frequency' property */ node = ofw_bus_get_node(dev); - if (OF_getprop(OF_parent(node), "bus-frequency", &freq, + if (OF_getencprop(OF_parent(node), "bus-frequency", &freq, sizeof(pcell_t)) <= 0) { bus_release_resources(dev, lpc_timer_spec, sc->lt_res); bus_teardown_intr(dev, sc->lt_res[2], intrcookie); @@ -166,8 +165,6 @@ lpc_timer_attach(device_t dev) return (ENXIO); } - freq = fdt32_to_cpu(freq); - /* Set desired frequency in event timer and timecounter */ sc->lt_et.et_frequency = (uint64_t)freq; lpc_timecounter.tc_frequency = (uint64_t)freq; diff --git a/sys/arm/mv/armadaxp/armadaxp.c b/sys/arm/mv/armadaxp/armadaxp.c index 172d3d71b4d..29b2642f847 100644 --- a/sys/arm/mv/armadaxp/armadaxp.c +++ b/sys/arm/mv/armadaxp/armadaxp.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/mv/gpio.c b/sys/arm/mv/gpio.c index 79b7cc622a1..70d3d06be43 100644 --- a/sys/arm/mv/gpio.c +++ b/sys/arm/mv/gpio.c @@ -113,7 +113,7 @@ struct gpio_ctrl_entry { gpios_phandler_t handler; }; -int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len); +static int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len); int gpio_get_config_from_dt(void); struct gpio_ctrl_entry gpio_controllers[] = { @@ -540,7 +540,7 @@ mv_gpio_value_set(uint32_t pin, uint8_t val) mv_gpio_reg_clear(reg, pin); } -int +static int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len) { pcell_t gpio_cells, pincnt; @@ -554,10 +554,8 @@ mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len) /* Node is not a GPIO controller. */ return (ENXIO); - if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0) + if (OF_getencprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0) return (ENXIO); - - gpio_cells = fdt32_to_cpu(gpio_cells); if (gpio_cells != 3) return (ENXIO); @@ -567,9 +565,9 @@ mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len) if (fdt_regsize(ctrl, &gpio_ctrl, &size)) return (ENXIO); - if (OF_getprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0) + if (OF_getencprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0) return (ENXIO); - sc.pin_num = fdt32_to_cpu(pincnt); + sc.pin_num = pincnt; /* * Skip controller reference, since controller's phandle is given @@ -579,9 +577,9 @@ mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len) gpios += inc; for (t = 0; t < tuples; t++) { - pin = fdt32_to_cpu(gpios[0]); - dir = fdt32_to_cpu(gpios[1]); - flags = fdt32_to_cpu(gpios[2]); + pin = gpios[0]; + dir = gpios[1]; + flags = gpios[2]; mv_gpio_configure(pin, flags); @@ -630,7 +628,7 @@ mv_gpio_init(void) return (ENXIO); /* Get 'gpios' property. */ - OF_getprop(child, "gpios", &gpios, len); + OF_getencprop(child, "gpios", gpios, len); e = (struct gpio_ctrl_entry *)&gpio_controllers; @@ -641,9 +639,9 @@ mv_gpio_init(void) * contain a ref. to a node defining GPIO * controller. */ - ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0])); + ctrl = OF_node_from_xref(gpios[0]); - if (fdt_is_compatible(ctrl, e->compat)) + if (ofw_bus_node_is_compatible(ctrl, e->compat)) /* Call a handler. */ if ((rv = e->handler(ctrl, (pcell_t *)&gpios, len))) diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c index 497860f6d1e..4f7f07c027b 100644 --- a/sys/arm/mv/mv_common.c +++ b/sys/arm/mv/mv_common.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -230,7 +231,8 @@ fdt_pm(phandle_t node) if (dev_mask & (1 << i)) continue; - compat = fdt_is_compatible(node, fdt_pm_mask_table[i].compat); + compat = ofw_bus_node_is_compatible(node, + fdt_pm_mask_table[i].compat); #if defined(SOC_MV_KIRKWOOD) if (compat && (cpu_pm_ctrl & fdt_pm_mask_table[i].mask)) { dev_mask |= (1 << i); @@ -2092,7 +2094,7 @@ win_cpu_from_dt(void) * Retrieve CESA SRAM data. */ if ((node = OF_finddevice("sram")) != -1) - if (fdt_is_compatible(node, "mrvl,cesa-sram")) + if (ofw_bus_node_is_compatible(node, "mrvl,cesa-sram")) goto moveon; if ((node = OF_finddevice("/")) == 0) @@ -2120,7 +2122,7 @@ moveon: /* Check if there is a second CESA node */ while ((node = OF_peer(node)) != 0) { - if (fdt_is_compatible(node, "mrvl,cesa-sram")) { + if (ofw_bus_node_is_compatible(node, "mrvl,cesa-sram")) { if (fdt_regsize(node, &sram_base, &sram_size) != 0) return (EINVAL); break; @@ -2170,7 +2172,7 @@ fdt_win_setup(void) soc_node = &soc_nodes[i]; - if (!fdt_is_compatible(child, soc_node->compat)) + if (!ofw_bus_node_is_compatible(child,soc_node->compat)) continue; err = fdt_regsize(child, &base, &size); @@ -2319,8 +2321,8 @@ fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) { - if (!fdt_is_compatible(node, "mrvl,pic") && - !fdt_is_compatible(node, "mrvl,mpic")) + if (!ofw_bus_node_is_compatible(node, "mrvl,pic") && + !ofw_bus_node_is_compatible(node, "mrvl,mpic")) return (ENXIO); *interrupt = fdt32_to_cpu(intr[0]); diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c index ce9766370dd..b5bda023146 100644 --- a/sys/arm/mv/mv_machdep.c +++ b/sys/arm/mv/mv_machdep.c @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include static int platform_mpp_init(void); #if defined(SOC_MV_ARMADAXP) @@ -103,7 +104,7 @@ platform_mpp_init(void) * Try to access the MPP node directly i.e. through /aliases/mpp. */ if ((node = OF_finddevice("mpp")) != -1) - if (fdt_is_compatible(node, "mrvl,mpp")) + if (ofw_bus_node_is_compatible(node, "mrvl,mpp")) goto moveon; /* * Find the node the long way. @@ -146,21 +147,19 @@ moveon: /* * Process 'pin-count' and 'pin-map' props. */ - if (OF_getprop(node, "pin-count", &pin_count, sizeof(pin_count)) <= 0) + if (OF_getencprop(node, "pin-count", &pin_count, sizeof(pin_count)) <= 0) return (ENXIO); - pin_count = fdt32_to_cpu(pin_count); if (pin_count > MPP_PIN_MAX) return (ERANGE); - if (OF_getprop(node, "#pin-cells", &pin_cells, sizeof(pin_cells)) <= 0) + if (OF_getencprop(node, "#pin-cells", &pin_cells, sizeof(pin_cells)) <= 0) pin_cells = MPP_PIN_CELLS; - pin_cells = fdt32_to_cpu(pin_cells); if (pin_cells > MPP_PIN_CELLS) return (ERANGE); tuple_size = sizeof(pcell_t) * pin_cells; bzero(pinmap, sizeof(pinmap)); - len = OF_getprop(node, "pin-map", pinmap, sizeof(pinmap)); + len = OF_getencprop(node, "pin-map", pinmap, sizeof(pinmap)); if (len <= 0) return (ERANGE); if (len % tuple_size) @@ -175,8 +174,8 @@ moveon: bzero(mpp, sizeof(mpp)); pinmap_ptr = pinmap; for (i = 0; i < pins; i++) { - mpp_pin = fdt32_to_cpu(*pinmap_ptr); - mpp_function = fdt32_to_cpu(*(pinmap_ptr + 1)); + mpp_pin = *pinmap_ptr; + mpp_function = *(pinmap_ptr + 1); mpp[mpp_pin] = mpp_function; pinmap_ptr += pin_cells; } @@ -290,8 +289,8 @@ platform_sram_devmap(struct devmap_entry *map) * SRAM range. */ if ((child = OF_finddevice("/sram")) != 0) - if (fdt_is_compatible(child, "mrvl,cesa-sram") || - fdt_is_compatible(child, "mrvl,scratchpad")) + if (ofw_bus_node_is_compatible(child, "mrvl,cesa-sram") || + ofw_bus_node_is_compatible(child, "mrvl,scratchpad")) goto moveon; if ((root = OF_finddevice("/")) == 0) @@ -406,14 +405,12 @@ platform_devmap_init(void) i += 2; } - if (fdt_is_compatible(child, "mrvl,lbc")) { + if (ofw_bus_node_is_compatible(child, "mrvl,lbc")) { /* Check available space */ - if (OF_getprop(child, "bank-count", (void *)&bank_count, + if (OF_getencprop(child, "bank-count", &bank_count, sizeof(bank_count)) <= 0) /* If no property, use default value */ bank_count = 1; - else - bank_count = fdt32_to_cpu(bank_count); if ((i + bank_count) >= FDT_DEVMAP_MAX) return (ENOMEM); diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c index 55d3f15bb89..7f6b1f7da20 100644 --- a/sys/arm/mv/mv_pci.c +++ b/sys/arm/mv/mv_pci.c @@ -429,12 +429,12 @@ mv_pcib_attach(device_t self) node = ofw_bus_get_node(self); parnode = OF_parent(node); - if (fdt_is_compatible(node, "mrvl,pcie")) { + if (ofw_bus_node_is_compatible(node, "mrvl,pcie")) { sc->sc_type = MV_TYPE_PCIE; sc->sc_win_target = MV_WIN_PCIE_TARGET(unit); sc->sc_mem_win_attr = MV_WIN_PCIE_MEM_ATTR(unit); sc->sc_io_win_attr = MV_WIN_PCIE_IO_ATTR(unit); - } else if (fdt_is_compatible(node, "mrvl,pci")) { + } else if (ofw_bus_node_is_compatible(node, "mrvl,pci")) { sc->sc_type = MV_TYPE_PCI; sc->sc_win_target = MV_WIN_PCI_TARGET; sc->sc_mem_win_attr = MV_WIN_PCI_MEM_ATTR; diff --git a/sys/arm/mv/mv_ts.c b/sys/arm/mv/mv_ts.c index 35cd06221e4..3ed8ab748d1 100644 --- a/sys/arm/mv/mv_ts.c +++ b/sys/arm/mv/mv_ts.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/nvidia/tegra124/tegra124_machdep.c b/sys/arm/nvidia/tegra124/tegra124_machdep.c index 0e881cc83ad..b874b5abd0f 100644 --- a/sys/arm/nvidia/tegra124/tegra124_machdep.c +++ b/sys/arm/nvidia/tegra124/tegra124_machdep.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/nvidia/tegra124/tegra124_pmc.c b/sys/arm/nvidia/tegra124/tegra124_pmc.c index 04ff73cd1d9..cae31238037 100644 --- a/sys/arm/nvidia/tegra124/tegra124_pmc.c +++ b/sys/arm/nvidia/tegra124/tegra124_pmc.c @@ -38,7 +38,6 @@ #include #include -#include #include #include diff --git a/sys/arm/nvidia/tegra_abpmisc.c b/sys/arm/nvidia/tegra_abpmisc.c index 56d91b7caa9..d51ec2e9729 100644 --- a/sys/arm/nvidia/tegra_abpmisc.c +++ b/sys/arm/nvidia/tegra_abpmisc.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/nvidia/tegra_ahci.c b/sys/arm/nvidia/tegra_ahci.c index bfa34132581..2ea714a7764 100644 --- a/sys/arm/nvidia/tegra_ahci.c +++ b/sys/arm/nvidia/tegra_ahci.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/arm/nvidia/tegra_efuse.c b/sys/arm/nvidia/tegra_efuse.c index 34e0da00f0e..13d97abd033 100644 --- a/sys/arm/nvidia/tegra_efuse.c +++ b/sys/arm/nvidia/tegra_efuse.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/nvidia/tegra_gpio.c b/sys/arm/nvidia/tegra_gpio.c index d715a692a4c..7626d3072be 100644 --- a/sys/arm/nvidia/tegra_gpio.c +++ b/sys/arm/nvidia/tegra_gpio.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/nvidia/tegra_i2c.c b/sys/arm/nvidia/tegra_i2c.c index f88768e6939..ed0074277d0 100644 --- a/sys/arm/nvidia/tegra_i2c.c +++ b/sys/arm/nvidia/tegra_i2c.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/nvidia/tegra_pcie.c b/sys/arm/nvidia/tegra_pcie.c index 4fe7c710261..e62f35308e4 100644 --- a/sys/arm/nvidia/tegra_pcie.c +++ b/sys/arm/nvidia/tegra_pcie.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/arm/nvidia/tegra_rtc.c b/sys/arm/nvidia/tegra_rtc.c index 09a7c74728a..2a783735f4b 100644 --- a/sys/arm/nvidia/tegra_rtc.c +++ b/sys/arm/nvidia/tegra_rtc.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/nvidia/tegra_uart.c b/sys/arm/nvidia/tegra_uart.c index c70303ff5e0..05c306931e3 100644 --- a/sys/arm/nvidia/tegra_uart.c +++ b/sys/arm/nvidia/tegra_uart.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -248,4 +247,4 @@ static driver_t tegra_uart_driver = { }; DRIVER_MODULE(tegra_uart, simplebus, tegra_uart_driver, uart_devclass, - 0, 0); \ No newline at end of file + 0, 0); diff --git a/sys/arm/nvidia/tegra_usbphy.c b/sys/arm/nvidia/tegra_usbphy.c index d1c6eeb45cf..811c5a878bd 100644 --- a/sys/arm/nvidia/tegra_usbphy.c +++ b/sys/arm/nvidia/tegra_usbphy.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/arm/rockchip/files.rk30xx b/sys/arm/rockchip/files.rk30xx index 274748a0e18..b058ed91c57 100644 --- a/sys/arm/rockchip/files.rk30xx +++ b/sys/arm/rockchip/files.rk30xx @@ -1,7 +1,6 @@ # $FreeBSD$ kern/kern_clocksource.c standard -arm/rockchip/rk30xx_common.c standard arm/rockchip/rk30xx_machdep.c standard arm/rockchip/rk30xx_pmu.c standard arm/rockchip/rk30xx_grf.c standard diff --git a/sys/arm/rockchip/rk30xx_gpio.c b/sys/arm/rockchip/rk30xx_gpio.c index 609eb6af6c9..75bfd003404 100644 --- a/sys/arm/rockchip/rk30xx_gpio.c +++ b/sys/arm/rockchip/rk30xx_gpio.c @@ -526,10 +526,8 @@ rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len) if (sc == NULL) return ENXIO; - if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0) + if (OF_getencprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0) return (ENXIO); - - gpio_cells = fdt32_to_cpu(gpio_cells); if (gpio_cells != 2) return (ENXIO); @@ -546,9 +544,9 @@ rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len) inc = sizeof(ihandle_t) / sizeof(pcell_t); gpios += inc; for (t = 0; t < tuples; t++) { - pin = fdt32_to_cpu(gpios[0]); - dir = fdt32_to_cpu(gpios[1]); - flags = fdt32_to_cpu(gpios[2]); + pin = gpios[0]; + dir = gpios[1]; + flags = gpios[2]; for (i = 0; i < sc->sc_gpio_npins; i++) { if (sc->sc_gpio_pins[i].gp_pin == pin) @@ -601,7 +599,7 @@ rk30_gpio_init(void) return (ENXIO); /* Get 'gpios' property. */ - OF_getprop(child, "gpios", &gpios, len); + OF_getencprop(child, "gpios", gpios, len); e = (struct gpio_ctrl_entry *)&gpio_controllers; @@ -612,9 +610,9 @@ rk30_gpio_init(void) * contain a ref. to a node defining GPIO * controller. */ - ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0])); + ctrl = OF_node_from_xref(gpios[0]); - if (fdt_is_compatible(ctrl, e->compat)) + if (ofw_bus_node_is_compatible(ctrl, e->compat)) /* Call a handler. */ if ((rv = e->handler(ctrl, (pcell_t *)&gpios, len))) diff --git a/sys/arm/rockchip/rk30xx_grf.c b/sys/arm/rockchip/rk30xx_grf.c index ce61e8c4e5f..6261928ff11 100644 --- a/sys/arm/rockchip/rk30xx_grf.c +++ b/sys/arm/rockchip/rk30xx_grf.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/rockchip/rk30xx_machdep.c b/sys/arm/rockchip/rk30xx_machdep.c index bb3731504d9..d45ef8d4c04 100644 --- a/sys/arm/rockchip/rk30xx_machdep.c +++ b/sys/arm/rockchip/rk30xx_machdep.c @@ -47,8 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include vm_offset_t diff --git a/sys/arm/rockchip/rk30xx_pmu.c b/sys/arm/rockchip/rk30xx_pmu.c index 514e961d0d1..a3d1bd74cba 100644 --- a/sys/arm/rockchip/rk30xx_pmu.c +++ b/sys/arm/rockchip/rk30xx_pmu.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/rockchip/rk30xx_wdog.c b/sys/arm/rockchip/rk30xx_wdog.c index 32ef5bdb029..612b793fcbe 100644 --- a/sys/arm/rockchip/rk30xx_wdog.c +++ b/sys/arm/rockchip/rk30xx_wdog.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/samsung/exynos/exynos5_common.c b/sys/arm/samsung/exynos/exynos5_common.c index 04021c1cb91..c5174d48b26 100644 --- a/sys/arm/samsung/exynos/exynos5_common.c +++ b/sys/arm/samsung/exynos/exynos5_common.c @@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -48,24 +47,3 @@ cpu_reset(void) while (1); } - -#ifndef INTRNG -static int -fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, - int *pol) -{ - - if (!fdt_is_compatible(node, "arm,gic")) - return (ENXIO); - - *interrupt = fdt32_to_cpu(intr[0]); - *trig = INTR_TRIGGER_CONFORM; - *pol = INTR_POLARITY_CONFORM; - return (0); -} - -fdt_pic_decode_t fdt_pic_table[] = { - &fdt_pic_decode_ic, - NULL -}; -#endif diff --git a/sys/arm/ti/aintc.c b/sys/arm/ti/aintc.c index 764f3a0726d..ec2aad83059 100644 --- a/sys/arm/ti/aintc.c +++ b/sys/arm/ti/aintc.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -298,13 +297,13 @@ static device_method_t ti_aintc_methods[] = { }; static driver_t ti_aintc_driver = { - "aintc", + "ti_aintc", ti_aintc_methods, sizeof(struct ti_aintc_softc), }; static devclass_t ti_aintc_devclass; -EARLY_DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, +EARLY_DRIVER_MODULE(ti_aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); SIMPLEBUS_PNP_INFO(compat_data); diff --git a/sys/arm/ti/am335x/am335x_ecap.c b/sys/arm/ti/am335x/am335x_ecap.c index eba5f722aed..75b845f56e0 100644 --- a/sys/arm/ti/am335x/am335x_ecap.c +++ b/sys/arm/ti/am335x/am335x_ecap.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include #include diff --git a/sys/arm/ti/am335x/am335x_ehrpwm.c b/sys/arm/ti/am335x/am335x_ehrpwm.c index 331331fcd94..53cb3bb7824 100644 --- a/sys/arm/ti/am335x/am335x_ehrpwm.c +++ b/sys/arm/ti/am335x/am335x_ehrpwm.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include #include diff --git a/sys/arm/ti/am335x/am335x_gpio.c b/sys/arm/ti/am335x/am335x_gpio.c index 63fc54429a7..cbfde175c2e 100644 --- a/sys/arm/ti/am335x/am335x_gpio.c +++ b/sys/arm/ti/am335x/am335x_gpio.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -66,8 +65,6 @@ static struct ofw_compat_data compat_data[] = { static int am335x_gpio_probe(device_t dev) { - if (ti_chip() != CHIP_AM335X) - return (ENXIO); if (!ofw_bus_status_okay(dev)) return (ENXIO); @@ -75,6 +72,9 @@ am335x_gpio_probe(device_t dev) if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); + if (ti_chip() != CHIP_AM335X) + return (ENXIO); + device_set_desc(dev, "TI AM335x General Purpose I/O (GPIO)"); return (0); diff --git a/sys/arm/ti/am335x/am335x_lcd.c b/sys/arm/ti/am335x/am335x_lcd.c index 8121ef58e7c..c23aa24fb65 100644 --- a/sys/arm/ti/am335x/am335x_lcd.c +++ b/sys/arm/ti/am335x/am335x_lcd.c @@ -359,13 +359,13 @@ am335x_read_property(device_t dev, phandle_t node, const char *name, uint32_t *v { pcell_t cell; - if ((OF_getprop(node, name, &cell, sizeof(cell))) <= 0) { + if ((OF_getencprop(node, name, &cell, sizeof(cell))) <= 0) { device_printf(dev, "missing '%s' attribute in LCD panel info\n", name); return (ENXIO); } - *val = fdt32_to_cpu(cell); + *val = cell; return (0); } diff --git a/sys/arm/ti/am335x/am335x_lcd_syscons.c b/sys/arm/ti/am335x/am335x_lcd_syscons.c index 2cbf2fcadad..946722fb878 100644 --- a/sys/arm/ti/am335x/am335x_lcd_syscons.c +++ b/sys/arm/ti/am335x/am335x_lcd_syscons.c @@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -351,7 +350,7 @@ am335x_syscons_find_panel_node(phandle_t start) phandle_t result; for (child = OF_child(start); child != 0; child = OF_peer(child)) { - if (fdt_is_compatible(child, "ti,am335x-lcd")) + if (ofw_bus_node_is_compatible(child, "ti,am335x-lcd")) return (child); if ((result = am335x_syscons_find_panel_node(child))) return (result); @@ -383,13 +382,13 @@ am335x_syscons_configure(int flags) root = OF_finddevice("/"); if ((root != 0) && (display = am335x_syscons_find_panel_node(root))) { - if ((OF_getprop(display, "panel_width", - &cell, sizeof(cell))) > 0) - va_sc->width = (int)fdt32_to_cpu(cell); + if ((OF_getencprop(display, "panel_width", &cell, + sizeof(cell))) > 0) + va_sc->width = cell; - if ((OF_getprop(display, "panel_height", - &cell, sizeof(cell))) > 0) - va_sc->height = (int)fdt32_to_cpu(cell); + if ((OF_getencprop(display, "panel_height", &cell, + sizeof(cell))) > 0) + va_sc->height = cell; } if (va_sc->width == 0) diff --git a/sys/arm/ti/am335x/am335x_musb.c b/sys/arm/ti/am335x/am335x_musb.c index c168493d086..8abcc89079b 100644 --- a/sys/arm/ti/am335x/am335x_musb.c +++ b/sys/arm/ti/am335x/am335x_musb.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/am335x/am335x_prcm.c b/sys/arm/ti/am335x/am335x_prcm.c index f7934328e35..7f65f0f6b4a 100644 --- a/sys/arm/ti/am335x/am335x_prcm.c +++ b/sys/arm/ti/am335x/am335x_prcm.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/am335x/am335x_pwmss.c b/sys/arm/ti/am335x/am335x_pwmss.c index dbc613e9190..814865d6b76 100644 --- a/sys/arm/ti/am335x/am335x_pwmss.c +++ b/sys/arm/ti/am335x/am335x_pwmss.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include #include diff --git a/sys/arm/ti/am335x/am335x_scm_padconf.c b/sys/arm/ti/am335x/am335x_scm_padconf.c index ebb65ddba2f..61917856325 100644 --- a/sys/arm/ti/am335x/am335x_scm_padconf.c +++ b/sys/arm/ti/am335x/am335x_scm_padconf.c @@ -293,7 +293,7 @@ const static struct ti_pinmux_padconf ti_padconf_devmap[] = { { .ballname = NULL }, }; -const struct ti_pinmux_device ti_pinmux_dev = { +const struct ti_pinmux_device ti_am335x_pinmux_dev = { .padconf_muxmode_mask = 0x7, .padconf_sate_mask = 0x78, .padstate = ti_padstate_devmap, diff --git a/sys/arm/ti/am335x/am335x_scm_padconf.h b/sys/arm/ti/am335x/am335x_scm_padconf.h index 2d0cd4b9cce..b1fa22bac6c 100644 --- a/sys/arm/ti/am335x/am335x_scm_padconf.h +++ b/sys/arm/ti/am335x/am335x_scm_padconf.h @@ -42,4 +42,6 @@ #define PADCONF_INPUT_PULLDOWN (RXACTIVE) #define PADCONF_INPUT_PULLUP_SLOW (PADCONF_INPUT_PULLUP | SLEWCTRL) +extern const struct ti_pinmux_device ti_am335x_pinmux_dev; + #endif /* AM335X_SCM_PADCONF_H */ diff --git a/sys/arm/ti/am335x/am335x_usbss.c b/sys/arm/ti/am335x/am335x_usbss.c index 6ddc562c5a9..8355faaa0f1 100644 --- a/sys/arm/ti/am335x/am335x_usbss.c +++ b/sys/arm/ti/am335x/am335x_usbss.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c index a7a7569dd98..79bfa0d44ca 100644 --- a/sys/arm/ti/cpsw/if_cpsw.c +++ b/sys/arm/ti/cpsw/if_cpsw.c @@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/ti/omap4/files.omap4 b/sys/arm/ti/omap4/files.omap4 index 1f331fc9066..ddae056d3fc 100644 --- a/sys/arm/ti/omap4/files.omap4 +++ b/sys/arm/ti/omap4/files.omap4 @@ -14,6 +14,8 @@ arm/ti/omap4/omap4_scm_padconf.c standard arm/ti/omap4/omap4_mp.c optional smp arm/ti/omap4/omap4_wugen.c standard +arm/ti/omap4/pandaboard/pandaboard.c standard + arm/ti/twl/twl.c optional twl arm/ti/twl/twl_vreg.c optional twl twl_vreg arm/ti/twl/twl_clks.c optional twl twl_clks diff --git a/sys/arm/ti/omap4/omap4_gpio.c b/sys/arm/ti/omap4/omap4_gpio.c index dd38f4a6a56..faf2339411b 100644 --- a/sys/arm/ti/omap4/omap4_gpio.c +++ b/sys/arm/ti/omap4/omap4_gpio.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -60,14 +59,14 @@ static struct ofw_compat_data compat_data[] = { static int omap4_gpio_probe(device_t dev) { - if (ti_chip() != CHIP_OMAP_4) - return (ENXIO); if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); + if (ti_chip() != CHIP_OMAP_4) + return (ENXIO); device_set_desc(dev, "TI OMAP4 General Purpose I/O (GPIO)"); diff --git a/sys/arm/ti/omap4/omap4_mp.c b/sys/arm/ti/omap4/omap4_mp.c index 055a8aad5f0..165cbcfb993 100644 --- a/sys/arm/ti/omap4/omap4_mp.c +++ b/sys/arm/ti/omap4/omap4_mp.c @@ -38,20 +38,24 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include void -platform_mp_setmaxid(void) +omap4_mp_setmaxid(platform_t plat) { + if (mp_ncpus != 0) + return; mp_maxid = 1; mp_ncpus = 2; } void -platform_mp_start_ap(void) +omap4_mp_start_ap(platform_t plat) { bus_addr_t scu_addr; diff --git a/sys/arm/ti/omap4/omap4_mp.h b/sys/arm/ti/omap4/omap4_mp.h new file mode 100644 index 00000000000..d4aa8df876b --- /dev/null +++ b/sys/arm/ti/omap4/omap4_mp.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2016 Olivier Houchard + * 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 _OMAP4_MP_H_ +#define _OMAP4_MP_H_ +void omap4_mp_setmaxid(platform_t plat); +void omap4_mp_start_ap(platform_t plat); +#endif /* _OMAP4_MP_H_ */ + diff --git a/sys/arm/ti/omap4/omap4_prcm_clks.c b/sys/arm/ti/omap4/omap4_prcm_clks.c index 782e7ac7111..d350121d7a4 100644 --- a/sys/arm/ti/omap4/omap4_prcm_clks.c +++ b/sys/arm/ti/omap4/omap4_prcm_clks.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/omap4/omap4_scm_padconf.c b/sys/arm/ti/omap4/omap4_scm_padconf.c index e43581e8db5..ada0e096f30 100644 --- a/sys/arm/ti/omap4/omap4_scm_padconf.c +++ b/sys/arm/ti/omap4/omap4_scm_padconf.c @@ -295,7 +295,7 @@ const static struct ti_pinmux_padconf ti_padconf_devmap[] = { { .ballname = NULL }, }; -const struct ti_pinmux_device ti_pinmux_dev = { +const struct ti_pinmux_device omap4_pinmux_dev = { .padconf_muxmode_mask = CONTROL_PADCONF_MUXMODE_MASK, .padconf_sate_mask = CONTROL_PADCONF_SATE_MASK, .padstate = ti_padstate_devmap, diff --git a/sys/arm/ti/omap4/omap4_scm_padconf.h b/sys/arm/ti/omap4/omap4_scm_padconf.h index b0c12fe595e..adee0a799cd 100644 --- a/sys/arm/ti/omap4/omap4_scm_padconf.h +++ b/sys/arm/ti/omap4/omap4_scm_padconf.h @@ -78,4 +78,6 @@ | CONTROL_PADCONF_OFF_PULL_ENABLE) #define PADCONF_PIN_OFF_WAKEUPENABLE CONTROL_PADCONF_WAKEUP_ENABLE +extern const struct ti_pinmux_device omap4_pinmux_dev; + #endif /* OMAP4_SCM_PADCONF_H */ diff --git a/sys/arm/ti/omap4/pandaboard/files.pandaboard b/sys/arm/ti/omap4/pandaboard/files.pandaboard deleted file mode 100644 index f658ffb3dc7..00000000000 --- a/sys/arm/ti/omap4/pandaboard/files.pandaboard +++ /dev/null @@ -1,3 +0,0 @@ -# $FreeBSD$ - -arm/ti/omap4/pandaboard/pandaboard.c standard diff --git a/sys/arm/ti/omap4/pandaboard/pandaboard.c b/sys/arm/ti/omap4/pandaboard/pandaboard.c index f557f736c56..94996f6ca10 100644 --- a/sys/arm/ti/omap4/pandaboard/pandaboard.c +++ b/sys/arm/ti/omap4/pandaboard/pandaboard.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include /* Registers in the SCRM that control the AUX clocks */ #define SCRM_ALTCLKSRC (0x110) @@ -111,8 +112,8 @@ __FBSDID("$FreeBSD$"); * RETURNS: * nothing. */ -static void -usb_hub_init(void) +void +pandaboard_usb_hub_init(void) { bus_space_handle_t scrm_addr, gpio1_addr, gpio2_addr, scm_addr; @@ -169,39 +170,3 @@ usb_hub_init(void) bus_space_unmap(fdtbus_bs_tag, gpio2_addr, OMAP44XX_GPIO2_SIZE); bus_space_unmap(fdtbus_bs_tag, scm_addr, OMAP44XX_SCM_PADCONF_SIZE); } - -/** - * board_init - initialises the pandaboard - * @dummy: ignored - * - * This function is called before any of the driver are initialised, which is - * annoying because it means we can't use the SCM, PRCM and GPIO modules which - * would really be useful. - * - * So we don't have: - * - any drivers - * - no interrupts - * - * What we do have: - * - virt/phys mappings from the devmap (see omap4.c) - * - - * - * - * So we are hamstrung without the useful drivers and we have to go back to - * direct register manupulation. Luckly we don't have to do to much, basically - * just setup the usb hub/ethernet. - * - */ -static void -board_init(void *dummy) -{ - /* Initialise the USB phy and hub */ - usb_hub_init(); - - /* - * XXX Board identification e.g. read out from FPGA or similar should - * go here - */ -} - -SYSINIT(board_init, SI_SUB_CPU, SI_ORDER_THIRD, board_init, NULL); diff --git a/sys/arm/ti/omap4/pandaboard/pandaboard.h b/sys/arm/ti/omap4/pandaboard/pandaboard.h new file mode 100644 index 00000000000..8d48d5b80ec --- /dev/null +++ b/sys/arm/ti/omap4/pandaboard/pandaboard.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2016 Olivier Houchard + * 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 _PANDABOARD_H_ +#define _PANDABOARD_H_ +void pandaboard_usb_hub_init(void); +#endif /* _OMAP4_MP_H_ */ + diff --git a/sys/arm/ti/omap4/pandaboard/std.pandaboard b/sys/arm/ti/omap4/pandaboard/std.pandaboard deleted file mode 100644 index 6a65f66bb13..00000000000 --- a/sys/arm/ti/omap4/pandaboard/std.pandaboard +++ /dev/null @@ -1,4 +0,0 @@ -# $FreeBSD$ - -include "../ti/omap4/std.omap4" -files "../ti/omap4/pandaboard/files.pandaboard" diff --git a/sys/arm/ti/ti_adc.c b/sys/arm/ti/ti_adc.c index 154cd78b630..2b49789f5ce 100644 --- a/sys/arm/ti/ti_adc.c +++ b/sys/arm/ti/ti_adc.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include #include @@ -767,14 +766,17 @@ ti_adc_attach(device_t dev) /* Read "tsc" node properties */ child = ofw_bus_find_child(node, "tsc"); if (child != 0 && OF_hasprop(child, "ti,wires")) { - if ((OF_getprop(child, "ti,wires", &cell, sizeof(cell))) > 0) - sc->sc_tsc_wires = fdt32_to_cpu(cell); - if ((OF_getprop(child, "ti,coordinate-readouts", &cell, sizeof(cell))) > 0) - sc->sc_coord_readouts = fdt32_to_cpu(cell); - if ((OF_getprop(child, "ti,x-plate-resistance", &cell, sizeof(cell))) > 0) - sc->sc_x_plate_resistance = fdt32_to_cpu(cell); - if ((OF_getprop(child, "ti,charge-delay", &cell, sizeof(cell))) > 0) - sc->sc_charge_delay = fdt32_to_cpu(cell); + if ((OF_getencprop(child, "ti,wires", &cell, sizeof(cell))) > 0) + sc->sc_tsc_wires = cell; + if ((OF_getencprop(child, "ti,coordinate-readouts", &cell, + sizeof(cell))) > 0) + sc->sc_coord_readouts = cell; + if ((OF_getencprop(child, "ti,x-plate-resistance", &cell, + sizeof(cell))) > 0) + sc->sc_x_plate_resistance = cell; + if ((OF_getencprop(child, "ti,charge-delay", &cell, + sizeof(cell))) > 0) + sc->sc_charge_delay = cell; nwire_configs = OF_getencprop_alloc(child, "ti,wire-config", sizeof(*wire_configs), (void **)&wire_configs); if (nwire_configs != sc->sc_tsc_wires) { diff --git a/sys/arm/ti/ti_cpuid.c b/sys/arm/ti/ti_cpuid.c index 7043d93b8cf..ca64c811dfa 100644 --- a/sys/arm/ti/ti_cpuid.c +++ b/sys/arm/ti/ti_cpuid.c @@ -43,6 +43,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include +#include + #include #include @@ -268,6 +272,12 @@ am335x_get_revision(void) static void ti_cpu_ident(void *dummy) { + phandle_t root; + + root = OF_finddevice("/"); + if (!ofw_bus_node_is_compatible(root, "ti,omap4") && + !ofw_bus_node_is_compatible(root, "ti,am33xx")) + return; switch(ti_chip()) { case CHIP_OMAP_4: omap4_get_revision(); diff --git a/sys/arm/ti/ti_cpuid.h b/sys/arm/ti/ti_cpuid.h index 86ac9828726..715f080e5ff 100644 --- a/sys/arm/ti/ti_cpuid.h +++ b/sys/arm/ti/ti_cpuid.h @@ -70,15 +70,12 @@ #define CHIP_OMAP_4 0 #define CHIP_AM335X 1 +extern int _ti_chip; + static __inline int ti_chip(void) { -#if defined(SOC_OMAP4) - return CHIP_OMAP_4; -#elif defined(SOC_TI_AM335X) - return CHIP_AM335X; -#else -# error Chip type not defined, ensure SOC_xxxx is defined -#endif + KASSERT(_ti_chip != -1, ("Can't determine TI Chip")); + return _ti_chip; } uint32_t ti_revision(void); diff --git a/sys/arm/ti/ti_edma3.c b/sys/arm/ti/ti_edma3.c index 080e7bddbe7..e12d82b3706 100644 --- a/sys/arm/ti/ti_edma3.c +++ b/sys/arm/ti/ti_edma3.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index fe2b5ff06bd..4f0f4f35aee 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -711,7 +710,8 @@ ti_gpio_detach(device_t dev) /* Disable all interrupts */ if (sc->sc_mem_res != NULL) ti_gpio_intr_clr(sc, 0xffffffff); - gpiobus_detach_bus(dev); + if (sc->sc_busdev != NULL) + gpiobus_detach_bus(dev); if (sc->sc_isrcs != NULL) ti_gpio_pic_detach(sc); /* Release the memory and IRQ resources. */ @@ -719,10 +719,12 @@ ti_gpio_detach(device_t dev) bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_hdl); } - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, - sc->sc_irq_res); - bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, - sc->sc_mem_res); + if (sc->sc_irq_res) + bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, + sc->sc_irq_res); + if (sc->sc_mem_res) + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, + sc->sc_mem_res); TI_GPIO_LOCK_DESTROY(sc); return (0); diff --git a/sys/arm/ti/ti_hwmods.c b/sys/arm/ti/ti_hwmods.c index e662d27e460..1dfb074a790 100644 --- a/sys/arm/ti/ti_hwmods.c +++ b/sys/arm/ti/ti_hwmods.c @@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/ti_machdep.c b/sys/arm/ti/ti_machdep.c index f9d83890ba8..23cfea021da 100644 --- a/sys/arm/ti/ti_machdep.c +++ b/sys/arm/ti/ti_machdep.c @@ -53,11 +53,33 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include "platform_if.h" void (*ti_cpu_reset)(void) = NULL; +int _ti_chip = -1; + +#if defined(SOC_OMAP4) +static int +omap4_attach(platform_t plat) +{ + _ti_chip = CHIP_OMAP_4; + return (0); +} +#endif + +#if defined(SOC_TI_AM335X) +static int +ti_am335x_attach(platform_t plat) +{ + _ti_chip = CHIP_AM335X; + return (0); +} +#endif + static vm_offset_t ti_lastaddr(platform_t plat) { @@ -106,17 +128,23 @@ ti_plat_cpu_reset(platform_t plat) #if defined(SOC_OMAP4) static platform_method_t omap4_methods[] = { + PLATFORMMETHOD(platform_attach, omap4_attach), PLATFORMMETHOD(platform_devmap_init, ti_omap4_devmap_init), PLATFORMMETHOD(platform_lastaddr, ti_lastaddr), PLATFORMMETHOD(platform_cpu_reset, ti_plat_cpu_reset), +#ifdef SMP + PLATFORMMETHOD(platform_mp_start_ap, omap4_mp_start_ap), + PLATFORMMETHOD(platform_mp_setmaxid, omap4_mp_setmaxid), +#endif PLATFORMMETHOD_END, }; -FDT_PLATFORM_DEF(omap4, "omap4", 0, "ti,omap4430", 0); +FDT_PLATFORM_DEF(omap4, "omap4", 0, "ti,omap4430", 200); #endif #if defined(SOC_TI_AM335X) static platform_method_t am335x_methods[] = { + PLATFORMMETHOD(platform_attach, ti_am335x_attach), PLATFORMMETHOD(platform_devmap_init, ti_am335x_devmap_init), PLATFORMMETHOD(platform_lastaddr, ti_lastaddr), PLATFORMMETHOD(platform_cpu_reset, ti_plat_cpu_reset), @@ -124,5 +152,5 @@ static platform_method_t am335x_methods[] = { PLATFORMMETHOD_END, }; -FDT_PLATFORM_DEF(am335x, "am335x", 0, "ti,am335x", 200); +FDT_PLATFORM_DEF(am335x, "am335x", 0, "ti,am33xx", 200); #endif diff --git a/sys/arm/ti/ti_mbox.c b/sys/arm/ti/ti_mbox.c index 9729ed40fc4..9747be13aac 100644 --- a/sys/arm/ti/ti_mbox.c +++ b/sys/arm/ti/ti_mbox.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/ti_pinmux.c b/sys/arm/ti/ti_pinmux.c index d3daf76eca7..e102d61611a 100644 --- a/sys/arm/ti/ti_pinmux.c +++ b/sys/arm/ti/ti_pinmux.c @@ -49,12 +49,14 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include #include #include +#include +#include +#include +#include #include "ti_pinmux.h" struct pincfg { @@ -86,7 +88,7 @@ static struct ti_pinmux_softc *ti_pinmux_sc; * files and is specific to the given SoC platform. Each entry in the array * corresponds to an individual pin. */ -extern const struct ti_pinmux_device ti_pinmux_dev; +static const struct ti_pinmux_device *ti_pinmux_dev; /** @@ -102,7 +104,7 @@ ti_pinmux_padconf_from_name(const char *ballname) { const struct ti_pinmux_padconf *padconf; - padconf = ti_pinmux_dev.padconf; + padconf = ti_pinmux_dev->padconf; while (padconf->ballname != NULL) { if (strcmp(ballname, padconf->ballname) == 0) return(padconf); @@ -135,7 +137,7 @@ ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc, uint16_t reg_val; /* populate the new value for the PADCONF register */ - reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask); + reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask); /* find the new mode requested */ for (mode = 0; mode < 8; mode++) { @@ -152,7 +154,7 @@ ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc, } /* set the mux mode */ - reg_val |= (uint16_t)(mode & ti_pinmux_dev.padconf_muxmode_mask); + reg_val |= (uint16_t)(mode & ti_pinmux_dev->padconf_muxmode_mask); if (bootverbose) device_printf(sc->sc_dev, "setting internal %x for %s\n", @@ -227,11 +229,11 @@ ti_pinmux_padconf_get(const char *padname, const char **muxmode, /* save the state */ if (state) - *state = (reg_val & ti_pinmux_dev.padconf_sate_mask); + *state = (reg_val & ti_pinmux_dev->padconf_sate_mask); /* save the mode */ if (muxmode) - *muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev.padconf_muxmode_mask)]; + *muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev->padconf_muxmode_mask)]; return (0); } @@ -260,7 +262,7 @@ ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state) return (ENXIO); /* find the gpio pin in the padconf array */ - padconf = ti_pinmux_dev.padconf; + padconf = ti_pinmux_dev->padconf; while (padconf->ballname != NULL) { if (padconf->gpio_pin == gpio) break; @@ -270,10 +272,10 @@ ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state) return (EINVAL); /* populate the new value for the PADCONF register */ - reg_val = (uint16_t)(state & ti_pinmux_dev.padconf_sate_mask); + reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask); /* set the mux mode */ - reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev.padconf_muxmode_mask); + reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev->padconf_muxmode_mask); /* write the register value (16-bit writes) */ ti_pinmux_write_2(ti_pinmux_sc, padconf->reg_off, reg_val); @@ -305,7 +307,7 @@ ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) return (ENXIO); /* find the gpio pin in the padconf array */ - padconf = ti_pinmux_dev.padconf; + padconf = ti_pinmux_dev->padconf; while (padconf->ballname != NULL) { if (padconf->gpio_pin == gpio) break; @@ -318,12 +320,12 @@ ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state) reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off); /* check to make sure the pins is configured as GPIO in the first state */ - if ((reg_val & ti_pinmux_dev.padconf_muxmode_mask) != padconf->gpio_mode) + if ((reg_val & ti_pinmux_dev->padconf_muxmode_mask) != padconf->gpio_mode) return (EINVAL); /* read and store the reset of the state, i.e. pull-up, pull-down, etc */ if (state) - *state = (reg_val & ti_pinmux_dev.padconf_sate_mask); + *state = (reg_val & ti_pinmux_dev->padconf_sate_mask); return (0); } @@ -382,6 +384,22 @@ ti_pinmux_probe(device_t dev) __func__); return (EEXIST); } + switch (ti_chip()) { +#ifdef SOC_OMAP4 + case CHIP_OMAP_4: + ti_pinmux_dev = &omap4_pinmux_dev; + break; +#endif +#ifdef SOC_TI_AM335X + case CHIP_AM335X: + ti_pinmux_dev = &ti_am335x_pinmux_dev; + break; +#endif + default: + printf("Unknown CPU in pinmux\n"); + return (ENXIO); + } + device_set_desc(dev, "TI Pinmux Module"); return (BUS_PROBE_DEFAULT); diff --git a/sys/arm/ti/ti_pruss.c b/sys/arm/ti/ti_pruss.c index cbf8050a57b..8ffb9e07899 100644 --- a/sys/arm/ti/ti_pruss.c +++ b/sys/arm/ti/ti_pruss.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/ti_scm.c b/sys/arm/ti/ti_scm.c index ae36a9b63a7..bc7861828f1 100644 --- a/sys/arm/ti/ti_scm.c +++ b/sys/arm/ti/ti_scm.c @@ -61,11 +61,10 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include #include #include +#include #include "ti_scm.h" diff --git a/sys/arm/ti/ti_sdhci.c b/sys/arm/ti/ti_sdhci.c index a24e6936a62..ed7f1e72dac 100644 --- a/sys/arm/ti/ti_sdhci.c +++ b/sys/arm/ti/ti_sdhci.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -506,10 +505,10 @@ ti_sdhci_attach(device_t dev) * See if we've got a GPIO-based write detect pin. This is not the * standard documented property for this, we added it in freebsd. */ - if ((OF_getprop(node, "mmchs-wp-gpio-pin", &prop, sizeof(prop))) <= 0) + if ((OF_getencprop(node, "mmchs-wp-gpio-pin", &prop, sizeof(prop))) <= 0) sc->wp_gpio_pin = 0xffffffff; else - sc->wp_gpio_pin = fdt32_to_cpu(prop); + sc->wp_gpio_pin = prop; if (sc->wp_gpio_pin != 0xffffffff) { sc->gpio_dev = devclass_get_device(devclass_find("gpio"), 0); diff --git a/sys/arm/ti/ti_sdma.c b/sys/arm/ti/ti_sdma.c index 7e5e9574e4c..6f3024153fa 100644 --- a/sys/arm/ti/ti_sdma.c +++ b/sys/arm/ti/ti_sdma.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/ti_spi.c b/sys/arm/ti/ti_spi.c index e35f365b5e1..75f3df77710 100644 --- a/sys/arm/ti/ti_spi.c +++ b/sys/arm/ti/ti_spi.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/ti/ti_wdt.c b/sys/arm/ti/ti_wdt.c index 2b51cc2d138..179b783029d 100644 --- a/sys/arm/ti/ti_wdt.c +++ b/sys/arm/ti/ti_wdt.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/ti/usb/omap_ehci.c b/sys/arm/ti/usb/omap_ehci.c index f7e2057b852..ea9a01dd8da 100644 --- a/sys/arm/ti/usb/omap_ehci.c +++ b/sys/arm/ti/usb/omap_ehci.c @@ -36,8 +36,8 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include +#include #include #include @@ -58,6 +58,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + /* EHCI */ #define OMAP_USBHOST_HCCAPBASE 0x0000 #define OMAP_USBHOST_HCSPARAMS 0x0004 @@ -259,7 +261,6 @@ omap_ehci_init(struct omap_ehci_softc *isc) static int omap_ehci_probe(device_t dev) { - if (!ofw_bus_status_okay(dev)) return (ENXIO); @@ -290,9 +291,22 @@ omap_ehci_attach(device_t dev) { struct omap_ehci_softc *isc = device_get_softc(dev); ehci_softc_t *sc = &isc->base; +#ifdef SOC_OMAP4 + phandle_t root; +#endif int err; int rid; +#ifdef SOC_OMAP4 + /* + * If we're running a Pandaboard, run Pandaboard-specific + * init code. + */ + root = OF_finddevice("/"); + if (ofw_bus_node_is_compatible(root, "ti,omap4-panda")) + pandaboard_usb_hub_init(); +#endif + /* initialise some bus fields */ sc->sc_bus.parent = dev; sc->sc_bus.devices = sc->sc_devices; diff --git a/sys/arm/ti/usb/omap_host.c b/sys/arm/ti/usb/omap_host.c index 326a5b39c38..0bc1118db58 100644 --- a/sys/arm/ti/usb/omap_host.c +++ b/sys/arm/ti/usb/omap_host.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/ti/usb/omap_tll.c b/sys/arm/ti/usb/omap_tll.c index 9bcb7d660a3..eb3e246a61d 100644 --- a/sys/arm/ti/usb/omap_tll.c +++ b/sys/arm/ti/usb/omap_tll.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/versatile/pl050.c b/sys/arm/versatile/pl050.c index c5d8a61372c..51d22afd340 100644 --- a/sys/arm/versatile/pl050.c +++ b/sys/arm/versatile/pl050.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/versatile/sp804.c b/sys/arm/versatile/sp804.c index de05700dd1c..894415ba11c 100644 --- a/sys/arm/versatile/sp804.c +++ b/sys/arm/versatile/sp804.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -223,8 +222,8 @@ sp804_timer_attach(device_t dev) sc->sysclk_freq = DEFAULT_FREQUENCY; /* Get the base clock frequency */ node = ofw_bus_get_node(dev); - if ((OF_getprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) { - sc->sysclk_freq = fdt32_to_cpu(clock); + if ((OF_getencprop(node, "clock-frequency", &clock, sizeof(clock))) > 0) { + sc->sysclk_freq = clock; } /* Setup and enable the timer */ diff --git a/sys/arm/versatile/versatile_clcd.c b/sys/arm/versatile/versatile_clcd.c index 76c6c63d8c5..93f71d53f03 100644 --- a/sys/arm/versatile/versatile_clcd.c +++ b/sys/arm/versatile/versatile_clcd.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/versatile/versatile_common.c b/sys/arm/versatile/versatile_common.c index 983b3ce018b..54d6192eb08 100644 --- a/sys/arm/versatile/versatile_common.c +++ b/sys/arm/versatile/versatile_common.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -52,7 +53,7 @@ fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, int *pol) { - if (!fdt_is_compatible(node, "arm,versatile-vic")) + if (!ofw_bus_node_is_compatible(node, "arm,versatile-vic")) return (ENXIO); *interrupt = fdt32_to_cpu(intr[0]); diff --git a/sys/arm/versatile/versatile_machdep.c b/sys/arm/versatile/versatile_machdep.c index a0c97eeed15..2ce2faf969d 100644 --- a/sys/arm/versatile/versatile_machdep.c +++ b/sys/arm/versatile/versatile_machdep.c @@ -51,8 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - /* Start of address space used for bootstrap map */ #define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000 diff --git a/sys/arm/versatile/versatile_pci.c b/sys/arm/versatile/versatile_pci.c index 0bc49264c7e..7db737cc067 100644 --- a/sys/arm/versatile/versatile_pci.c +++ b/sys/arm/versatile/versatile_pci.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include "pcib_if.h" -#include #include #include #include diff --git a/sys/arm/versatile/versatile_sic.c b/sys/arm/versatile/versatile_sic.c index 99ffb27a72d..d695bbfa754 100644 --- a/sys/arm/versatile/versatile_sic.c +++ b/sys/arm/versatile/versatile_sic.c @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/versatile/versatile_timer.c b/sys/arm/versatile/versatile_timer.c index c5f6def30c6..b6f508393c8 100644 --- a/sys/arm/versatile/versatile_timer.c +++ b/sys/arm/versatile/versatile_timer.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/xilinx/zy7_devcfg.c b/sys/arm/xilinx/zy7_devcfg.c index 385afd16a33..74e1cfe8752 100644 --- a/sys/arm/xilinx/zy7_devcfg.c +++ b/sys/arm/xilinx/zy7_devcfg.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/xilinx/zy7_ehci.c b/sys/arm/xilinx/zy7_ehci.c index 6468faa7ac1..f6e34f77449 100644 --- a/sys/arm/xilinx/zy7_ehci.c +++ b/sys/arm/xilinx/zy7_ehci.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/arm/xilinx/zy7_gpio.c b/sys/arm/xilinx/zy7_gpio.c index 25d22f87e4d..a51d60fa352 100644 --- a/sys/arm/xilinx/zy7_gpio.c +++ b/sys/arm/xilinx/zy7_gpio.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/xilinx/zy7_machdep.c b/sys/arm/xilinx/zy7_machdep.c index 771503d7dd3..472f70c6473 100644 --- a/sys/arm/xilinx/zy7_machdep.c +++ b/sys/arm/xilinx/zy7_machdep.c @@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include #include @@ -92,29 +90,6 @@ platform_devmap_init(void) return (0); } - -#ifndef INTRNG -static int -fdt_gic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, - int *pol) -{ - - if (!fdt_is_compatible(node, "arm,gic")) - return (ENXIO); - - *interrupt = fdt32_to_cpu(intr[0]); - *trig = INTR_TRIGGER_CONFORM; - *pol = INTR_POLARITY_CONFORM; - - return (0); -} - -fdt_pic_decode_t fdt_pic_table[] = { - &fdt_gic_decode_ic, - NULL -}; -#endif - void cpu_reset() { diff --git a/sys/arm/xilinx/zy7_slcr.c b/sys/arm/xilinx/zy7_slcr.c index c99d5b0b5ae..bd0311c3320 100644 --- a/sys/arm/xilinx/zy7_slcr.c +++ b/sys/arm/xilinx/zy7_slcr.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -621,8 +620,8 @@ zy7_slcr_attach(device_t dev) /* Derive PLL frequencies from PS_CLK. */ node = ofw_bus_get_node(dev); - if (OF_getprop(node, "clock-frequency", &cell, sizeof(cell)) > 0) - ps_clk_frequency = fdt32_to_cpu(cell); + if (OF_getencprop(node, "clock-frequency", &cell, sizeof(cell)) > 0) + ps_clk_frequency = cell; else ps_clk_frequency = ZYNQ_DEFAULT_PS_CLK_FREQUENCY; diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC index 4502dc8fb1b..9b1c42e634f 100644 --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -121,6 +121,7 @@ device em # Intel PRO/1000 Gigabit Ethernet Family device igb # Intel PRO/1000 PCIE Server Gigabit Family device ix # Intel 10Gb Ethernet Family device msk # Marvell/SysKonnect Yukon II Gigabit Ethernet +device smc # SMSC LAN91C111 device vnic # Cavium ThunderX NIC device al_eth # Annapurna Alpine Ethernet NIC diff --git a/sys/boot/common/commands.c b/sys/boot/common/commands.c index 9f1d9590e79..2b0e8cbe0ac 100644 --- a/sys/boot/common/commands.c +++ b/sys/boot/common/commands.c @@ -497,10 +497,8 @@ command_lsdev(int argc, char *argv[]) pager_open(); for (i = 0; devsw[i] != NULL; i++) { if (devsw[i]->dv_print != NULL){ - sprintf(line, "%s devices:\n", devsw[i]->dv_name); - if (pager_output(line)) - break; - devsw[i]->dv_print(verbose); + if (devsw[i]->dv_print(verbose)) + break; } else { sprintf(line, "%s: (unknown)\n", devsw[i]->dv_name); if (pager_output(line)) diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c index 7b178af0190..76abb2eb50b 100644 --- a/sys/boot/common/dev_net.c +++ b/sys/boot/common/dev_net.c @@ -332,11 +332,18 @@ net_print(int verbose) int i, d, cnt; int ret = 0; + if (netif_drivers[0] == NULL) + return (ret); + + printf("%s devices:", netdev.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + cnt = 0; for (d = 0; netif_drivers[d]; d++) { drv = netif_drivers[d]; for (i = 0; i < drv->netif_nifs; i++) { - printf("\t%s%d:", "net", cnt++); + printf("\t%s%d:", netdev.dv_name, cnt++); if (verbose) { printf(" (%s%d)", drv->netif_bname, drv->netif_ifs[i].dif_unit); diff --git a/sys/boot/common/install.c b/sys/boot/common/install.c index 36e7c6484dc..8c19066894a 100644 --- a/sys/boot/common/install.c +++ b/sys/boot/common/install.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" -extern struct in_addr rootip; extern struct in_addr servip; extern int pkgfs_init(const char *, struct fs_ops *); @@ -50,6 +49,7 @@ COMMAND_SET(install, "install", "install software package", command_install); static char *inst_kernel; static char **inst_modules; static char *inst_rootfs; +static char *inst_loader_rc; static int setpath(char **what, char *val) @@ -146,6 +146,8 @@ read_metatags(int fd) error = setmultipath(&inst_modules, val); else if (strcmp(tag, "ROOTFS") == 0) error = setpath(&inst_rootfs, val); + else if (strcmp(tag, "LOADER_RC") == 0) + error = setpath(&inst_loader_rc, val); tag = p; } @@ -173,6 +175,10 @@ cleanup(void) free(inst_rootfs); inst_rootfs = NULL; } + if (inst_loader_rc != NULL) { + free(inst_loader_rc); + inst_loader_rc = NULL; + } pkgfs_cleanup(); } @@ -275,6 +281,16 @@ install(char *pkgname) goto fail; } + /* If there is a loader.rc in the package, execute it */ + s = (inst_loader_rc == NULL) ? "/loader.rc" : inst_loader_rc; + fd = open(s, O_RDONLY); + if (fd != -1) { + close(fd); + error = include(s); + if (error == CMD_ERROR) + goto fail; + } + i = 0; while (inst_modules != NULL && inst_modules[i] != NULL) { error = mod_loadkld(inst_modules[i], 0, NULL); @@ -286,7 +302,7 @@ install(char *pkgname) } s = (inst_rootfs == NULL) ? "/install.iso" : inst_rootfs; - if (file_loadraw(s, "mfs_root") == NULL) { + if (file_loadraw(s, "mfs_root", 1) == NULL) { error = errno; command_errmsg = "cannot load root file system"; goto fail; diff --git a/sys/boot/common/md.c b/sys/boot/common/md.c index e5e8a4850dc..f4469329ca4 100644 --- a/sys/boot/common/md.c +++ b/sys/boot/common/md.c @@ -63,7 +63,7 @@ static int md_init(void); static int md_strategy(void *, int, daddr_t, size_t, size_t, char *, size_t *); static int md_open(struct open_file *, ...); static int md_close(struct open_file *); -static void md_print(int); +static int md_print(int); struct devsw md_dev = { "md", @@ -143,9 +143,14 @@ md_close(struct open_file *f) return ((dev->d_unit != 0) ? ENXIO : 0); } -static void +static int md_print(int verbose) { - printf("MD (%u bytes)\n", MD_IMAGE_SIZE); + printf("%s devices:", md_dev.dv_name); + if (pager_output("\n") != 0) + return (1); + + printf("MD (%u bytes)", MD_IMAGE_SIZE); + return (pager_output("\n")); } diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index 8d7db1f63f1..1207088d868 100644 --- a/sys/boot/efi/libefi/efinet.c +++ b/sys/boot/efi/libefi/efinet.c @@ -353,6 +353,10 @@ efinet_dev_print(int verbose) EFI_HANDLE h; int unit, ret = 0; + printf("%s devices:", efinet_dev.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (unit = 0, h = efi_find_handle(&efinet_dev, 0); h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) { printf(" %s%d:", efinet_dev.dv_name, unit); diff --git a/sys/boot/efi/libefi/efipart.c b/sys/boot/efi/libefi/efipart.c index cba94de9d27..5a993812bce 100644 --- a/sys/boot/efi/libefi/efipart.c +++ b/sys/boot/efi/libefi/efipart.c @@ -172,6 +172,10 @@ efipart_print(int verbose) u_int unit; int ret = 0; + printf("%s devices:", efipart_dev.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (unit = 0, h = efi_find_handle(&efipart_dev, 0); h != NULL; h = efi_find_handle(&efipart_dev, ++unit)) { snprintf(line, sizeof(line), " %s%d:", diff --git a/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi b/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi index 2567be51da6..c83d6a2c1d9 100644 --- a/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi +++ b/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi @@ -28,25 +28,11 @@ / { clocks { - pll3: clk@01c20010 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-pll3-clk"; - reg = <0x01c20010 0x4>; - clock-output-names = "pll3-1x", "pll3-2x"; - }; - - pll7: clk@01c20030 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-pll3-clk"; - reg = <0x01c20030 0x4>; - clock-output-names = "pll7-1x", "pll7-2x"; - }; - hdmi_clk: clk@01c20150 { #clock-cells = <0>; compatible = "allwinner,sun4i-a10-hdmi-clk"; reg = <0x01c20150 0x4>; - clocks = <&pll3 0>, <&pll7 0>, <&pll3 1>, <&pll7 1>; + clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>; clock-output-names = "hdmi"; }; @@ -55,7 +41,7 @@ #reset-cells = <0>; compatible = "allwinner,sun4i-a10-lcd-ch0-clk"; reg = <0x01c20118 0x4>; - clocks = <&pll3 0>, <&pll7 0>, <&pll3 1>, <&pll6 2>; + clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll6 2>; clock-output-names = "lcd0_ch0"; }; @@ -63,7 +49,7 @@ #clock-cells = <1>; compatible = "allwinner,sun4i-a10-lcd-ch1-clk"; reg = <0x01c2012c 0x4>; - clocks = <&pll3 0>, <&pll7 0>, <&pll3 1>, <&pll7 1>; + clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>; clock-output-names = "lcd0_ch1_sclk1", "lcd0_ch1_sclk2"; }; @@ -73,7 +59,7 @@ #reset-cells = <0>; compatible = "allwinner,sun4i-a10-de-be-clk"; reg = <0x01c20104 0x4>; - clocks = <&pll3 0>, <&pll7 0>, <&pll5 1>; + clocks = <&pll3>, <&pll7>, <&pll5 1>; clock-output-names = "de_be0"; }; }; diff --git a/sys/boot/fdt/dts/powerpc/p2041rdb.dts b/sys/boot/fdt/dts/powerpc/p2041rdb.dts index aa5af072e76..3ce2e60096c 100644 --- a/sys/boot/fdt/dts/powerpc/p2041rdb.dts +++ b/sys/boot/fdt/dts/powerpc/p2041rdb.dts @@ -442,47 +442,6 @@ }; }; - fsl,dpaa { - compatible = "fsl,p2041-dpaa", "fsl,dpaa"; - - ethernet@0 { - compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet0>; - status = "okay"; - }; - ethernet@1 { - compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet1>; - status = "okay"; - }; - ethernet@2 { - compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet2>; - status = "okay"; - }; - ethernet@3 { - compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet3>; - status = "okay"; - }; - ethernet@4 { - compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet4>; - status = "okay"; - }; - ethernet@5 { - compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet5>; - status = "okay"; - }; - }; - chosen { stdin = "serial0"; stdout = "serial0"; diff --git a/sys/boot/fdt/dts/powerpc/p2041si.dtsi b/sys/boot/fdt/dts/powerpc/p2041si.dtsi index 9db01fa62ca..41eb1dd7452 100644 --- a/sys/boot/fdt/dts/powerpc/p2041si.dtsi +++ b/sys/boot/fdt/dts/powerpc/p2041si.dtsi @@ -208,7 +208,7 @@ bman-portals@ff4000000 { #address-cells = <0x1>; #size-cells = <0x1>; - compatible = "bman-portals"; + compatible = "fsl,bman-portals"; ranges = <0x0 0xf 0xfde00000 0x200000>; bman-portal@0 { cell-index = <0x0>; @@ -281,7 +281,7 @@ qman-portals@ff4200000 { #address-cells = <0x1>; #size-cells = <0x1>; - compatible = "qman-portals"; + compatible = "fsl,qman-portals"; ranges = <0x0 0xf 0xfdc00000 0x200000>; qportal0: qman-portal@0 { cell-index = <0x0>; @@ -913,8 +913,8 @@ pme: pme@316000 { compatible = "fsl,pme"; reg = <0x316000 0x10000>; - /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */ - /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */ + /* "fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */ + /* "fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */ interrupts = <16 2 1 5>; }; @@ -923,16 +923,16 @@ reg = <0x318000 0x1000>; interrupts = <16 2 1 3>; /* Commented out, use default allocation */ - /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */ - /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */ + /* "fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */ + /* "fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */ }; bman: bman@31a000 { compatible = "fsl,p2041-bman", "fsl,bman"; reg = <0x31a000 0x1000>; interrupts = <16 2 1 2>; - /* Same as fsl,qman-*, use default allocation */ - /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */ + /* Same as "fsl,qman-*, use default allocation */ + /* "fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */ }; fman0: fman@400000 { @@ -983,27 +983,27 @@ fman0_rx0: port@88000 { cell-index = <0>; - compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x88000 0x1000>; }; fman0_rx1: port@89000 { cell-index = <1>; - compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x89000 0x1000>; }; fman0_rx2: port@8a000 { cell-index = <2>; - compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8a000 0x1000>; }; fman0_rx3: port@8b000 { cell-index = <3>; - compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8b000 0x1000>; }; fman0_rx4: port@8c000 { cell-index = <4>; - compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8c000 0x1000>; }; fman0_rx5: port@90000 { @@ -1020,31 +1020,31 @@ }; fman0_tx0: port@a8000 { cell-index = <0>; - compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xa8000 0x1000>; fsl,qman-channel-id = <0x41>; }; fman0_tx1: port@a9000 { cell-index = <1>; - compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xa9000 0x1000>; fsl,qman-channel-id = <0x42>; }; fman0_tx2: port@aa000 { cell-index = <2>; - compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xaa000 0x1000>; fsl,qman-channel-id = <0x43>; }; fman0_tx3: port@ab000 { cell-index = <3>; - compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xab000 0x1000>; fsl,qman-channel-id = <0x44>; }; fman0_tx4: port@ac000 { cell-index = <4>; - compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xac000 0x1000>; fsl,qman-channel-id = <0x45>; }; @@ -1093,7 +1093,7 @@ enet0: ethernet@e0000 { cell-index = <0>; - compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe0000 0x1000>; fsl,port-handles = <&fman0_rx0 &fman0_tx0>; }; @@ -1108,7 +1108,7 @@ enet1: ethernet@e2000 { cell-index = <1>; - compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe2000 0x1000>; fsl,port-handles = <&fman0_rx1 &fman0_tx1>; }; @@ -1123,7 +1123,7 @@ enet2: ethernet@e4000 { cell-index = <2>; - compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe4000 0x1000>; fsl,port-handles = <&fman0_rx2 &fman0_tx2>; }; @@ -1138,7 +1138,7 @@ enet3: ethernet@e6000 { cell-index = <3>; - compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe6000 0x1000>; fsl,port-handles = <&fman0_rx3 &fman0_tx3>; }; @@ -1153,7 +1153,7 @@ enet4: ethernet@e8000 { cell-index = <4>; - compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe8000 0x1000>; fsl,port-handles = <&fman0_rx4 &fman0_tx4>; }; @@ -1168,7 +1168,7 @@ enet5: ethernet@f0000 { cell-index = <0>; - compatible = "fsl,p2041-fman-10g-mac", "fsl,fman-10g-mac"; + compatible = "fsl,p2041-fman-10g-mac", "fsl,fman-10g-mac", "fsl,fman-xgec"; reg = <0xf0000 0x1000>; fsl,port-handles = <&fman0_rx5 &fman0_tx5>; }; diff --git a/sys/boot/fdt/dts/powerpc/p3041ds.dts b/sys/boot/fdt/dts/powerpc/p3041ds.dts index 70787e43276..bcc9ff3112b 100644 --- a/sys/boot/fdt/dts/powerpc/p3041ds.dts +++ b/sys/boot/fdt/dts/powerpc/p3041ds.dts @@ -539,47 +539,6 @@ }; }; - fsl,dpaa { - compatible = "fsl,p3041-dpaa", "fsl,dpaa"; - - ethernet@0 { - compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet0>; - status="okay"; - }; - ethernet@1 { - compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet1>; - status = "disabled"; - }; - ethernet@2 { - compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet2>; - status = "disabled"; - }; - ethernet@3 { - compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet3>; - status = "disabled"; - }; - ethernet@4 { - compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet4>; - status = "okay"; - }; - ethernet@5 { - compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet5>; - status = "disabled"; - }; - }; - chosen { stdin = "serial0"; stdout = "serial0"; diff --git a/sys/boot/fdt/dts/powerpc/p3041si.dtsi b/sys/boot/fdt/dts/powerpc/p3041si.dtsi index 3335e48d470..368cd6272bf 100644 --- a/sys/boot/fdt/dts/powerpc/p3041si.dtsi +++ b/sys/boot/fdt/dts/powerpc/p3041si.dtsi @@ -209,7 +209,7 @@ bman-portals@ff4000000 { #address-cells = <0x1>; #size-cells = <0x1>; - compatible = "bman-portals"; + compatible = "fsl,bman-portals"; ranges = <0x0 0xf 0xfde00000 0x200000>; bman-portal@0 { cell-index = <0x0>; @@ -282,7 +282,7 @@ qman-portals@ff4200000 { #address-cells = <0x1>; #size-cells = <0x1>; - compatible = "qman-portals"; + compatible = "fsl,qman-portals"; ranges = <0x0 0xf 0xfdc00000 0x200000>; qportal0: qman-portal@0 { cell-index = <0x0>; @@ -915,8 +915,8 @@ pme: pme@316000 { compatible = "fsl,pme"; reg = <0x316000 0x10000>; - /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */ - /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */ + /* "fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */ + /* "fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */ interrupts = <16 2 1 5>; }; @@ -925,16 +925,16 @@ reg = <0x318000 0x1000>; interrupts = <16 2 1 3>; /* Commented out, use default allocation */ - /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */ - /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */ + /* "fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */ + /* "fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */ }; bman: bman@31a000 { compatible = "fsl,p3041-bman", "fsl,bman"; reg = <0x31a000 0x1000>; interrupts = <16 2 1 2>; - /* Same as fsl,qman-*, use default allocation */ - /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */ + /* Same as "fsl,qman-*, use default allocation */ + /* "fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */ }; fman0: fman@400000 { @@ -985,27 +985,27 @@ fman0_rx0: port@88000 { cell-index = <0>; - compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x88000 0x1000>; }; fman0_rx1: port@89000 { cell-index = <1>; - compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x89000 0x1000>; }; fman0_rx2: port@8a000 { cell-index = <2>; - compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8a000 0x1000>; }; fman0_rx3: port@8b000 { cell-index = <3>; - compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8b000 0x1000>; }; fman0_rx4: port@8c000 { cell-index = <4>; - compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8c000 0x1000>; }; fman0_rx5: port@90000 { @@ -1022,31 +1022,31 @@ }; fman0_tx0: port@a8000 { cell-index = <0>; - compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xa8000 0x1000>; fsl,qman-channel-id = <0x41>; }; fman0_tx1: port@a9000 { cell-index = <1>; - compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xa9000 0x1000>; fsl,qman-channel-id = <0x42>; }; fman0_tx2: port@aa000 { cell-index = <2>; - compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xaa000 0x1000>; fsl,qman-channel-id = <0x43>; }; fman0_tx3: port@ab000 { cell-index = <3>; - compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xab000 0x1000>; fsl,qman-channel-id = <0x44>; }; fman0_tx4: port@ac000 { cell-index = <4>; - compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xac000 0x1000>; fsl,qman-channel-id = <0x45>; }; @@ -1095,7 +1095,8 @@ enet0: ethernet@e0000 { cell-index = <0>; - compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p3041-fman-1g-mac", + "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe0000 0x1000>; fsl,port-handles = <&fman0_rx0 &fman0_tx0>; ptimer-handle = <&ptp_timer0>; @@ -1111,7 +1112,8 @@ enet1: ethernet@e2000 { cell-index = <1>; - compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p3041-fman-1g-mac", + "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe2000 0x1000>; fsl,port-handles = <&fman0_rx1 &fman0_tx1>; ptimer-handle = <&ptp_timer0>; @@ -1127,7 +1129,8 @@ enet2: ethernet@e4000 { cell-index = <2>; - compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p3041-fman-1g-mac", + "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe4000 0x1000>; fsl,port-handles = <&fman0_rx2 &fman0_tx2>; ptimer-handle = <&ptp_timer0>; @@ -1143,7 +1146,8 @@ enet3: ethernet@e6000 { cell-index = <3>; - compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p3041-fman-1g-mac", + "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe6000 0x1000>; fsl,port-handles = <&fman0_rx3 &fman0_tx3>; }; @@ -1158,7 +1162,8 @@ enet4: ethernet@e8000 { cell-index = <4>; - compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p3041-fman-1g-mac", + "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe8000 0x1000>; fsl,port-handles = <&fman0_rx4 &fman0_tx4>; ptimer-handle = <&ptp_timer0>; @@ -1174,7 +1179,8 @@ enet5: ethernet@f0000 { cell-index = <0>; - compatible = "fsl,p3041-fman-10g-mac", "fsl,fman-10g-mac"; + compatible = "fsl,p3041-fman-10g-mac", + "fsl,fman-10g-mac", "fsl,fman-xgec"; reg = <0xf0000 0x1000>; fsl,port-handles = <&fman0_rx5 &fman0_tx5>; }; diff --git a/sys/boot/fdt/dts/powerpc/p5020ds.dts b/sys/boot/fdt/dts/powerpc/p5020ds.dts index cb070457924..3e0d92fbd83 100644 --- a/sys/boot/fdt/dts/powerpc/p5020ds.dts +++ b/sys/boot/fdt/dts/powerpc/p5020ds.dts @@ -535,47 +535,6 @@ }; }; - fsl,dpaa { - compatible = "fsl,p5020-dpaa", "fsl,dpaa"; - - ethernet@0 { - compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet0>; - status = "okay"; - }; - ethernet@1 { - compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet1>; - status = "disabled"; - }; - ethernet@2 { - compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet2>; - status = "disabled"; - }; - ethernet@3 { - compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet3>; - status = "disabled"; - }; - ethernet@4 { - compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet4>; - status = "okay"; - }; - ethernet@5 { - compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet"; - fsl,qman-channel = <&qpool1>; - fsl,fman-mac = <&enet5>; - status = "disabled"; - }; - }; - chosen { stdin = "serial0"; stdout = "serial0"; diff --git a/sys/boot/fdt/dts/powerpc/p5020si.dtsi b/sys/boot/fdt/dts/powerpc/p5020si.dtsi index 27699cbc7e0..afed942a2b9 100644 --- a/sys/boot/fdt/dts/powerpc/p5020si.dtsi +++ b/sys/boot/fdt/dts/powerpc/p5020si.dtsi @@ -194,7 +194,7 @@ bman-portals@ff4000000 { #address-cells = <0x1>; #size-cells = <0x1>; - compatible = "bman-portals"; + compatible = "fsl,bman-portals"; ranges = <0x0 0xf 0xfde00000 0x200000>; bman-portal@0 { cell-index = <0x0>; @@ -267,7 +267,7 @@ qman-portals@ff4200000 { #address-cells = <0x1>; #size-cells = <0x1>; - compatible = "qman-portals"; + compatible = "fsl,qman-portals"; ranges = <0x0 0xf 0xfdc00000 0x200000>; qportal0: qman-portal@0 { cell-index = <0x0>; @@ -960,8 +960,8 @@ pme: pme@316000 { compatible = "fsl,pme"; reg = <0x316000 0x10000>; - /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */ - /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */ + /* "fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */ + /* "fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */ interrupts = <16 2 1 5>; }; @@ -970,16 +970,16 @@ reg = <0x318000 0x1000>; interrupts = <16 2 1 3>; /* Commented out, use default allocation */ - /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */ - /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */ + /* "fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */ + /* "fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */ }; bman: bman@31a000 { compatible = "fsl,p5020-bman", "fsl,bman"; reg = <0x31a000 0x1000>; interrupts = <16 2 1 2>; - /* Same as fsl,qman-*, use default allocation */ - /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */ + /* Same as "fsl,qman-*, use default allocation */ + /* "fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */ }; fman0: fman@400000 { @@ -1030,27 +1030,27 @@ fman0_rx0: port@88000 { cell-index = <0>; - compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x88000 0x1000>; }; fman0_rx1: port@89000 { cell-index = <1>; - compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x89000 0x1000>; }; fman0_rx2: port@8a000 { cell-index = <2>; - compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8a000 0x1000>; }; fman0_rx3: port@8b000 { cell-index = <3>; - compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8b000 0x1000>; }; fman0_rx4: port@8c000 { cell-index = <4>; - compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx"; + compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx", "fsl,fman-v2-port-rx"; reg = <0x8c000 0x1000>; }; fman0_rx5: port@90000 { @@ -1067,31 +1067,31 @@ }; fman0_tx0: port@a8000 { cell-index = <0>; - compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xa8000 0x1000>; fsl,qman-channel-id = <0x41>; }; fman0_tx1: port@a9000 { cell-index = <1>; - compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xa9000 0x1000>; fsl,qman-channel-id = <0x42>; }; fman0_tx2: port@aa000 { cell-index = <2>; - compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xaa000 0x1000>; fsl,qman-channel-id = <0x43>; }; fman0_tx3: port@ab000 { cell-index = <3>; - compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xab000 0x1000>; fsl,qman-channel-id = <0x44>; }; fman0_tx4: port@ac000 { cell-index = <4>; - compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx"; + compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx", "fsl,fman-v2-port-tx"; reg = <0xac000 0x1000>; fsl,qman-channel-id = <0x45>; }; @@ -1140,7 +1140,7 @@ enet0: ethernet@e0000 { cell-index = <0>; - compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe0000 0x1000>; fsl,port-handles = <&fman0_rx0 &fman0_tx0>; ptimer-handle = <&ptp_timer0>; @@ -1156,7 +1156,7 @@ enet1: ethernet@e2000 { cell-index = <1>; - compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe2000 0x1000>; fsl,port-handles = <&fman0_rx1 &fman0_tx1>; ptimer-handle = <&ptp_timer0>; @@ -1172,7 +1172,7 @@ enet2: ethernet@e4000 { cell-index = <2>; - compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe4000 0x1000>; fsl,port-handles = <&fman0_rx2 &fman0_tx2>; ptimer-handle = <&ptp_timer0>; @@ -1188,7 +1188,7 @@ enet3: ethernet@e6000 { cell-index = <3>; - compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe6000 0x1000>; fsl,port-handles = <&fman0_rx3 &fman0_tx3>; ptimer-handle = <&ptp_timer0>; @@ -1204,7 +1204,7 @@ enet4: ethernet@e8000 { cell-index = <4>; - compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac"; + compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac", "fsl,fman-dtsec"; reg = <0xe8000 0x1000>; fsl,port-handles = <&fman0_rx4 &fman0_tx4>; ptimer-handle = <&ptp_timer0>; @@ -1220,7 +1220,7 @@ enet5: ethernet@f0000 { cell-index = <0>; - compatible = "fsl,p5020-fman-10g-mac", "fsl,fman-10g-mac"; + compatible = "fsl,p5020-fman-10g-mac", "fsl,fman-10g-mac", "fsl,fman-xgec"; reg = <0xf0000 0x1000>; fsl,port-handles = <&fman0_rx5 &fman0_tx5>; }; diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf index 69a4fcde213..d17d33580db 100644 --- a/sys/boot/forth/loader.conf +++ b/sys/boot/forth/loader.conf @@ -312,6 +312,7 @@ if_axe_load="NO" # ASIX Electronics AX88172 USB Ethernet if_bce_load="NO" # Broadcom NetXtreme II Gigabit Ethernet if_bfe_load="NO" # Broadcom BCM4401 if_bge_load="NO" # Broadcom BCM570x PCI Gigabit Ethernet +if_bnxt_load="NO" # Broadcom NetXtreme-C/NetXtreme-E if_bridge_load="NO" # if_bridge(4) devices if_bwi_load="NO" # Broadcom BCM53xx IEEE 802.11b/g wireness NICs if_bwn_load="NO" # Broadcom BCM43xx IEEE 802.11 wireless NICs diff --git a/sys/boot/i386/libfirewire/firewire.c b/sys/boot/i386/libfirewire/firewire.c index fea61f3bad9..f2975944820 100644 --- a/sys/boot/i386/libfirewire/firewire.c +++ b/sys/boot/i386/libfirewire/firewire.c @@ -155,6 +155,10 @@ fw_print(int verbose) int i, ret = 0; struct fwohci_softc *sc; + printf("%s devices:", fwohci.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (i = 0; i < MAX_OHCI; i ++) { sc = &fwinfo[i]; if (sc->state == FWOHCI_STATE_DEAD) diff --git a/sys/boot/i386/libi386/bioscd.c b/sys/boot/i386/libi386/bioscd.c index 776ddfa65fe..37cd6d2aa4c 100644 --- a/sys/boot/i386/libi386/bioscd.c +++ b/sys/boot/i386/libi386/bioscd.c @@ -183,6 +183,13 @@ bc_print(int verbose) char line[80]; int i, ret = 0; + if (nbcinfo == 0) + return (0); + + printf("%s devices:", bioscd.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (i = 0; i < nbcinfo; i++) { snprintf(line, sizeof(line), " cd%d: Device 0x%x\n", i, bcinfo[i].bc_sp.sp_devicespec); diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c index 0af0c2a4c81..fa59234e0d3 100644 --- a/sys/boot/i386/libi386/biosdisk.c +++ b/sys/boot/i386/libi386/biosdisk.c @@ -328,6 +328,13 @@ bd_print(int verbose) struct disk_devdesc dev; int i, ret = 0; + if (nbdinfo == 0) + return (0); + + printf("%s devices:", biosdisk.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (i = 0; i < nbdinfo; i++) { snprintf(line, sizeof(line), " disk%d: BIOS drive %c (%ju X %u):\n", i, diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c index a246e835624..7f27ba4a674 100644 --- a/sys/boot/i386/libi386/pxe.c +++ b/sys/boot/i386/libi386/pxe.c @@ -389,6 +389,9 @@ pxe_print(int verbose) if (pxe_call == NULL) return (0); + printf("%s devices:", pxedisk.dv_name); + if (pager_output("\n") != 0) + return (1); if (verbose) { snprintf(line, sizeof(line), " pxe0: %s:%s\n", inet_ntoa(rootip), rootpath); diff --git a/sys/boot/mips/beri/loader/beri_disk_cfi.c b/sys/boot/mips/beri/loader/beri_disk_cfi.c index 7a84cc648b4..a9695e2d929 100644 --- a/sys/boot/mips/beri/loader/beri_disk_cfi.c +++ b/sys/boot/mips/beri/loader/beri_disk_cfi.c @@ -119,6 +119,10 @@ beri_cfi_disk_print(int verbose) char line[80]; int ret; + printf("%s devices:", beri_cfi_disk.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + snprintf(line, sizeof(line), " cfi%d CFI flash device\n", 0); ret = pager_output(line); if (ret != 0) diff --git a/sys/boot/mips/beri/loader/beri_disk_sdcard.c b/sys/boot/mips/beri/loader/beri_disk_sdcard.c index e1a2e87d11f..c07ba75c1db 100644 --- a/sys/boot/mips/beri/loader/beri_disk_sdcard.c +++ b/sys/boot/mips/beri/loader/beri_disk_sdcard.c @@ -118,13 +118,17 @@ beri_sdcard_disk_close(struct open_file *f) return (disk_close(dev)); } -static void +static int beri_sdcard_disk_print(int verbose) { struct disk_devdesc dev; char line[80]; int ret; + printf("%s devices:", beri_sdcard_disk.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + snprintf(line, sizeof(line), " sdcard%d Altera SD card drive\n", 0); ret = pager_output(line); if (ret != 0) diff --git a/sys/boot/pc98/libpc98/bioscd.c b/sys/boot/pc98/libpc98/bioscd.c index 6e520138400..9cdc5673bfd 100644 --- a/sys/boot/pc98/libpc98/bioscd.c +++ b/sys/boot/pc98/libpc98/bioscd.c @@ -179,6 +179,13 @@ bc_print(int verbose) char line[80]; int i, ret = 0; + if (nbcinfo == 0) + return (0); + + printf("%s devices:", bioscd.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (i = 0; i < nbcinfo; i++) { sprintf(line, " cd%d: Device 0x%x\n", i, bcinfo[i].bc_sp.sp_devicespec); diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c index 6ecfa4912a6..3163019c2b9 100644 --- a/sys/boot/pc98/libpc98/biosdisk.c +++ b/sys/boot/pc98/libpc98/biosdisk.c @@ -258,6 +258,13 @@ bd_print(int verbose) struct open_disk *od; struct pc98_partition *dptr; + if (nbdinfo == 0) + return (0); + + printf("%s devices:", biosdisk.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (i = 0; i < nbdinfo; i++) { snprintf(line, sizeof(line), " disk%d: BIOS drive %c:\n", i, 'A' + i); diff --git a/sys/boot/uboot/lib/disk.c b/sys/boot/uboot/lib/disk.c index c0d187d1f96..474d4aa31f7 100644 --- a/sys/boot/uboot/lib/disk.c +++ b/sys/boot/uboot/lib/disk.c @@ -245,6 +245,13 @@ stor_print(int verbose) static char line[80]; int i, ret = 0; + if (stor_info_no == 0) + return (ret); + + printf("%s devices:", uboot_storage.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (i = 0; i < stor_info_no; i++) { dev.d_dev = &uboot_storage; dev.d_unit = i; diff --git a/sys/boot/usb/storage/umass_loader.c b/sys/boot/usb/storage/umass_loader.c index e6e38bfe9e2..9ecd4b2e162 100644 --- a/sys/boot/usb/storage/umass_loader.c +++ b/sys/boot/usb/storage/umass_loader.c @@ -175,6 +175,10 @@ umass_disk_print(int verbose) { struct disk_devdesc dev; + printf("%s devices:", umass_disk.dv_name); + if (pager_output("\n") != 0) + return (1); + memset(&dev, 0, sizeof(dev)); ret = pager_output(" umass0 UMASS device\n"); diff --git a/sys/boot/userboot/userboot/host.c b/sys/boot/userboot/userboot/host.c index dca2f341ba6..e69d2d31bfc 100644 --- a/sys/boot/userboot/userboot/host.c +++ b/sys/boot/userboot/userboot/host.c @@ -139,6 +139,10 @@ host_dev_print(int verbose) { char line[80]; + printf("%s devices:", host_dev.dv_name); + if (pager_output("\n") != 0) + return (1); + snprintf(line, sizeof(line), " host%d: Host filesystem\n", 0); return (pager_output(line)); } diff --git a/sys/boot/userboot/userboot/userboot_disk.c b/sys/boot/userboot/userboot/userboot_disk.c index 7c0c36820a9..ecd933b9c31 100644 --- a/sys/boot/userboot/userboot/userboot_disk.c +++ b/sys/boot/userboot/userboot/userboot_disk.c @@ -123,6 +123,13 @@ userdisk_print(int verbose) char line[80]; int i, ret = 0; + if (userdisk_maxunit == 0) + return (0); + + printf("%s devices:", userboot_disk.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + for (i = 0; i < userdisk_maxunit; i++) { snprintf(line, sizeof(line), " disk%d: Guest drive image\n", i); diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c index 3efa429e84a..602db44aa97 100644 --- a/sys/boot/zfs/zfs.c +++ b/sys/boot/zfs/zfs.c @@ -521,6 +521,13 @@ zfs_dev_print(int verbose) char line[80]; int ret = 0; + if (STAILQ_EMPTY(&zfs_pools)) + return (0); + + printf("%s devices:", zfs_dev.dv_name); + if ((ret = pager_output("\n")) != 0) + return (ret); + if (verbose) { return (spa_all_status()); } diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c index 5f05c35587a..8729a7517d1 100644 --- a/sys/boot/zfs/zfsimpl.c +++ b/sys/boot/zfs/zfsimpl.c @@ -1049,8 +1049,10 @@ vdev_probe(vdev_phys_read_t *read, void *read_priv, spa_t **spap) STAILQ_FOREACH(pool_vdev, &spa->spa_vdevs, v_childlink) if (top_vdev == pool_vdev) break; - if (!pool_vdev && top_vdev) + if (!pool_vdev && top_vdev) { + top_vdev->spa = spa; STAILQ_INSERT_TAIL(&spa->spa_vdevs, top_vdev, v_childlink); + } /* * We should already have created an incomplete vdev for this diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index ddb565830ae..cb7205e3331 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -1626,8 +1626,8 @@ probe_device_check: sizeof(struct scsi_inquiry_data)); if (have_serialnum) - MD5Update(&context, serial_buf->serial_num, - serial_buf->length); + MD5Update(&context, path->device->serial_num, + path->device->serial_num_len); MD5Final(digest, &context); if (bcmp(softc->digest, digest, 16) == 0) diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h index e7a92ae9957..d15cd88c193 100644 --- a/sys/cddl/compat/opensolaris/sys/vnode.h +++ b/sys/cddl/compat/opensolaris/sys/vnode.h @@ -75,8 +75,7 @@ vn_is_readonly(vnode_t *vp) #define vn_mountedvfs(vp) ((vp)->v_mountedhere) #define vn_has_cached_data(vp) \ ((vp)->v_object != NULL && \ - ((vp)->v_object->resident_page_count > 0 || \ - !vm_object_cache_is_empty((vp)->v_object))) + (vp)->v_object->resident_page_count > 0) #define vn_exists(vp) do { } while (0) #define vn_invalid(vp) do { } while (0) #define vn_renamepath(tdvp, svp, tnm, lentnm) do { } while (0) diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 8ef31211fe1..27d62d1f013 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -6042,22 +6042,6 @@ inetout: regs[rd] = (uintptr_t)end + 1; break; } #endif - - case DIF_SUBR_TYPEREF: { - uintptr_t size = 4 * sizeof(uintptr_t); - uintptr_t *typeref = (uintptr_t *) P2ROUNDUP(mstate->dtms_scratch_ptr, sizeof(uintptr_t)); - size_t scratch_size = ((uintptr_t) typeref - mstate->dtms_scratch_ptr) + size; - - /* address, num_elements, type_str, type_len */ - typeref[0] = tupregs[0].dttk_value; - typeref[1] = tupregs[1].dttk_value; - typeref[2] = tupregs[2].dttk_value; - typeref[3] = tupregs[3].dttk_value; - - regs[rd] = (uintptr_t) typeref; - mstate->dtms_scratch_ptr += scratch_size; - break; - } } } @@ -7707,66 +7691,6 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, break; } - case DTRACEACT_PRINTT: { - /* The DIF returns a 'typeref'. */ - uintptr_t *typeref = (uintptr_t *)(uintptr_t) val; - char c = '\0' + 1; - size_t s; - - /* - * Get the type string length and round it - * up so that the data that follows is - * aligned for easy access. - */ - size_t typs = strlen((char *) typeref[2]) + 1; - typs = roundup(typs, sizeof(uintptr_t)); - - /* - *Get the size from the typeref using the - * number of elements and the type size. - */ - size = typeref[1] * typeref[3]; - - /* - * Check if the size exceeds the allocated - * buffer size. - */ - if (size + typs + 2 * sizeof(uintptr_t) > dp->dtdo_rtype.dtdt_size) { - /* Flag a drop! */ - *flags |= CPU_DTRACE_DROP; - - } - - /* Store the size in the buffer first. */ - DTRACE_STORE(uintptr_t, tomax, - valoffs, size); - valoffs += sizeof(uintptr_t); - - /* Store the type size in the buffer. */ - DTRACE_STORE(uintptr_t, tomax, - valoffs, typeref[3]); - valoffs += sizeof(uintptr_t); - - val = typeref[2]; - - for (s = 0; s < typs; s++) { - if (c != '\0') - c = dtrace_load8(val++); - - DTRACE_STORE(uint8_t, tomax, - valoffs++, c); - } - - /* - * Reset to the memory address rather than - * the typeref array, then let the BYREF - * code below do the work to store the - * memory data in the buffer. - */ - val = typeref[0]; - break; - } - case DTRACEACT_CHILL: if (dtrace_priv_kernel_destructive(state)) dtrace_action_chill(&mstate, val); @@ -10342,12 +10266,12 @@ dtrace_difo_validate_helper(dtrace_difo_t *dp) subr == DIF_SUBR_NTOHS || subr == DIF_SUBR_NTOHL || subr == DIF_SUBR_NTOHLL || - subr == DIF_SUBR_MEMREF || -#ifndef illumos - subr == DIF_SUBR_MEMSTR || -#endif - subr == DIF_SUBR_TYPEREF) + subr == DIF_SUBR_MEMREF) break; +#ifdef __FreeBSD__ + if (subr == DIF_SUBR_MEMSTR) + break; +#endif err += efunc(pc, "invalid subr %u\n", subr); break; @@ -11647,10 +11571,6 @@ dtrace_ecb_action_add(dtrace_ecb_t *ecb, dtrace_actdesc_t *desc) size = dp->dtdo_rtype.dtdt_size; break; - case DTRACEACT_PRINTT: - size = dp->dtdo_rtype.dtdt_size; - break; - case DTRACEACT_COMMIT: { dtrace_action_t *act = ecb->dte_action; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h index 8887aa8d925..8b206a378d2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h @@ -369,7 +369,6 @@ typedef struct itx { void *itx_private; /* type-specific opaque data */ itx_wr_state_t itx_wr_state; /* write state */ uint8_t itx_sync; /* synchronous transaction */ - uint64_t itx_sod; /* record size on disk */ uint64_t itx_oid; /* object id */ lr_t itx_lr; /* common part of log record */ /* followed by type-specific part of lr_xx_t and its immediate data */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h index ac908bd322e..a1ed9e58d12 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil_impl.h @@ -42,6 +42,7 @@ extern "C" { typedef struct lwb { zilog_t *lwb_zilog; /* back pointer to log struct */ blkptr_t lwb_blk; /* on disk address of this log blk */ + boolean_t lwb_slog; /* lwb_blk is on SLOG device */ int lwb_nused; /* # used bytes in buffer */ int lwb_sz; /* size of block and buffer */ char *lwb_buf; /* log write buffer */ @@ -62,7 +63,6 @@ typedef struct itxs { typedef struct itxg { kmutex_t itxg_lock; /* lock for this structure */ uint64_t itxg_txg; /* txg for this chain */ - uint64_t itxg_sod; /* total size on disk for this txg */ itxs_t *itxg_itxs; /* sync and async itxs */ } itxg_t; @@ -120,7 +120,6 @@ struct zilog { kcondvar_t zl_cv_batch[2]; /* batch condition variables */ itxg_t zl_itxg[TXG_SIZE]; /* intent log txg chains */ list_t zl_itx_commit_list; /* itx list to be committed */ - uint64_t zl_itx_list_sz; /* total size of records on list */ uint64_t zl_cur_used; /* current commit log size used */ list_t zl_lwb_list; /* in-flight log write list */ kmutex_t zl_vdev_lock; /* protects zl_vdev_tree */ @@ -142,6 +141,8 @@ typedef struct zil_bp_node { #define ZIL_MAX_LOG_DATA (SPA_OLD_MAXBLOCKSIZE - sizeof (zil_chain_t) - \ sizeof (lr_write_t)) +#define ZIL_MAX_COPIED_DATA \ + ((SPA_OLD_MAXBLOCKSIZE - sizeof (zil_chain_t)) / 2 - sizeof (lr_write_t)) #ifdef __cplusplus } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h index da3461e10e6..30f8d81f4c8 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h @@ -547,7 +547,7 @@ extern zio_t *zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp, uint64_t size, enum zio_flag flags); extern int zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, - blkptr_t *old_bp, uint64_t size, boolean_t use_slog); + blkptr_t *old_bp, uint64_t size, boolean_t *slog); extern void zio_free_zil(spa_t *spa, uint64_t txg, blkptr_t *bp); extern void zio_flush(zio_t *zio, vdev_t *vd); extern zio_t *zio_trim(zio_t *zio, spa_t *spa, vdev_t *vd, uint64_t offset, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c index 049b958605d..31054bac599 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c @@ -464,20 +464,17 @@ void zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp, offset_t off, ssize_t resid, int ioflag) { + uint32_t blocksize = zp->z_blksz; itx_wr_state_t write_state; - boolean_t slogging; uintptr_t fsync_cnt; - ssize_t immediate_write_sz; if (zil_replaying(zilog, tx) || zp->z_unlinked) return; - immediate_write_sz = (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT) - ? 0 : zfs_immediate_write_sz; - - slogging = spa_has_slogs(zilog->zl_spa) && - (zilog->zl_logbias == ZFS_LOGBIAS_LATENCY); - if (resid > immediate_write_sz && !slogging && resid <= zp->z_blksz) + if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT) + write_state = WR_INDIRECT; + else if (!spa_has_slogs(zilog->zl_spa) && + resid >= zfs_immediate_write_sz) write_state = WR_INDIRECT; else if (ioflag & (FSYNC | FDSYNC)) write_state = WR_COPIED; @@ -491,30 +488,26 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, while (resid) { itx_t *itx; lr_write_t *lr; - ssize_t len; + itx_wr_state_t wr_state = write_state; + ssize_t len = resid; - /* - * If the write would overflow the largest block then split it. - */ - if (write_state != WR_INDIRECT && resid > ZIL_MAX_LOG_DATA) - len = SPA_OLD_MAXBLOCKSIZE >> 1; - else - len = resid; + if (wr_state == WR_COPIED && resid > ZIL_MAX_COPIED_DATA) + wr_state = WR_NEED_COPY; + else if (wr_state == WR_INDIRECT) + len = MIN(blocksize - P2PHASE(off, blocksize), resid); itx = zil_itx_create(txtype, sizeof (*lr) + - (write_state == WR_COPIED ? len : 0)); + (wr_state == WR_COPIED ? len : 0)); lr = (lr_write_t *)&itx->itx_lr; - if (write_state == WR_COPIED && dmu_read(zp->z_zfsvfs->z_os, + if (wr_state == WR_COPIED && dmu_read(zp->z_zfsvfs->z_os, zp->z_id, off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) { zil_itx_destroy(itx); itx = zil_itx_create(txtype, sizeof (*lr)); lr = (lr_write_t *)&itx->itx_lr; - write_state = WR_NEED_COPY; + wr_state = WR_NEED_COPY; } - itx->itx_wr_state = write_state; - if (write_state == WR_NEED_COPY) - itx->itx_sod += len; + itx->itx_wr_state = wr_state; lr->lr_foid = zp->z_id; lr->lr_offset = off; lr->lr_length = len; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 17c702a335f..d176706f777 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -426,12 +426,8 @@ page_busy(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes) continue; } vm_page_sbusy(pp); - } else if (pp == NULL) { - pp = vm_page_alloc(obj, OFF_TO_IDX(start), - VM_ALLOC_SYSTEM | VM_ALLOC_IFCACHED | - VM_ALLOC_SBUSY); - } else { - ASSERT(pp != NULL && !pp->valid); + } else if (pp != NULL) { + ASSERT(!pp->valid); pp = NULL; } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c index 6d58078a5d9..bef7015af83 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c @@ -88,6 +88,15 @@ SYSCTL_DECL(_vfs_zfs_trim); SYSCTL_INT(_vfs_zfs_trim, OID_AUTO, enabled, CTLFLAG_RDTUN, &zfs_trim_enabled, 0, "Enable ZFS TRIM"); +/* + * Limit SLOG write size per commit executed with synchronous priority. + * Any writes above that executed with lower (asynchronous) priority to + * limit potential SLOG device abuse by single active ZIL writer. + */ +uint64_t zil_slog_limit = 768 * 1024; +SYSCTL_QUAD(_vfs_zfs, OID_AUTO, zil_slog_limit, CTLFLAG_RWTUN, + &zil_slog_limit, 0, "Maximal SLOG commit size with sync priority"); + static kmem_cache_t *zil_lwb_cache; #define LWB_EMPTY(lwb) ((BP_GET_LSIZE(&lwb->lwb_blk) - \ @@ -447,13 +456,14 @@ zil_free_log_record(zilog_t *zilog, lr_t *lrc, void *tx, uint64_t claim_txg) } static lwb_t * -zil_alloc_lwb(zilog_t *zilog, blkptr_t *bp, uint64_t txg) +zil_alloc_lwb(zilog_t *zilog, blkptr_t *bp, boolean_t slog, uint64_t txg) { lwb_t *lwb; lwb = kmem_cache_alloc(zil_lwb_cache, KM_SLEEP); lwb->lwb_zilog = zilog; lwb->lwb_blk = *bp; + lwb->lwb_slog = slog; lwb->lwb_buf = zio_buf_alloc(BP_GET_LSIZE(bp)); lwb->lwb_max_txg = txg; lwb->lwb_zio = NULL; @@ -516,6 +526,7 @@ zil_create(zilog_t *zilog) dmu_tx_t *tx = NULL; blkptr_t blk; int error = 0; + boolean_t slog = FALSE; /* * Wait for any previous destroy to complete. @@ -544,7 +555,7 @@ zil_create(zilog_t *zilog) } error = zio_alloc_zil(zilog->zl_spa, txg, &blk, NULL, - ZIL_MIN_BLKSZ, zilog->zl_logbias == ZFS_LOGBIAS_LATENCY); + ZIL_MIN_BLKSZ, &slog); if (error == 0) zil_init_log_chain(zilog, &blk); @@ -554,7 +565,7 @@ zil_create(zilog_t *zilog) * Allocate a log write buffer (lwb) for the first log block. */ if (error == 0) - lwb = zil_alloc_lwb(zilog, &blk, txg); + lwb = zil_alloc_lwb(zilog, &blk, slog, txg); /* * If we just allocated the first log block, commit our transaction @@ -885,6 +896,7 @@ static void zil_lwb_write_init(zilog_t *zilog, lwb_t *lwb) { zbookmark_phys_t zb; + zio_priority_t prio; SET_BOOKMARK(&zb, lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_OBJSET], ZB_ZIL_OBJECT, ZB_ZIL_LEVEL, @@ -895,9 +907,13 @@ zil_lwb_write_init(zilog_t *zilog, lwb_t *lwb) ZIO_FLAG_CANFAIL); } if (lwb->lwb_zio == NULL) { + if (zilog->zl_cur_used <= zil_slog_limit || !lwb->lwb_slog) + prio = ZIO_PRIORITY_SYNC_WRITE; + else + prio = ZIO_PRIORITY_ASYNC_WRITE; lwb->lwb_zio = zio_rewrite(zilog->zl_root_zio, zilog->zl_spa, 0, &lwb->lwb_blk, lwb->lwb_buf, BP_GET_LSIZE(&lwb->lwb_blk), - zil_lwb_write_done, lwb, ZIO_PRIORITY_SYNC_WRITE, + zil_lwb_write_done, lwb, prio, ZIO_FLAG_CANFAIL | ZIO_FLAG_DONT_PROPAGATE, &zb); } } @@ -916,18 +932,6 @@ uint64_t zil_block_buckets[] = { UINT64_MAX }; -/* - * Use the slog as long as the logbias is 'latency' and the current commit size - * is less than the limit or the total list size is less than 2X the limit. - * Limit checking is disabled by setting zil_slog_limit to UINT64_MAX. - */ -uint64_t zil_slog_limit = 1024 * 1024; -SYSCTL_QUAD(_vfs_zfs, OID_AUTO, zil_slog_limit, CTLFLAG_RWTUN, - &zil_slog_limit, 0, "Maximal commit size to use SLOG"); -#define USE_SLOG(zilog) (((zilog)->zl_logbias == ZFS_LOGBIAS_LATENCY) && \ - (((zilog)->zl_cur_used < zil_slog_limit) || \ - ((zilog)->zl_itx_list_sz < (zil_slog_limit << 1)))) - /* * Start a log block write and advance to the next log block. * Calls are serialized. @@ -943,6 +947,7 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb) uint64_t txg; uint64_t zil_blksz, wsz; int i, error; + boolean_t slog; if (BP_GET_CHECKSUM(&lwb->lwb_blk) == ZIO_CHECKSUM_ZILOG2) { zilc = (zil_chain_t *)lwb->lwb_buf; @@ -999,8 +1004,7 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb) BP_ZERO(bp); /* pass the old blkptr in order to spread log blocks across devs */ - error = zio_alloc_zil(spa, txg, bp, &lwb->lwb_blk, zil_blksz, - USE_SLOG(zilog)); + error = zio_alloc_zil(spa, txg, bp, &lwb->lwb_blk, zil_blksz, &slog); if (error == 0) { ASSERT3U(bp->blk_birth, ==, txg); bp->blk_cksum = lwb->lwb_blk.blk_cksum; @@ -1009,7 +1013,7 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb) /* * Allocate a new log write buffer (lwb). */ - nlwb = zil_alloc_lwb(zilog, bp, txg); + nlwb = zil_alloc_lwb(zilog, bp, slog, txg); /* Record the block for later vdev flushing */ zil_add_block(zilog, &lwb->lwb_blk); @@ -1046,12 +1050,13 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb) static lwb_t * zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb) { - lr_t *lrc = &itx->itx_lr; /* common log record */ - lr_write_t *lrw = (lr_write_t *)lrc; + lr_t *lrcb, *lrc = &itx->itx_lr; /* common log record */ + lr_write_t *lrwb, *lrw = (lr_write_t *)lrc; char *lr_buf; uint64_t txg = lrc->lrc_txg; uint64_t reclen = lrc->lrc_reclen; uint64_t dlen = 0; + uint64_t dnow, lwb_sp; if (lwb == NULL) return (NULL); @@ -1068,25 +1073,30 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb) zil_lwb_write_init(zilog, lwb); +cont: /* * If this record won't fit in the current log block, start a new one. + * For WR_NEED_COPY optimize layout for minimal number of chunks, but + * try to keep wasted space withing reasonable range (12%). */ - if (lwb->lwb_nused + reclen + dlen > lwb->lwb_sz) { + lwb_sp = lwb->lwb_sz - lwb->lwb_nused; + if (reclen > lwb_sp || (reclen + dlen > lwb_sp && + lwb_sp < ZIL_MAX_LOG_DATA / 8 && (dlen % ZIL_MAX_LOG_DATA == 0 || + lwb_sp < reclen + dlen % ZIL_MAX_LOG_DATA))) { lwb = zil_lwb_write_start(zilog, lwb); if (lwb == NULL) return (NULL); zil_lwb_write_init(zilog, lwb); ASSERT(LWB_EMPTY(lwb)); - if (lwb->lwb_nused + reclen + dlen > lwb->lwb_sz) { - txg_wait_synced(zilog->zl_dmu_pool, txg); - return (lwb); - } + lwb_sp = lwb->lwb_sz - lwb->lwb_nused; + ASSERT3U(reclen + MIN(dlen, sizeof(uint64_t)), <=, lwb_sp); } + dnow = MIN(dlen, lwb_sp - reclen); lr_buf = lwb->lwb_buf + lwb->lwb_nused; bcopy(lrc, lr_buf, reclen); - lrc = (lr_t *)lr_buf; - lrw = (lr_write_t *)lrc; + lrcb = (lr_t *)lr_buf; + lrwb = (lr_write_t *)lrcb; /* * If it's a write, fetch the data or get its blkptr as appropriate. @@ -1098,16 +1108,19 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb) char *dbuf; int error; - if (dlen) { - ASSERT(itx->itx_wr_state == WR_NEED_COPY); + if (itx->itx_wr_state == WR_NEED_COPY) { dbuf = lr_buf + reclen; - lrw->lr_common.lrc_reclen += dlen; + lrcb->lrc_reclen += dnow; + if (lrwb->lr_length > dnow) + lrwb->lr_length = dnow; + lrw->lr_offset += dnow; + lrw->lr_length -= dnow; } else { ASSERT(itx->itx_wr_state == WR_INDIRECT); dbuf = NULL; } error = zilog->zl_get_data( - itx->itx_private, lrw, dbuf, lwb->lwb_zio); + itx->itx_private, lrwb, dbuf, lwb->lwb_zio); if (error == EIO) { txg_wait_synced(zilog->zl_dmu_pool, txg); return (lwb); @@ -1126,12 +1139,18 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb) * equal to the itx sequence number because not all transactions * are synchronous, and sometimes spa_sync() gets there first. */ - lrc->lrc_seq = ++zilog->zl_lr_seq; /* we are single threaded */ - lwb->lwb_nused += reclen + dlen; + lrcb->lrc_seq = ++zilog->zl_lr_seq; /* we are single threaded */ + lwb->lwb_nused += reclen + dnow; lwb->lwb_max_txg = MAX(lwb->lwb_max_txg, txg); ASSERT3U(lwb->lwb_nused, <=, lwb->lwb_sz); ASSERT0(P2PHASE(lwb->lwb_nused, sizeof (uint64_t))); + dlen -= dnow; + if (dlen > 0) { + zilog->zl_cur_used += reclen; + goto cont; + } + return (lwb); } @@ -1142,15 +1161,9 @@ zil_itx_create(uint64_t txtype, size_t lrsize) lrsize = P2ROUNDUP_TYPED(lrsize, sizeof (uint64_t), size_t); -#ifdef __FreeBSD__ - if (offsetof(itx_t, itx_lr) + lrsize > PAGE_SIZE) - itx = zio_buf_alloc(offsetof(itx_t, itx_lr) + lrsize); - else -#endif itx = kmem_alloc(offsetof(itx_t, itx_lr) + lrsize, KM_SLEEP); itx->itx_lr.lrc_txtype = txtype; itx->itx_lr.lrc_reclen = lrsize; - itx->itx_sod = lrsize; /* if write & WR_NEED_COPY will be increased */ itx->itx_lr.lrc_seq = 0; /* defensive */ itx->itx_sync = B_TRUE; /* default is synchronous */ @@ -1160,11 +1173,6 @@ zil_itx_create(uint64_t txtype, size_t lrsize) void zil_itx_destroy(itx_t *itx) { -#ifdef __FreeBSD__ - if (offsetof(itx_t, itx_lr) + itx->itx_lr.lrc_reclen > PAGE_SIZE) - zio_buf_free(itx, offsetof(itx_t, itx_lr) + itx->itx_lr.lrc_reclen); - else -#endif kmem_free(itx, offsetof(itx_t, itx_lr) + itx->itx_lr.lrc_reclen); } @@ -1184,7 +1192,8 @@ zil_itxg_clean(itxs_t *itxs) list = &itxs->i_sync_list; while ((itx = list_head(list)) != NULL) { list_remove(list, itx); - zil_itx_destroy(itx); + kmem_free(itx, offsetof(itx_t, itx_lr) + + itx->itx_lr.lrc_reclen); } cookie = NULL; @@ -1193,7 +1202,8 @@ zil_itxg_clean(itxs_t *itxs) list = &ian->ia_list; while ((itx = list_head(list)) != NULL) { list_remove(list, itx); - zil_itx_destroy(itx); + kmem_free(itx, offsetof(itx_t, itx_lr) + + itx->itx_lr.lrc_reclen); } list_destroy(list); kmem_free(ian, sizeof (itx_async_node_t)); @@ -1258,7 +1268,8 @@ zil_remove_async(zilog_t *zilog, uint64_t oid) } while ((itx = list_head(&clean_list)) != NULL) { list_remove(&clean_list, itx); - zil_itx_destroy(itx); + kmem_free(itx, offsetof(itx_t, itx_lr) + + itx->itx_lr.lrc_reclen); } list_destroy(&clean_list); } @@ -1301,11 +1312,8 @@ zil_itx_assign(zilog_t *zilog, itx_t *itx, dmu_tx_t *tx) * this itxg. Save the itxs for release below. * This should be rare. */ - atomic_add_64(&zilog->zl_itx_list_sz, -itxg->itxg_sod); - itxg->itxg_sod = 0; clean = itxg->itxg_itxs; } - ASSERT(itxg->itxg_sod == 0); itxg->itxg_txg = txg; itxs = itxg->itxg_itxs = kmem_zalloc(sizeof (itxs_t), KM_SLEEP); @@ -1317,8 +1325,6 @@ zil_itx_assign(zilog_t *zilog, itx_t *itx, dmu_tx_t *tx) } if (itx->itx_sync) { list_insert_tail(&itxs->i_sync_list, itx); - atomic_add_64(&zilog->zl_itx_list_sz, itx->itx_sod); - itxg->itxg_sod += itx->itx_sod; } else { avl_tree_t *t = &itxs->i_async_tree; uint64_t foid = ((lr_ooo_t *)&itx->itx_lr)->lr_foid; @@ -1366,8 +1372,6 @@ zil_clean(zilog_t *zilog, uint64_t synced_txg) ASSERT3U(itxg->itxg_txg, <=, synced_txg); ASSERT(itxg->itxg_txg != 0); ASSERT(zilog->zl_clean_taskq != NULL); - atomic_add_64(&zilog->zl_itx_list_sz, -itxg->itxg_sod); - itxg->itxg_sod = 0; clean_me = itxg->itxg_itxs; itxg->itxg_itxs = NULL; itxg->itxg_txg = 0; @@ -1391,7 +1395,6 @@ zil_get_commit_list(zilog_t *zilog) { uint64_t otxg, txg; list_t *commit_list = &zilog->zl_itx_commit_list; - uint64_t push_sod = 0; if (spa_freeze_txg(zilog->zl_spa) != UINT64_MAX) /* ziltest support */ otxg = ZILTEST_TXG; @@ -1408,12 +1411,9 @@ zil_get_commit_list(zilog_t *zilog) } list_move_tail(commit_list, &itxg->itxg_itxs->i_sync_list); - push_sod += itxg->itxg_sod; - itxg->itxg_sod = 0; mutex_exit(&itxg->itxg_lock); } - atomic_add_64(&zilog->zl_itx_list_sz, -push_sod); } /* @@ -1508,7 +1508,8 @@ zil_commit_writer(zilog_t *zilog) if (txg > spa_last_synced_txg(spa) || txg > spa_freeze_txg(spa)) lwb = zil_lwb_commit(zilog, itx, lwb); list_remove(&zilog->zl_itx_commit_list, itx); - zil_itx_destroy(itx); + kmem_free(itx, offsetof(itx_t, itx_lr) + + itx->itx_lr.lrc_reclen); } DTRACE_PROBE1(zil__cw2, zilog_t *, zilog); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c index 7cf8dc46a3a..0b6813a96a9 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c @@ -2908,20 +2908,21 @@ zio_dva_unallocate(zio_t *zio, zio_gang_node_t *gn, blkptr_t *bp) */ int zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, blkptr_t *old_bp, - uint64_t size, boolean_t use_slog) + uint64_t size, boolean_t *slog) { int error = 1; ASSERT(txg > spa_syncing_txg(spa)); - if (use_slog) { - error = metaslab_alloc(spa, spa_log_class(spa), size, - new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, NULL); - } - - if (error) { + error = metaslab_alloc(spa, spa_log_class(spa), size, + new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, NULL); + if (error == 0) { + *slog = TRUE; + } else { error = metaslab_alloc(spa, spa_normal_class(spa), size, new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, NULL); + if (error == 0) + *slog = FALSE; } if (error == 0) { diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c index 908de12a46c..1847ad54906 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c @@ -1387,54 +1387,44 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, offset_t off, ssize_t resid, { uint32_t blocksize = zv->zv_volblocksize; zilog_t *zilog = zv->zv_zilog; - boolean_t slogging; - ssize_t immediate_write_sz; + itx_wr_state_t write_state; if (zil_replaying(zilog, tx)) return; - immediate_write_sz = (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT) - ? 0 : zvol_immediate_write_sz; - - slogging = spa_has_slogs(zilog->zl_spa) && - (zilog->zl_logbias == ZFS_LOGBIAS_LATENCY); + if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT) + write_state = WR_INDIRECT; + else if (!spa_has_slogs(zilog->zl_spa) && + resid >= blocksize && blocksize > zvol_immediate_write_sz) + write_state = WR_INDIRECT; + else if (sync) + write_state = WR_COPIED; + else + write_state = WR_NEED_COPY; while (resid) { itx_t *itx; lr_write_t *lr; - ssize_t len; - itx_wr_state_t write_state; + itx_wr_state_t wr_state = write_state; + ssize_t len = resid; - /* - * Unlike zfs_log_write() we can be called with - * upto DMU_MAX_ACCESS/2 (5MB) writes. - */ - if (blocksize > immediate_write_sz && !slogging && - resid >= blocksize && off % blocksize == 0) { - write_state = WR_INDIRECT; /* uses dmu_sync */ - len = blocksize; - } else if (sync) { - write_state = WR_COPIED; - len = MIN(ZIL_MAX_LOG_DATA, resid); - } else { - write_state = WR_NEED_COPY; - len = MIN(ZIL_MAX_LOG_DATA, resid); - } + if (wr_state == WR_COPIED && resid > ZIL_MAX_COPIED_DATA) + wr_state = WR_NEED_COPY; + else if (wr_state == WR_INDIRECT) + len = MIN(blocksize - P2PHASE(off, blocksize), resid); itx = zil_itx_create(TX_WRITE, sizeof (*lr) + - (write_state == WR_COPIED ? len : 0)); + (wr_state == WR_COPIED ? len : 0)); lr = (lr_write_t *)&itx->itx_lr; - if (write_state == WR_COPIED && dmu_read(zv->zv_objset, + if (wr_state == WR_COPIED && dmu_read(zv->zv_objset, ZVOL_OBJ, off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) { zil_itx_destroy(itx); itx = zil_itx_create(TX_WRITE, sizeof (*lr)); lr = (lr_write_t *)&itx->itx_lr; - write_state = WR_NEED_COPY; + wr_state = WR_NEED_COPY; } - itx->itx_wr_state = write_state; - if (write_state == WR_NEED_COPY) - itx->itx_sod += len; + itx->itx_wr_state = wr_state; lr->lr_foid = ZVOL_OBJ; lr->lr_offset = off; lr->lr_length = len; diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h index 92d35690ad7..f489bb0629d 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h @@ -308,7 +308,7 @@ typedef enum dtrace_probespec { #define DIF_SUBR_TOUPPER 44 #define DIF_SUBR_TOLOWER 45 #define DIF_SUBR_MEMREF 46 -#define DIF_SUBR_TYPEREF 47 +#define DIF_SUBR_UNUSED 47 #define DIF_SUBR_SX_SHARED_HELD 48 #define DIF_SUBR_SX_EXCLUSIVE_HELD 49 #define DIF_SUBR_SX_ISEXCLUSIVE 50 @@ -429,7 +429,6 @@ typedef struct dtrace_difv { #define DTRACEACT_TRACEMEM 6 /* tracemem() action */ #define DTRACEACT_TRACEMEM_DYNSIZE 7 /* dynamic tracemem() size */ #define DTRACEACT_PRINTM 8 /* printm() action (BSD) */ -#define DTRACEACT_PRINTT 9 /* printt() action (BSD) */ #define DTRACEACT_PROC 0x0100 #define DTRACEACT_USTACK (DTRACEACT_PROC + 1) diff --git a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c index e1f95de8a8d..1ffe6a7a809 100644 --- a/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c +++ b/sys/cddl/contrib/opensolaris/uts/intel/dtrace/fasttrap_isa.c @@ -1871,9 +1871,7 @@ fasttrap_getreg(struct reg *rp, uint_t reg) case REG_ERR: return (rp->r_err); case REG_RIP: return (rp->r_rip); case REG_CS: return (rp->r_cs); -#ifdef illumos - case REG_RFL: return (rp->r_rfl); -#endif + case REG_RFL: return (rp->r_rflags); case REG_RSP: return (rp->r_rsp); case REG_SS: return (rp->r_ss); case REG_FS: return (rp->r_fs); diff --git a/sys/conf/Makefile.mips b/sys/conf/Makefile.mips index d1e69239080..de006c018e6 100644 --- a/sys/conf/Makefile.mips +++ b/sys/conf/Makefile.mips @@ -52,6 +52,8 @@ CFLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS) HACK_EXTRA_FLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS) TRAMP_ARCH_FLAGS?=$(ARCH_FLAGS) TRAMP_EXTRA_FLAGS=${EXTRA_FLAGS} ${TRAMP_ARCH_FLAGS} +# Kernel code is always compiled with soft-float on MIPS +TRAMP_EXTRA_FLAGS+=-msoft-float .if ${MACHINE_ARCH:Mmips64*} != "" TRAMP_ELFSIZE=64 .else diff --git a/sys/conf/NOTES b/sys/conf/NOTES index f964d256a61..ebb7d424545 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1903,6 +1903,7 @@ device amphy # AMD AM79c873 / Davicom DM910{1,2} device atphy # Attansic/Atheros F1 device axphy # Asix Semiconductor AX88x9x device bmtphy # Broadcom BCM5201/BCM5202 and 3Com 3c905C +device bnxt # Broadcom NetXtreme-C/NetXtreme-E device brgphy # Broadcom BCM54xx/57xx 1000baseTX device ciphy # Cicada/Vitesse CS/VSC8xxx device e1000phy # Marvell 88E1000 1000/100/10-BT @@ -1943,6 +1944,7 @@ device xmphy # XaQti XMAC II # BCM570x family of controllers, including the 3Com 3c996-T, # the Netgear GA302T, the SysKonnect SK-9D21 and SK-9D41, and # the embedded gigE NICs on Dell PowerEdge 2550 servers. +# bnxt: Broadcom NetXtreme-C and NetXtreme-E PCIe 10/25/50G Ethernet adapters. # bxe: Broadcom NetXtreme II (BCM5771X/BCM578XX) PCIe 10Gb Ethernet # adapters. # bwi: Broadcom BCM430* and BCM431* family of wireless adapters. diff --git a/sys/conf/files b/sys/conf/files index 7a92df184c7..07bbfb8c41c 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1242,6 +1242,10 @@ dev/bktr/bktr_i2c.c optional bktr pci smbus dev/bktr/bktr_os.c optional bktr pci dev/bktr/bktr_tuner.c optional bktr pci dev/bktr/msp34xx.c optional bktr pci +dev/bnxt/bnxt_hwrm.c optional bnxt iflib pci +dev/bnxt/bnxt_sysctl.c optional bnxt iflib pci +dev/bnxt/bnxt_txrx.c optional bnxt iflib pci +dev/bnxt/if_bnxt.c optional bnxt iflib pci dev/buslogic/bt.c optional bt dev/buslogic/bt_eisa.c optional bt eisa dev/buslogic/bt_isa.c optional bt isa @@ -1398,6 +1402,7 @@ dev/dcons/dcons.c optional dcons dev/dcons/dcons_crom.c optional dcons_crom dev/dcons/dcons_os.c optional dcons dev/de/if_de.c optional de pci +dev/dme/if_dme.c optional dme dev/dpt/dpt_eisa.c optional dpt eisa dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt @@ -1466,6 +1471,49 @@ dev/drm/via_map.c optional viadrm dev/drm/via_mm.c optional viadrm dev/drm/via_verifier.c optional viadrm dev/drm/via_video.c optional viadrm +dev/drm2/drm_agpsupport.c optional drm2 +dev/drm2/drm_auth.c optional drm2 +dev/drm2/drm_bufs.c optional drm2 +dev/drm2/drm_buffer.c optional drm2 +dev/drm2/drm_context.c optional drm2 +dev/drm2/drm_crtc.c optional drm2 +dev/drm2/drm_crtc_helper.c optional drm2 +dev/drm2/drm_dma.c optional drm2 +dev/drm2/drm_dp_helper.c optional drm2 +dev/drm2/drm_dp_iic_helper.c optional drm2 +dev/drm2/drm_drv.c optional drm2 +dev/drm2/drm_edid.c optional drm2 +dev/drm2/drm_fb_helper.c optional drm2 +dev/drm2/drm_fops.c optional drm2 +dev/drm2/drm_gem.c optional drm2 +dev/drm2/drm_gem_names.c optional drm2 +dev/drm2/drm_global.c optional drm2 +dev/drm2/drm_hashtab.c optional drm2 +dev/drm2/drm_ioctl.c optional drm2 +dev/drm2/drm_irq.c optional drm2 +dev/drm2/drm_linux_list_sort.c optional drm2 +dev/drm2/drm_lock.c optional drm2 +dev/drm2/drm_memory.c optional drm2 +dev/drm2/drm_mm.c optional drm2 +dev/drm2/drm_modes.c optional drm2 +dev/drm2/drm_pci.c optional drm2 +dev/drm2/drm_scatter.c optional drm2 +dev/drm2/drm_stub.c optional drm2 +dev/drm2/drm_sysctl.c optional drm2 +dev/drm2/drm_vm.c optional drm2 +dev/drm2/drm_os_freebsd.c optional drm2 +dev/drm2/ttm/ttm_agp_backend.c optional drm2 +dev/drm2/ttm/ttm_lock.c optional drm2 +dev/drm2/ttm/ttm_object.c optional drm2 +dev/drm2/ttm/ttm_tt.c optional drm2 +dev/drm2/ttm/ttm_bo_util.c optional drm2 +dev/drm2/ttm/ttm_bo.c optional drm2 +dev/drm2/ttm/ttm_bo_manager.c optional drm2 +dev/drm2/ttm/ttm_execbuf_util.c optional drm2 +dev/drm2/ttm/ttm_memory.c optional drm2 +dev/drm2/ttm/ttm_page_alloc.c optional drm2 +dev/drm2/ttm/ttm_bo_vm.c optional drm2 +dev/drm2/ati_pcigart.c optional drm2 agp pci dev/ed/if_ed.c optional ed dev/ed/if_ed_novell.c optional ed dev/ed/if_ed_rtl80x9.c optional ed @@ -1614,6 +1662,7 @@ dev/gpio/gpioc.c optional gpio \ dev/gpio/gpioiic.c optional gpioiic dev/gpio/gpioled.c optional gpioled !fdt dev/gpio/gpioled_fdt.c optional gpioled fdt +dev/gpio/gpiopower.c optional gpiopower fdt dev/gpio/gpioregulator.c optional gpioregulator fdt ext_resources dev/gpio/gpiospi.c optional gpiospi dev/gpio/gpio_if.m optional gpio diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 99d4aef326b..c6609a31fbf 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -292,18 +292,20 @@ dev/hwpmc/hwpmc_uncore.c optional hwpmc dev/hwpmc/hwpmc_piv.c optional hwpmc dev/hwpmc/hwpmc_tsc.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc +dev/hyperv/pcib/vmbus_pcib.c optional hyperv pci dev/hyperv/netvsc/hn_nvs.c optional hyperv dev/hyperv/netvsc/hn_rndis.c optional hyperv dev/hyperv/netvsc/if_hn.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv +dev/hyperv/utilities/hv_snapshot.c optional hyperv dev/hyperv/utilities/hv_shutdown.c optional hyperv dev/hyperv/utilities/hv_timesync.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hyperv.c optional hyperv dev/hyperv/vmbus/hyperv_busdma.c optional hyperv -dev/hyperv/vmbus/vmbus.c optional hyperv +dev/hyperv/vmbus/vmbus.c optional hyperv pci dev/hyperv/vmbus/vmbus_br.c optional hyperv dev/hyperv/vmbus/vmbus_chan.c optional hyperv dev/hyperv/vmbus/vmbus_et.c optional hyperv diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index ea7b7d4b443..879515185c7 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -52,7 +52,6 @@ arm/arm/pmu.c standard arm/broadcom/bcm2835/bcm2835_audio.c optional sound vchiq \ compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq" arm/broadcom/bcm2835/bcm2835_bsc.c optional bcm2835_bsc soc_brcm_bcm2837 -arm/broadcom/bcm2835/bcm2835_common.c optional fdt soc_brcm_bcm2837 arm/broadcom/bcm2835/bcm2835_cpufreq.c optional soc_brcm_bcm2837 arm/broadcom/bcm2835/bcm2835_dma.c optional soc_brcm_bcm2837 arm/broadcom/bcm2835/bcm2835_fbd.c optional vt soc_brcm_bcm2837 diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 681b81f218b..597376de1a2 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -249,18 +249,20 @@ dev/hwpmc/hwpmc_piv.c optional hwpmc dev/hwpmc/hwpmc_ppro.c optional hwpmc dev/hwpmc/hwpmc_tsc.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc +dev/hyperv/pcib/vmbus_pcib.c optional hyperv pci dev/hyperv/netvsc/hn_nvs.c optional hyperv dev/hyperv/netvsc/hn_rndis.c optional hyperv dev/hyperv/netvsc/if_hn.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv dev/hyperv/utilities/hv_heartbeat.c optional hyperv dev/hyperv/utilities/hv_kvp.c optional hyperv +dev/hyperv/utilities/hv_snapshot.c optional hyperv dev/hyperv/utilities/hv_shutdown.c optional hyperv dev/hyperv/utilities/hv_timesync.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hyperv.c optional hyperv dev/hyperv/vmbus/hyperv_busdma.c optional hyperv -dev/hyperv/vmbus/vmbus.c optional hyperv +dev/hyperv/vmbus/vmbus.c optional hyperv pci dev/hyperv/vmbus/vmbus_br.c optional hyperv dev/hyperv/vmbus/vmbus_chan.c optional hyperv dev/hyperv/vmbus/vmbus_et.c optional hyperv diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index 0a2d9a65ee7..ee72dbe0ebe 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -74,7 +74,7 @@ CFLAGS+= ${INCLUDES} -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global. CFLAGS_PARAM_INLINE_UNIT_GROWTH?=100 CFLAGS_PARAM_LARGE_FUNCTION_GROWTH?=1000 .if ${MACHINE_CPUARCH} == "mips" -CFLAGS_ARCH_PARAMS?=--param max-inline-insns-single=1000 +CFLAGS_ARCH_PARAMS?=--param max-inline-insns-single=1000 -DMACHINE_ARCH='"${MACHINE_ARCH}"' .endif CFLAGS.gcc+= -fno-common -fms-extensions -finline-limit=${INLINE_LIMIT} CFLAGS.gcc+= --param inline-unit-growth=${CFLAGS_PARAM_INLINE_UNIT_GROWTH} diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index ca2ebc82247..72e9ae60610 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -39,6 +39,28 @@ fi RELEASE="${REVISION}-${BRANCH}" VERSION="${TYPE} ${RELEASE}" +# +# findvcs dir +# Looks up directory dir at world root and up the filesystem +# +findvcs() +{ + local savedir + + savedir=$(pwd) + cd ${SYSDIR}/.. + while [ $(pwd) != "/" ]; do + if [ -d "./$1" ]; then + VCSDIR=$(pwd)"/$1" + cd ${savedir} + return 0 + fi + cd .. + done + cd ${savedir} + return 1 +} + if [ -z "${SYSDIR}" ]; then SYSDIR=$(dirname $0)/.. fi @@ -142,19 +164,20 @@ for dir in /usr/bin /usr/local/bin; do p4_cmd=${dir}/p4 fi done -if [ -d "${SYSDIR}/../.git" ] ; then + +if findvcs .git; then for dir in /usr/bin /usr/local/bin; do if [ -x "${dir}/git" ] ; then - git_cmd="${dir}/git --git-dir=${SYSDIR}/../.git" + git_cmd="${dir}/git --git-dir=${VCSDIR}" break fi done fi -if [ -d "${SYSDIR}/../.hg" ] ; then +if findvcs .hg; then for dir in /usr/bin /usr/local/bin; do if [ -x "${dir}/hg" ] ; then - hg_cmd="${dir}/hg -R ${SYSDIR}/.." + hg_cmd="${dir}/hg -R ${VCSDIR}" break fi done @@ -193,7 +216,7 @@ if [ -n "$git_cmd" ] ; then if [ -n "$git_b" ] ; then git="${git}(${git_b})" fi - if $git_cmd --work-tree=${SYSDIR}/.. diff-index \ + if $git_cmd --work-tree=${VCSDIR}/.. diff-index \ --name-only HEAD | read dummy; then git="${git}-dirty" fi diff --git a/sys/conf/options b/sys/conf/options index 79f71a8e487..da04567fa48 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -220,6 +220,7 @@ SYSVSHM opt_sysvipc.h SW_WATCHDOG opt_watchdog.h TURNSTILE_PROFILING UMTX_PROFILING +UMTX_CHAINS opt_global.h VERBOSE_SYSINIT # POSIX kernel options @@ -992,7 +993,11 @@ BHND_LOGLEVEL opt_global.h # GPIO and child devices GPIO_SPI_DEBUG opt_gpio.h +# etherswitch(4) driver +RTL8366_SOFT_RESET opt_etherswitch.h + # evdev protocol support EVDEV_SUPPORT opt_evdev.h EVDEV_DEBUG opt_evdev.h UINPUT_DEBUG opt_evdev.h + diff --git a/sys/conf/options.riscv b/sys/conf/options.riscv index c263bd86087..af6a89e80f1 100644 --- a/sys/conf/options.riscv +++ b/sys/conf/options.riscv @@ -1,4 +1,4 @@ # $FreeBSD$ RISCV opt_global.h -VFP opt_global.h +FPE opt_global.h diff --git a/sys/contrib/ncsw/inc/xx_ext.h b/sys/contrib/ncsw/inc/xx_ext.h index ce8cae31005..f011b58b65a 100644 --- a/sys/contrib/ncsw/inc/xx_ext.h +++ b/sys/contrib/ncsw/inc/xx_ext.h @@ -930,9 +930,4 @@ t_Error XX_IpcSendMessage(t_Handle h_Session, /** @} */ /* end of xx_ipc group */ /** @} */ /* end of xx_id group */ -/** FreeBSD Specific additions. */ -void XX_TrackInit(void); -physAddress_t XX_TrackAddress(void *addr); -void XX_UntrackAddress(void *addr); - #endif /* __XX_EXT_H */ diff --git a/sys/contrib/ncsw/user/env/xx.c b/sys/contrib/ncsw/user/env/xx.c index 621c2025e16..c153c69dcef 100644 --- a/sys/contrib/ncsw/user/env/xx.c +++ b/sys/contrib/ncsw/user/env/xx.c @@ -51,6 +51,7 @@ #include #include +#include #include "error_ext.h" #include "std_ext.h" #include "list_ext.h" @@ -124,19 +125,6 @@ struct XX_PortalInfo { static struct XX_PortalInfo XX_PInfo; -/* The lower 9 bits, through emprical testing, tend to be 0. */ -#define XX_MALLOC_TRACK_SHIFT 9 - -typedef struct XX_MallocTrackStruct { - LIST_ENTRY(XX_MallocTrackStruct) entries; - physAddress_t pa; - void *va; -} XX_MallocTrackStruct; - -LIST_HEAD(XX_MallocTrackerList, XX_MallocTrackStruct) *XX_MallocTracker; -u_long XX_MallocHashMask; -static XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa); - void XX_Exit(int status) { @@ -266,7 +254,6 @@ XX_FreeSmart(void *p) KASSERT(XX_MallocSmartMap[start] > 0, ("XX_FreeSmart: Double or mid-block free!\n")); - XX_UntrackAddress(p); /* Free region */ slices = XX_MallocSmartMap[start]; XX_MallocSmartMapClear(start, slices); @@ -279,8 +266,6 @@ void XX_Free(void *p) { - if (p != NULL) - XX_UntrackAddress(p); free(p, M_NETCOMMSW); } @@ -758,6 +743,11 @@ XX_VirtToPhys(void *addr) if (addr == NULL) return (-1); + /* Check CCSR */ + if ((vm_offset_t)addr >= ccsrbar_va && + (vm_offset_t)addr < ccsrbar_va + ccsrbar_size) + return (((vm_offset_t)addr - ccsrbar_va) + ccsrbar_pa); + /* Handle BMAN mappings */ if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[BM_PORTAL]) && ((vm_offset_t)addr < XX_PInfo.portal_ce_va[BM_PORTAL] + @@ -784,10 +774,12 @@ XX_VirtToPhys(void *addr) return (XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] + (vm_offset_t)addr - XX_PInfo.portal_ci_va[QM_PORTAL]); - paddr = XX_TrackAddress(addr); - if (paddr == -1) + paddr = pmap_kextract((vm_offset_t)addr); + if (paddr == 0) printf("NetCommSW: " "Unable to translate virtual address 0x%08X!\n", addr); + else + pmap_track_page(kernel_pmap, (vm_offset_t)addr); return (paddr); } @@ -795,9 +787,15 @@ XX_VirtToPhys(void *addr) void * XX_PhysToVirt(physAddress_t addr) { - XX_MallocTrackStruct *ts; + struct pv_entry *pv; + vm_page_t page; int cpu; + /* Check CCSR */ + if (addr >= ccsrbar_pa && addr < ccsrbar_pa + ccsrbar_size) + return ((void *)((vm_offset_t)(addr - ccsrbar_pa) + + ccsrbar_va)); + cpu = PCPU_GET(cpuid); /* Handle BMAN mappings */ @@ -826,12 +824,11 @@ XX_PhysToVirt(physAddress_t addr) return ((void *)(XX_PInfo.portal_ci_va[QM_PORTAL] + (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]))); - mtx_lock(&XX_MallocTrackLock); - ts = XX_FindTracker(addr); - mtx_unlock(&XX_MallocTrackLock); + page = PHYS_TO_VM_PAGE(addr); + pv = TAILQ_FIRST(&page->md.pv_list); - if (ts != NULL) - return ts->va; + if (pv != NULL) + return ((void *)(pv->pv_va + ((vm_offset_t)addr & PAGE_MASK))); printf("NetCommSW: " "Unable to translate physical address 0x%08llX!\n", addr); @@ -877,72 +874,3 @@ XX_PortalSetInfo(device_t dev) end: free(dev_name, M_TEMP); } - -static inline XX_MallocTrackStruct * -XX_FindTracker(physAddress_t pa) -{ - struct XX_MallocTrackerList *l; - XX_MallocTrackStruct *tp; - - l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask]; - - LIST_FOREACH(tp, l, entries) { - if (tp->pa == pa) - return tp; - } - - return NULL; -} - -void -XX_TrackInit(void) -{ - if (XX_MallocTracker == NULL) { - XX_MallocTracker = hashinit(64, M_NETCOMMSW_MT, - &XX_MallocHashMask); - } -} - -physAddress_t -XX_TrackAddress(void *addr) -{ - physAddress_t pa; - struct XX_MallocTrackerList *l; - XX_MallocTrackStruct *ts; - - pa = pmap_kextract((vm_offset_t)addr); - - l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask]; - - mtx_lock(&XX_MallocTrackLock); - if (XX_FindTracker(pa) == NULL) { - ts = malloc(sizeof(*ts), M_NETCOMMSW_MT, M_NOWAIT); - if (ts == NULL) - return (-1); - ts->va = addr; - ts->pa = pa; - LIST_INSERT_HEAD(l, ts, entries); - } - mtx_unlock(&XX_MallocTrackLock); - - return (pa); -} - -void -XX_UntrackAddress(void *addr) -{ - physAddress_t pa; - XX_MallocTrackStruct *ts; - - pa = pmap_kextract((vm_offset_t)addr); - - KASSERT(XX_MallocTracker != NULL, - ("Untracking an address before it's even initialized!\n")); - - mtx_lock(&XX_MallocTrackLock); - ts = XX_FindTracker(pa); - if (ts != NULL) - LIST_REMOVE(ts, entries); - mtx_unlock(&XX_MallocTrackLock); - free(ts, M_NETCOMMSW_MT); -} diff --git a/sys/contrib/vchiq/interface/compat/vchi_bsd.c b/sys/contrib/vchiq/interface/compat/vchi_bsd.c index 3d939b130a2..5e9965f03c7 100644 --- a/sys/contrib/vchiq/interface/compat/vchi_bsd.c +++ b/sys/contrib/vchiq/interface/compat/vchi_bsd.c @@ -300,7 +300,6 @@ void sema_sysinit(void *arg) { struct semaphore *s = arg; - printf("sema_sysinit\n"); _sema_init(s, 1); } diff --git a/sys/dev/acpi_support/acpi_hp.c b/sys/dev/acpi_support/acpi_hp.c index ec858965943..e9de245e264 100644 --- a/sys/dev/acpi_support/acpi_hp.c +++ b/sys/dev/acpi_support/acpi_hp.c @@ -66,11 +66,17 @@ ACPI_MODULE_NAME("HP") #define ACPI_HP_WMI_BIOS_GUID "5FB7F034-2C63-45E9-BE91-3D44E2C707E4" #define ACPI_HP_WMI_CMI_GUID "2D114B49-2DFB-4130-B8FE-4A3C09E75133" -#define ACPI_HP_WMI_DISPLAY_COMMAND 0x1 -#define ACPI_HP_WMI_HDDTEMP_COMMAND 0x2 -#define ACPI_HP_WMI_ALS_COMMAND 0x3 -#define ACPI_HP_WMI_DOCK_COMMAND 0x4 -#define ACPI_HP_WMI_WIRELESS_COMMAND 0x5 +#define ACPI_HP_WMI_DISPLAY_COMMAND 0x1 +#define ACPI_HP_WMI_HDDTEMP_COMMAND 0x2 +#define ACPI_HP_WMI_ALS_COMMAND 0x3 +#define ACPI_HP_WMI_DOCK_COMMAND 0x4 +#define ACPI_HP_WMI_WIRELESS_COMMAND 0x5 +#define ACPI_HP_WMI_BIOS_COMMAND 0x9 +#define ACPI_HP_WMI_FEATURE_COMMAND 0xb +#define ACPI_HP_WMI_HOTKEY_COMMAND 0xc +#define ACPI_HP_WMI_FEATURE2_COMMAND 0xd +#define ACPI_HP_WMI_WIRELESS2_COMMAND 0x1b +#define ACPI_HP_WMI_POSTCODEERROR_COMMAND 0x2a #define ACPI_HP_METHOD_WLAN_ENABLED 1 #define ACPI_HP_METHOD_WLAN_RADIO 2 @@ -104,11 +110,32 @@ ACPI_MODULE_NAME("HP") #define HP_MASK_BLUETOOTH_ENABLED 0x20000 #define HP_MASK_WLAN_ENABLED 0x200 +#define ACPI_HP_EVENT_DOCK 0x01 +#define ACPI_HP_EVENT_PARK_HDD 0x02 +#define ACPI_HP_EVENT_SMART_ADAPTER 0x03 +#define ACPI_HP_EVENT_BEZEL_BUTTON 0x04 +#define ACPI_HP_EVENT_WIRELESS 0x05 +#define ACPI_HP_EVENT_CPU_BATTERY_THROTTLE 0x06 +#define ACPI_HP_EVENT_LOCK_SWITCH 0x07 +#define ACPI_HP_EVENT_LID_SWITCH 0x08 +#define ACPI_HP_EVENT_SCREEN_ROTATION 0x09 +#define ACPI_HP_EVENT_COOLSENSE_SYSTEM_MOBILE 0x0A +#define ACPI_HP_EVENT_COOLSENSE_SYSTEM_HOT 0x0B +#define ACPI_HP_EVENT_PROXIMITY_SENSOR 0x0C +#define ACPI_HP_EVENT_BACKLIT_KB_BRIGHTNESS 0x0D +#define ACPI_HP_EVENT_PEAKSHIFT_PERIOD 0x0F +#define ACPI_HP_EVENT_BATTERY_CHARGE_PERIOD 0x10 + #define ACPI_HP_CMI_DETAIL_PATHS 0x01 #define ACPI_HP_CMI_DETAIL_ENUMS 0x02 #define ACPI_HP_CMI_DETAIL_FLAGS 0x04 #define ACPI_HP_CMI_DETAIL_SHOW_MAX_INSTANCE 0x08 +#define ACPI_HP_WMI_RET_WRONG_SIGNATURE 0x02 +#define ACPI_HP_WMI_RET_UNKNOWN_COMMAND 0x03 +#define ACPI_HP_WMI_RET_UNKNOWN_CMDTYPE 0x04 +#define ACPI_HP_WMI_RET_INVALID_PARAMETERS 0x05 + struct acpi_hp_inst_seq_pair { UINT32 sequence; /* sequence number as suggested by cmi bios */ UINT8 instance; /* object instance on guid */ @@ -119,6 +146,7 @@ struct acpi_hp_softc { device_t wmi_dev; int has_notify; /* notification GUID found */ int has_cmi; /* CMI GUID found */ + int has_wireless; /* Wireless command found */ int cmi_detail; /* CMI detail level (set by sysctl) */ int verbose; /* add debug output */ @@ -287,7 +315,7 @@ static int acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg); static int acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method); static int acpi_hp_exec_wmi_command(device_t wmi_dev, int command, - int is_write, int val); + int is_write, int val, int *retval); static void acpi_hp_notify(ACPI_HANDLE h, UINT32 notify, void *context); static int acpi_hp_get_cmi_block(device_t wmi_dev, const char* guid, UINT8 instance, char* outbuf, size_t outsize, @@ -332,13 +360,18 @@ MODULE_DEPEND(acpi_hp, acpi, 1, 1, 1); static void acpi_hp_evaluate_auto_on_off(struct acpi_hp_softc *sc) { + int res; int wireless; int new_wlan_status; int new_bluetooth_status; int new_wwan_status; - wireless = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + res = acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &wireless); + if (res != 0) { + device_printf(sc->wmi_dev, "Wireless command error %x\n", res); + return; + } new_wlan_status = -1; new_bluetooth_status = -1; new_wwan_status = -1; @@ -348,41 +381,41 @@ acpi_hp_evaluate_auto_on_off(struct acpi_hp_softc *sc) if (sc->wlan_disable_if_radio_off && !(wireless & HP_MASK_WLAN_RADIO) && (wireless & HP_MASK_WLAN_ENABLED)) { acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x100); + ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x100, NULL); new_wlan_status = 0; } else if (sc->wlan_enable_if_radio_on && (wireless & HP_MASK_WLAN_RADIO) && !(wireless & HP_MASK_WLAN_ENABLED)) { acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x101); + ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x101, NULL); new_wlan_status = 1; } if (sc->bluetooth_disable_if_radio_off && !(wireless & HP_MASK_BLUETOOTH_RADIO) && (wireless & HP_MASK_BLUETOOTH_ENABLED)) { acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x200); + ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x200, NULL); new_bluetooth_status = 0; } else if (sc->bluetooth_enable_if_radio_on && (wireless & HP_MASK_BLUETOOTH_RADIO) && !(wireless & HP_MASK_BLUETOOTH_ENABLED)) { acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x202); + ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x202, NULL); new_bluetooth_status = 1; } if (sc->wwan_disable_if_radio_off && !(wireless & HP_MASK_WWAN_RADIO) && (wireless & HP_MASK_WWAN_ENABLED)) { acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x400); + ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x400, NULL); new_wwan_status = 0; } else if (sc->wwan_enable_if_radio_on && (wireless & HP_MASK_WWAN_RADIO) && !(wireless & HP_MASK_WWAN_ENABLED)) { acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x404); + ACPI_HP_WMI_WIRELESS_COMMAND, 1, 0x404, NULL); new_wwan_status = 1; } @@ -441,6 +474,11 @@ acpi_hp_identify(driver_t *driver, device_t parent) if (device_find_child(parent, "acpi_hp", -1) != NULL) return; + /* Check BIOS GUID to see whether system is compatible. */ + if (!ACPI_WMI_PROVIDES_GUID_STRING(parent, + ACPI_HP_WMI_BIOS_GUID)) + return; + if (BUS_ADD_CHILD(parent, 0, "acpi_hp", -1) == NULL) device_printf(parent, "add acpi_hp child failed\n"); } @@ -476,7 +514,7 @@ acpi_hp_attach(device_t dev) sc->was_wwan_on_air = 0; sc->cmi_detail = 0; sc->cmi_order_size = -1; - sc->verbose = 0; + sc->verbose = bootverbose; memset(sc->cmi_order, 0, sizeof(sc->cmi_order)); sc->wmi_dev = device_get_parent(dev); @@ -513,13 +551,17 @@ acpi_hp_attach(device_t dev) sc->hpcmi_bufptr = -1; } + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, NULL) == 0) + sc->has_wireless = 1; + ACPI_SERIAL_BEGIN(hp); sc->sysctl_ctx = device_get_sysctl_ctx(dev); sc->sysctl_tree = device_get_sysctl_tree(dev); for (int i = 0; acpi_hp_sysctls[i].name != NULL; ++i) { arg = 0; - if ((!sc->has_notify && + if (((!sc->has_notify || !sc->has_wireless) && (acpi_hp_sysctls[i].method == ACPI_HP_METHOD_WLAN_ENABLE_IF_RADIO_ON || acpi_hp_sysctls[i].method == @@ -577,8 +619,10 @@ acpi_hp_detach(device_t dev) if (sc->has_cmi && sc->hpcmi_open_pid != 0) return (EBUSY); - if (sc->has_notify) - ACPI_WMI_REMOVE_EVENT_HANDLER(dev, ACPI_HP_WMI_EVENT_GUID); + if (sc->has_notify) { + ACPI_WMI_REMOVE_EVENT_HANDLER(sc->wmi_dev, + ACPI_HP_WMI_EVENT_GUID); + } if (sc->has_cmi) { if (sc->hpcmi_bufptr != -1) { @@ -630,18 +674,21 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method) switch (method) { case ACPI_HP_METHOD_WLAN_ENABLED: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_WLAN_ENABLED) != 0); break; case ACPI_HP_METHOD_WLAN_RADIO: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_WLAN_RADIO) != 0); break; case ACPI_HP_METHOD_WLAN_ON_AIR: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_WLAN_ON_AIR) != 0); break; case ACPI_HP_METHOD_WLAN_ENABLE_IF_RADIO_ON: @@ -651,18 +698,21 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method) val = sc->wlan_disable_if_radio_off; break; case ACPI_HP_METHOD_BLUETOOTH_ENABLED: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_BLUETOOTH_ENABLED) != 0); break; case ACPI_HP_METHOD_BLUETOOTH_RADIO: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_BLUETOOTH_RADIO) != 0); break; case ACPI_HP_METHOD_BLUETOOTH_ON_AIR: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_BLUETOOTH_ON_AIR) != 0); break; case ACPI_HP_METHOD_BLUETOOTH_ENABLE_IF_RADIO_ON: @@ -672,18 +722,21 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method) val = sc->bluetooth_disable_if_radio_off; break; case ACPI_HP_METHOD_WWAN_ENABLED: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_WWAN_ENABLED) != 0); break; case ACPI_HP_METHOD_WWAN_RADIO: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_WWAN_RADIO) != 0); break; case ACPI_HP_METHOD_WWAN_ON_AIR: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 0, 0, &val)) + return (-EINVAL); val = ((val & HP_MASK_WWAN_ON_AIR) != 0); break; case ACPI_HP_METHOD_WWAN_ENABLE_IF_RADIO_ON: @@ -693,20 +746,24 @@ acpi_hp_sysctl_get(struct acpi_hp_softc *sc, int method) val = sc->wwan_disable_if_radio_off; break; case ACPI_HP_METHOD_ALS: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_ALS_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_ALS_COMMAND, 0, 0, &val)) + return (-EINVAL); break; case ACPI_HP_METHOD_DISPLAY: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_DISPLAY_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_DISPLAY_COMMAND, 0, 0, &val)) + return (-EINVAL); break; case ACPI_HP_METHOD_HDDTEMP: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_HDDTEMP_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_HDDTEMP_COMMAND, 0, 0, &val)) + return (-EINVAL); break; case ACPI_HP_METHOD_DOCK: - val = acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_DOCK_COMMAND, 0, 0); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_DOCK_COMMAND, 0, 0, &val)) + return (-EINVAL); break; case ACPI_HP_METHOD_CMI_DETAIL: val = sc->cmi_detail; @@ -732,9 +789,11 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg) if (arg != oldarg) { switch (method) { case ACPI_HP_METHOD_WLAN_ENABLED: - return (acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, - arg?0x101:0x100)); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 1, + arg?0x101:0x100, NULL)) + return (-EINVAL); + break; case ACPI_HP_METHOD_WLAN_ENABLE_IF_RADIO_ON: sc->wlan_enable_if_radio_on = arg; acpi_hp_evaluate_auto_on_off(sc); @@ -744,9 +803,11 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg) acpi_hp_evaluate_auto_on_off(sc); break; case ACPI_HP_METHOD_BLUETOOTH_ENABLED: - return (acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, - arg?0x202:0x200)); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 1, + arg?0x202:0x200, NULL)) + return (-EINVAL); + break; case ACPI_HP_METHOD_BLUETOOTH_ENABLE_IF_RADIO_ON: sc->bluetooth_enable_if_radio_on = arg; acpi_hp_evaluate_auto_on_off(sc); @@ -756,9 +817,11 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg) acpi_hp_evaluate_auto_on_off(sc); break; case ACPI_HP_METHOD_WWAN_ENABLED: - return (acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_WIRELESS_COMMAND, 1, - arg?0x404:0x400)); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_WIRELESS_COMMAND, 1, + arg?0x404:0x400, NULL)) + return (-EINVAL); + break; case ACPI_HP_METHOD_WWAN_ENABLE_IF_RADIO_ON: sc->wwan_enable_if_radio_on = arg?1:0; acpi_hp_evaluate_auto_on_off(sc); @@ -768,9 +831,10 @@ acpi_hp_sysctl_set(struct acpi_hp_softc *sc, int method, int arg, int oldarg) acpi_hp_evaluate_auto_on_off(sc); break; case ACPI_HP_METHOD_ALS: - return (acpi_hp_exec_wmi_command(sc->wmi_dev, - ACPI_HP_WMI_ALS_COMMAND, 1, - arg?1:0)); + if (acpi_hp_exec_wmi_command(sc->wmi_dev, + ACPI_HP_WMI_ALS_COMMAND, 1, arg?1:0, NULL)) + return (-EINVAL); + break; case ACPI_HP_METHOD_CMI_DETAIL: sc->cmi_detail = arg; if ((arg & ACPI_HP_CMI_DETAIL_SHOW_MAX_INSTANCE) != @@ -806,26 +870,32 @@ acpi_hp_notify(ACPI_HANDLE h, UINT32 notify, void *context) ACPI_WMI_GET_EVENT_DATA(sc->wmi_dev, notify, &response); obj = (ACPI_OBJECT*) response.Pointer; if (obj && obj->Type == ACPI_TYPE_BUFFER && obj->Buffer.Length == 8) { - if (*((UINT8 *) obj->Buffer.Pointer) == 0x5) { + switch (*((UINT8 *) obj->Buffer.Pointer)) { + case ACPI_HP_EVENT_WIRELESS: acpi_hp_evaluate_auto_on_off(sc); + break; + default: + if (sc->verbose) { + device_printf(sc->dev, "Event %02x\n", + *((UINT8 *) obj->Buffer.Pointer)); + } + break; } } acpi_hp_free_buffer(&response); } static int -acpi_hp_exec_wmi_command(device_t wmi_dev, int command, int is_write, int val) +acpi_hp_exec_wmi_command(device_t wmi_dev, int command, int is_write, + int val, int *retval) { - UINT32 params[5] = { 0x55434553, - is_write?2:1, - command, - is_write?4:0, - val}; + UINT32 params[4+32] = { 0x55434553, is_write ? 2 : 1, + command, 4, val}; UINT32* result; ACPI_OBJECT *obj; ACPI_BUFFER in = { sizeof(params), ¶ms }; ACPI_BUFFER out = { ACPI_ALLOCATE_BUFFER, NULL }; - int retval; + int res; if (ACPI_FAILURE(ACPI_WMI_EVALUATE_CALL(wmi_dev, ACPI_HP_WMI_BIOS_GUID, 0, 0x3, &in, &out))) { @@ -838,13 +908,12 @@ acpi_hp_exec_wmi_command(device_t wmi_dev, int command, int is_write, int val) return (-EINVAL); } result = (UINT32*) obj->Buffer.Pointer; - retval = result[2]; - if (result[1] > 0) { - retval = result[1]; - } + res = result[1]; + if (res == 0 && retval != NULL) + *retval = result[2]; acpi_hp_free_buffer(&out); - return (retval); + return (res); } static __inline char* @@ -909,81 +978,91 @@ acpi_hp_get_cmi_block(device_t wmi_dev, const char* guid, UINT8 instance, return (-EINVAL); } - if (obj->Package.Count >= 8 && - obj->Package.Elements[7].Type == ACPI_TYPE_INTEGER) { - valuebase = 8 + obj->Package.Elements[7].Integer.Value; + /* Check if first 6 bytes matches our expectations. */ + if (obj->Package.Count < 8 || + obj->Package.Elements[0].Type != ACPI_TYPE_STRING || + obj->Package.Elements[1].Type != ACPI_TYPE_STRING || + obj->Package.Elements[2].Type != ACPI_TYPE_STRING || + obj->Package.Elements[3].Type != ACPI_TYPE_INTEGER || + obj->Package.Elements[4].Type != ACPI_TYPE_INTEGER || + obj->Package.Elements[5].Type != ACPI_TYPE_INTEGER || + obj->Package.Elements[6].Type != ACPI_TYPE_INTEGER || + obj->Package.Elements[7].Type != ACPI_TYPE_INTEGER) { + acpi_hp_free_buffer(&out); + return (-EINVAL); } - /* check if this matches our expectations based on limited knowledge */ - if (valuebase > 7 && obj->Package.Count > valuebase + 1 && - obj->Package.Elements[0].Type == ACPI_TYPE_STRING && - obj->Package.Elements[1].Type == ACPI_TYPE_STRING && - obj->Package.Elements[2].Type == ACPI_TYPE_STRING && - obj->Package.Elements[3].Type == ACPI_TYPE_INTEGER && - obj->Package.Elements[4].Type == ACPI_TYPE_INTEGER && - obj->Package.Elements[5].Type == ACPI_TYPE_INTEGER && - obj->Package.Elements[6].Type == ACPI_TYPE_INTEGER && - obj->Package.Elements[valuebase].Type == ACPI_TYPE_STRING && - obj->Package.Elements[valuebase+1].Type == ACPI_TYPE_INTEGER && - obj->Package.Count > valuebase + - obj->Package.Elements[valuebase+1].Integer.Value - ) { - enumbase = valuebase + 1; - if (detail & ACPI_HP_CMI_DETAIL_PATHS) { - strlcat(outbuf, acpi_hp_get_string_from_object( - &obj->Package.Elements[2], string_buffer, size), - outsize); - outlen += 48; - while (strlen(outbuf) < outlen) - strlcat(outbuf, " ", outsize); - } + /* Skip prerequisites and optionally array. */ + valuebase = 8 + obj->Package.Elements[7].Integer.Value; + if (obj->Package.Count <= valuebase) { + acpi_hp_free_buffer(&out); + return (-EINVAL); + } + if (obj->Package.Elements[valuebase].Type == ACPI_TYPE_INTEGER) + valuebase += 1 + obj->Package.Elements[valuebase].Integer.Value; + + /* Check if we have value and enum. */ + if (obj->Package.Count <= valuebase + 1 || + obj->Package.Elements[valuebase].Type != ACPI_TYPE_STRING || + obj->Package.Elements[valuebase+1].Type != ACPI_TYPE_INTEGER) { + acpi_hp_free_buffer(&out); + return (-EINVAL); + } + enumbase = valuebase + 1; + if (obj->Package.Count <= valuebase + + obj->Package.Elements[enumbase].Integer.Value) { + acpi_hp_free_buffer(&out); + return (-EINVAL); + } + + if (detail & ACPI_HP_CMI_DETAIL_PATHS) { strlcat(outbuf, acpi_hp_get_string_from_object( - &obj->Package.Elements[0], string_buffer, size), - outsize); - outlen += 43; + &obj->Package.Elements[2], string_buffer, size), outsize); + outlen += 48; while (strlen(outbuf) < outlen) strlcat(outbuf, " ", outsize); - strlcat(outbuf, acpi_hp_get_string_from_object( - &obj->Package.Elements[valuebase], string_buffer, - size), - outsize); - outlen += 21; - while (strlen(outbuf) < outlen) - strlcat(outbuf, " ", outsize); - for (i = 0; i < strlen(outbuf); ++i) - if (outbuf[i] == '\\') - outbuf[i] = '/'; - if (detail & ACPI_HP_CMI_DETAIL_ENUMS) { - for (i = enumbase + 1; i < enumbase + 1 + - obj->Package.Elements[enumbase].Integer.Value; - ++i) { - acpi_hp_get_string_from_object( - &obj->Package.Elements[i], string_buffer, - size); - if (strlen(string_buffer) > 1 || - (strlen(string_buffer) == 1 && - string_buffer[0] != ' ')) { - if (has_enums) - strlcat(outbuf, "/", outsize); - else - strlcat(outbuf, " (", outsize); - strlcat(outbuf, string_buffer, outsize); - has_enums = 1; - } + } + strlcat(outbuf, acpi_hp_get_string_from_object( + &obj->Package.Elements[0], string_buffer, size), outsize); + outlen += 43; + while (strlen(outbuf) < outlen) + strlcat(outbuf, " ", outsize); + strlcat(outbuf, acpi_hp_get_string_from_object( + &obj->Package.Elements[valuebase], string_buffer, size), outsize); + outlen += 21; + while (strlen(outbuf) < outlen) + strlcat(outbuf, " ", outsize); + for (i = 0; i < strlen(outbuf); ++i) + if (outbuf[i] == '\\') + outbuf[i] = '/'; + if (detail & ACPI_HP_CMI_DETAIL_ENUMS) { + for (i = enumbase + 1; i < enumbase + 1 + + obj->Package.Elements[enumbase].Integer.Value; ++i) { + acpi_hp_get_string_from_object( + &obj->Package.Elements[i], string_buffer, size); + if (strlen(string_buffer) > 1 || + (strlen(string_buffer) == 1 && + string_buffer[0] != ' ')) { + if (has_enums) + strlcat(outbuf, "/", outsize); + else + strlcat(outbuf, " (", outsize); + strlcat(outbuf, string_buffer, outsize); + has_enums = 1; } } - if (has_enums) - strlcat(outbuf, ")", outsize); - if (detail & ACPI_HP_CMI_DETAIL_FLAGS) { - strlcat(outbuf, obj->Package.Elements[3].Integer.Value? - " [ReadOnly]":"", outsize); - strlcat(outbuf, obj->Package.Elements[4].Integer.Value? - "":" [NOUI]", outsize); - strlcat(outbuf, obj->Package.Elements[5].Integer.Value? - " [RPP]":"", outsize); - } - *sequence = (UINT32) obj->Package.Elements[6].Integer.Value; } + if (has_enums) + strlcat(outbuf, ")", outsize); + if (detail & ACPI_HP_CMI_DETAIL_FLAGS) { + strlcat(outbuf, obj->Package.Elements[3].Integer.Value ? + " [ReadOnly]" : "", outsize); + strlcat(outbuf, obj->Package.Elements[4].Integer.Value ? + "" : " [NOUI]", outsize); + strlcat(outbuf, obj->Package.Elements[5].Integer.Value ? + " [RPP]" : "", outsize); + } + *sequence = (UINT32) obj->Package.Elements[6].Integer.Value; acpi_hp_free_buffer(&out); return (0); diff --git a/sys/dev/bhnd/bcma/bcma.c b/sys/dev/bhnd/bcma/bcma.c index 08808955ba0..7b4be6cb61b 100644 --- a/sys/dev/bhnd/bcma/bcma.c +++ b/sys/dev/bhnd/bcma/bcma.c @@ -274,7 +274,7 @@ bcma_is_hw_suspended(device_t dev, device_t child) return (true); } - if (rst & BMCA_DMP_RC_RESET) + if (rst & BCMA_DMP_RC_RESET) return (true); /* Is core clocked? */ @@ -367,11 +367,11 @@ bcma_suspend_hw(device_t dev, device_t child) /* Already in reset? */ rst = bhnd_bus_read_4(r, BCMA_DMP_RESETCTRL); - if (rst & BMCA_DMP_RC_RESET) + if (rst & BCMA_DMP_RC_RESET) return (0); /* Put core into reset */ - if ((error = bcma_dmp_write_reset(child, dinfo, BMCA_DMP_RC_RESET))) + if ((error = bcma_dmp_write_reset(child, dinfo, BCMA_DMP_RC_RESET))) return (error); /* Clear core flags */ diff --git a/sys/dev/bhnd/bcma/bcma_dmp.h b/sys/dev/bhnd/bcma/bcma_dmp.h index 0fd41a7a4f2..36f84f1388d 100644 --- a/sys/dev/bhnd/bcma/bcma_dmp.h +++ b/sys/dev/bhnd/bcma/bcma_dmp.h @@ -252,7 +252,7 @@ #define BCMA_DMP_IOST_MASK 0x0000FFFF /* resetctrl */ -#define BMCA_DMP_RC_RESET 0x00000001 +#define BCMA_DMP_RC_RESET 0x00000001 /* config */ #define BCMA_DMP_CFG_OOB 0x00000020 diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt.h new file mode 100644 index 00000000000..dee88885e8a --- /dev/null +++ b/sys/dev/bnxt/bnxt.h @@ -0,0 +1,568 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef _BNXT_H +#define _BNXT_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hsi_struct_def.h" + +/* PCI IDs */ +#define BROADCOM_VENDOR_ID 0x14E4 + +#define BCM57301 0x16c8 +#define BCM57302 0x16c9 +#define BCM57304 0x16ca +#define BCM57402 0x16d0 +#define BCM57404 0x16d1 +#define BCM57406 0x16d2 +#define BCM57402_NPAR 0x16d4 +#define BCM57407 0x16d5 +#define BCM57404_NPAR 0x16e7 +#define BCM57406_NPAR 0x16e8 +#define BCM57407_SFP 0x16e9 +#define BCM57304_VF 0x16cb +#define BCM57404_VF 0x16d3 + +#define CSUM_OFFLOAD (CSUM_IP_TSO|CSUM_IP6_TSO|CSUM_IP| \ + CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP| \ + CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP) + +#define BNXT_MAX_MTU 9000 + +/* Completion related defines */ +#define CMP_VALID(cmp, v_bit) \ + ((!!(((struct cmpl_base *)(cmp))->info3_v & htole32(CMPL_BASE_V))) == !!(v_bit) ) + +#define NEXT_CP_CONS_V(ring, cons, v_bit) do { \ + if (__predict_false(++(cons) == (ring)->ring_size)) \ + ((cons) = 0, (v_bit) = !v_bit); \ +} while (0) + +#define RING_NEXT(ring, idx) (__predict_false(idx + 1 == (ring)->ring_size) ? \ + 0 : idx + 1) + +#define CMPL_PREFETCH_NEXT(cpr, idx) \ + __builtin_prefetch(&((struct cmpl_base *)(cpr)->ring.vaddr)[((idx) +\ + (CACHE_LINE_SIZE / sizeof(struct cmpl_base))) & \ + ((cpr)->ring.ring_size - 1)]) + +/* + * If we update the index, a write barrier is needed after the write to ensure + * the completion ring has space before the RX/TX ring does. Since we can't + * make the RX and AG doorbells covered by the same barrier without remapping + * MSI-X vectors, we create the barrier over the enture doorbell bar. + * TODO: Remap the MSI-X vectors to allow a barrier to only cover the doorbells + * for a single ring group. + * + * A barrier of just the size of the write is used to ensure the ordering + * remains correct and no writes are lost. + */ +#define BNXT_CP_DISABLE_DB(ring) do { \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \ + BUS_SPACE_BARRIER_WRITE); \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, 0, \ + (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \ + bus_space_write_4((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \ + htole32(CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_MASK)); \ +} while (0) + +#define BNXT_CP_ENABLE_DB(ring) do { \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \ + BUS_SPACE_BARRIER_WRITE); \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, 0, \ + (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \ + bus_space_write_4((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \ + htole32(CMPL_DOORBELL_KEY_CMPL)); \ +} while (0) + +#define BNXT_CP_IDX_ENABLE_DB(ring, cons) do { \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \ + BUS_SPACE_BARRIER_WRITE); \ + bus_space_write_4((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \ + htole32(CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_IDX_VALID | \ + (cons))); \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, 0, \ + (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \ +} while (0) + +#define BNXT_CP_IDX_DISABLE_DB(ring, cons) do { \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \ + BUS_SPACE_BARRIER_WRITE); \ + bus_space_write_4((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, \ + htole32(CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_IDX_VALID | \ + CMPL_DOORBELL_MASK | (cons))); \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, 0, \ + (ring)->softc->doorbell_bar.size, BUS_SPACE_BARRIER_WRITE); \ +} while (0) + +#define BNXT_TX_DB(ring, idx) do { \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \ + BUS_SPACE_BARRIER_WRITE); \ + bus_space_write_4( \ + (ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, \ + (ring)->doorbell, htole32(TX_DOORBELL_KEY_TX | (idx))); \ +} while (0) + +#define BNXT_RX_DB(ring, idx) do { \ + bus_space_barrier((ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, (ring)->doorbell, 4, \ + BUS_SPACE_BARRIER_WRITE); \ + bus_space_write_4( \ + (ring)->softc->doorbell_bar.tag, \ + (ring)->softc->doorbell_bar.handle, \ + (ring)->doorbell, htole32(RX_DOORBELL_KEY_RX | (idx))); \ +} while (0) + +/* Lock macros */ +#define BNXT_HWRM_LOCK_INIT(_softc, _name) \ + mtx_init(&(_softc)->hwrm_lock, _name, "BNXT HWRM Lock", MTX_DEF) +#define BNXT_HWRM_LOCK(_softc) mtx_lock(&(_softc)->hwrm_lock) +#define BNXT_HWRM_UNLOCK(_softc) mtx_unlock(&(_softc)->hwrm_lock) +#define BNXT_HWRM_LOCK_DESTROY(_softc) mtx_destroy(&(_softc)->hwrm_lock) +#define BNXT_HWRM_LOCK_ASSERT(_softc) mtx_assert(&(_softc)->hwrm_lock, \ + MA_OWNED) + +/* Chip info */ +#define BNXT_TSO_SIZE UINT16_MAX + +/* NVRAM access */ +enum bnxt_nvm_directory_type { + BNX_DIR_TYPE_UNUSED = 0, + BNX_DIR_TYPE_PKG_LOG = 1, + BNX_DIR_TYPE_UPDATE = 2, + BNX_DIR_TYPE_CHIMP_PATCH = 3, + BNX_DIR_TYPE_BOOTCODE = 4, + BNX_DIR_TYPE_VPD = 5, + BNX_DIR_TYPE_EXP_ROM_MBA = 6, + BNX_DIR_TYPE_AVS = 7, + BNX_DIR_TYPE_PCIE = 8, + BNX_DIR_TYPE_PORT_MACRO = 9, + BNX_DIR_TYPE_APE_FW = 10, + BNX_DIR_TYPE_APE_PATCH = 11, + BNX_DIR_TYPE_KONG_FW = 12, + BNX_DIR_TYPE_KONG_PATCH = 13, + BNX_DIR_TYPE_BONO_FW = 14, + BNX_DIR_TYPE_BONO_PATCH = 15, + BNX_DIR_TYPE_TANG_FW = 16, + BNX_DIR_TYPE_TANG_PATCH = 17, + BNX_DIR_TYPE_BOOTCODE_2 = 18, + BNX_DIR_TYPE_CCM = 19, + BNX_DIR_TYPE_PCI_CFG = 20, + BNX_DIR_TYPE_TSCF_UCODE = 21, + BNX_DIR_TYPE_ISCSI_BOOT = 22, + BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24, + BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25, + BNX_DIR_TYPE_ISCSI_BOOT_CFG6 = 26, + BNX_DIR_TYPE_EXT_PHY = 27, + BNX_DIR_TYPE_SHARED_CFG = 40, + BNX_DIR_TYPE_PORT_CFG = 41, + BNX_DIR_TYPE_FUNC_CFG = 42, + BNX_DIR_TYPE_MGMT_CFG = 48, + BNX_DIR_TYPE_MGMT_DATA = 49, + BNX_DIR_TYPE_MGMT_WEB_DATA = 50, + BNX_DIR_TYPE_MGMT_WEB_META = 51, + BNX_DIR_TYPE_MGMT_EVENT_LOG = 52, + BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53 +}; + +enum bnxnvm_pkglog_field_index { + BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0, + BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1, + BNX_PKG_LOG_FIELD_IDX_PKG_VERSION = 2, + BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3, + BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM = 4, + BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5, + BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6 +}; + +#define BNX_DIR_ORDINAL_FIRST 0 +#define BNX_DIR_EXT_NONE 0 + +struct bnxt_bar_info { + struct resource *res; + bus_space_tag_t tag; + bus_space_handle_t handle; + bus_size_t size; + int rid; +}; + +struct bnxt_link_info { + uint8_t media_type; + uint8_t transceiver; + uint8_t phy_addr; + uint8_t phy_link_status; + uint8_t wire_speed; + uint8_t loop_back; + uint8_t link_up; + uint8_t last_link_up; + uint8_t duplex; + uint8_t last_duplex; + uint8_t pause; + uint8_t last_pause; + uint8_t auto_pause; + uint8_t force_pause; + uint8_t duplex_setting; + uint8_t auto_mode; +#define PHY_VER_LEN 3 + uint8_t phy_ver[PHY_VER_LEN]; + uint8_t phy_type; + uint16_t link_speed; + uint16_t support_speeds; + uint16_t auto_link_speeds; + uint16_t auto_link_speed; + uint16_t force_link_speed; + uint32_t preemphasis; + + /* copy of requested setting */ + uint8_t autoneg; +#define BNXT_AUTONEG_SPEED 1 +#define BNXT_AUTONEG_FLOW_CTRL 2 + uint8_t req_duplex; + uint8_t req_flow_ctrl; + uint16_t req_link_speed; +}; + +enum bnxt_cp_type { + BNXT_DEFAULT, + BNXT_TX, + BNXT_RX, + BNXT_SHARED +}; + +struct bnxt_cos_queue { + uint8_t id; + uint8_t profile; +}; + +struct bnxt_func_info { + uint32_t fw_fid; + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint16_t max_rsscos_ctxs; + uint16_t max_cp_rings; + uint16_t max_tx_rings; + uint16_t max_rx_rings; + uint16_t max_hw_ring_grps; + uint16_t max_irqs; + uint16_t max_l2_ctxs; + uint16_t max_vnics; + uint16_t max_stat_ctxs; +}; + +struct bnxt_pf_info { +#define BNXT_FIRST_PF_FID 1 +#define BNXT_FIRST_VF_FID 128 + uint8_t port_id; + uint32_t first_vf_id; + uint16_t active_vfs; + uint16_t max_vfs; + uint32_t max_encap_records; + uint32_t max_decap_records; + uint32_t max_tx_em_flows; + uint32_t max_tx_wm_flows; + uint32_t max_rx_em_flows; + uint32_t max_rx_wm_flows; + unsigned long *vf_event_bmap; + uint16_t hwrm_cmd_req_pages; + void *hwrm_cmd_req_addr[4]; + bus_addr_t hwrm_cmd_req_dma_addr[4]; +}; + +struct bnxt_vf_info { + uint16_t fw_fid; + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint16_t max_rsscos_ctxs; + uint16_t max_cp_rings; + uint16_t max_tx_rings; + uint16_t max_rx_rings; + uint16_t max_hw_ring_grps; + uint16_t max_l2_ctxs; + uint16_t max_irqs; + uint16_t max_vnics; + uint16_t max_stat_ctxs; + uint32_t vlan; +#define BNXT_VF_QOS 0x1 +#define BNXT_VF_SPOOFCHK 0x2 +#define BNXT_VF_LINK_FORCED 0x4 +#define BNXT_VF_LINK_UP 0x8 + uint32_t flags; + uint32_t func_flags; /* func cfg flags */ + uint32_t min_tx_rate; + uint32_t max_tx_rate; + void *hwrm_cmd_req_addr; + bus_addr_t hwrm_cmd_req_dma_addr; +}; + +#define BNXT_FLAG_VF (1<<1) + +#define BNXT_PF(softc) (!((softc)->flags & BNXT_FLAG_VF)) +#define BNXT_VF(softc) ((softc)->flags & BNXT_FLAG_VF) + +struct bnxt_vlan_tag { + SLIST_ENTRY(bnxt_vlan_tag) next; + uint16_t tpid; + uint16_t tag; +}; + +struct bnxt_vnic_info { + uint16_t id; + uint16_t def_ring_grp; + uint16_t cos_rule; + uint16_t lb_rule; + uint16_t mru; + + uint32_t rx_mask; + bool vlan_only; + struct iflib_dma_info mc_list; + int mc_list_count; +#define BNXT_MAX_MC_ADDRS 16 + + uint32_t flags; +#define BNXT_VNIC_FLAG_DEFAULT 0x01 +#define BNXT_VNIC_FLAG_BD_STALL 0x02 +#define BNXT_VNIC_FLAG_VLAN_STRIP 0x04 + + uint64_t filter_id; + uint32_t flow_id; + + uint16_t rss_id; + uint32_t rss_hash_type; + uint8_t rss_hash_key[HW_HASH_KEY_SIZE]; + struct iflib_dma_info rss_hash_key_tbl; + struct iflib_dma_info rss_grp_tbl; + SLIST_HEAD(vlan_head, bnxt_vlan_tag) vlan_tags; + struct iflib_dma_info vlan_tag_list; +}; + +struct bnxt_grp_info { + uint16_t stats_ctx; + uint16_t grp_id; + uint16_t rx_ring_id; + uint16_t cp_ring_id; + uint16_t ag_ring_id; +}; + +struct bnxt_ring { + uint64_t paddr; + vm_offset_t doorbell; + caddr_t vaddr; + struct bnxt_softc *softc; + uint32_t ring_size; /* Must be a power of two */ + uint16_t id; /* Logical ID */ + uint16_t phys_id; +}; + +struct bnxt_cp_ring { + struct bnxt_ring ring; + struct if_irq irq; + uint32_t cons; + bool v_bit; /* Value of valid bit */ + struct ctx_hw_stats *stats; + uint32_t stats_ctx_id; + uint32_t last_idx; /* Used by RX rings only + * set to the last read pidx + */ +}; + +struct bnxt_full_tpa_start { + struct rx_tpa_start_cmpl low; + struct rx_tpa_start_cmpl_hi high; +}; + +/* All the version information for the part */ +#define BNXT_VERSTR_SIZE (3*3+2+1) /* ie: "255.255.255\0" */ +#define BNXT_NAME_SIZE 17 +struct bnxt_ver_info { + uint8_t hwrm_if_major; + uint8_t hwrm_if_minor; + uint8_t hwrm_if_update; + char hwrm_if_ver[BNXT_VERSTR_SIZE]; + char driver_hwrm_if_ver[BNXT_VERSTR_SIZE]; + char hwrm_fw_ver[BNXT_VERSTR_SIZE]; + char mgmt_fw_ver[BNXT_VERSTR_SIZE]; + char netctrl_fw_ver[BNXT_VERSTR_SIZE]; + char roce_fw_ver[BNXT_VERSTR_SIZE]; + char phy_ver[BNXT_VERSTR_SIZE]; + char pkg_ver[64]; + + char hwrm_fw_name[BNXT_NAME_SIZE]; + char mgmt_fw_name[BNXT_NAME_SIZE]; + char netctrl_fw_name[BNXT_NAME_SIZE]; + char roce_fw_name[BNXT_NAME_SIZE]; + char phy_vendor[BNXT_NAME_SIZE]; + char phy_partnumber[BNXT_NAME_SIZE]; + + uint16_t chip_num; + uint8_t chip_rev; + uint8_t chip_metal; + uint8_t chip_bond_id; + uint8_t chip_type; + + uint8_t hwrm_min_major; + uint8_t hwrm_min_minor; + uint8_t hwrm_min_update; + + struct sysctl_ctx_list ver_ctx; + struct sysctl_oid *ver_oid; +}; + +struct bnxt_nvram_info { + uint16_t mfg_id; + uint16_t device_id; + uint32_t sector_size; + uint32_t size; + uint32_t reserved_size; + uint32_t available_size; + + struct sysctl_ctx_list nvm_ctx; + struct sysctl_oid *nvm_oid; +}; + +struct bnxt_softc { + device_t dev; + if_ctx_t ctx; + if_softc_ctx_t scctx; + if_shared_ctx_t sctx; + struct ifmedia *media; + + struct bnxt_bar_info hwrm_bar; + struct bnxt_bar_info doorbell_bar; + struct bnxt_link_info link_info; +#define BNXT_FLAG_NPAR 1 + uint32_t flags; + uint32_t total_msix; + + struct bnxt_func_info func; + struct bnxt_pf_info pf; + struct bnxt_vf_info vf; + + uint16_t hwrm_cmd_seq; + uint32_t hwrm_cmd_timeo; /* milliseconds */ + struct iflib_dma_info hwrm_cmd_resp; + /* Interrupt info for HWRM */ + struct if_irq irq; + struct mtx hwrm_lock; + uint16_t hwrm_max_req_len; + +#define BNXT_MAX_QUEUE 8 + uint8_t max_tc; + struct bnxt_cos_queue q_info[BNXT_MAX_QUEUE]; + + struct iflib_dma_info hw_rx_port_stats; + struct iflib_dma_info hw_tx_port_stats; + struct rx_port_stats *rx_port_stats; + struct tx_port_stats *tx_port_stats; + + int num_cp_rings; + + struct bnxt_ring *tx_rings; + struct bnxt_cp_ring *tx_cp_rings; + struct iflib_dma_info tx_stats; + int ntxqsets; + + struct bnxt_vnic_info vnic_info; + struct bnxt_ring *ag_rings; + struct bnxt_ring *rx_rings; + struct bnxt_cp_ring *rx_cp_rings; + struct bnxt_grp_info *grp_info; + struct iflib_dma_info rx_stats; + int nrxqsets; + + struct bnxt_cp_ring def_cp_ring; + struct iflib_dma_info def_cp_ring_mem; + struct grouptask def_cp_task; + + struct sysctl_ctx_list hw_stats; + struct sysctl_oid *hw_stats_oid; + + struct bnxt_full_tpa_start *tpa_start; + struct bnxt_ver_info *ver_info; + struct bnxt_nvram_info *nvm_info; +}; + +struct bnxt_filter_info { + STAILQ_ENTRY(bnxt_filter_info) next; + uint64_t fw_l2_filter_id; +#define INVALID_MAC_INDEX ((uint16_t)-1) + uint16_t mac_index; + + /* Filter Characteristics */ + uint32_t flags; + uint32_t enables; + uint8_t l2_addr[ETHER_ADDR_LEN]; + uint8_t l2_addr_mask[ETHER_ADDR_LEN]; + uint16_t l2_ovlan; + uint16_t l2_ovlan_mask; + uint16_t l2_ivlan; + uint16_t l2_ivlan_mask; + uint8_t t_l2_addr[ETHER_ADDR_LEN]; + uint8_t t_l2_addr_mask[ETHER_ADDR_LEN]; + uint16_t t_l2_ovlan; + uint16_t t_l2_ovlan_mask; + uint16_t t_l2_ivlan; + uint16_t t_l2_ivlan_mask; + uint8_t tunnel_type; + uint16_t mirror_vnic_id; + uint32_t vni; + uint8_t pri_hint; + uint64_t l2_filter_id_hint; +}; + +/* Function declarations */ +void bnxt_report_link(struct bnxt_softc *softc); +bool bnxt_check_hwrm_version(struct bnxt_softc *softc); + +#endif /* _BNXT_H */ diff --git a/sys/dev/bnxt/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_hwrm.c new file mode 100644 index 00000000000..a6c5cf17b1a --- /dev/null +++ b/sys/dev/bnxt/bnxt_hwrm.c @@ -0,0 +1,1485 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include "bnxt.h" +#include "bnxt_hwrm.h" +#include "hsi_struct_def.h" + +static int bnxt_hwrm_err_map(uint16_t err); +static inline int _is_valid_ether_addr(uint8_t *); +static inline void get_random_ether_addr(uint8_t *); +static void bnxt_hwrm_set_link_common(struct bnxt_softc *softc, + struct hwrm_port_phy_cfg_input *req); +static void bnxt_hwrm_set_pause_common(struct bnxt_softc *softc, + struct hwrm_port_phy_cfg_input *req); +static void bnxt_hwrm_set_eee(struct bnxt_softc *softc, + struct hwrm_port_phy_cfg_input *req); +static int _hwrm_send_message(struct bnxt_softc *, void *, uint32_t); +static int hwrm_send_message(struct bnxt_softc *, void *, uint32_t); +static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t); + +/* NVRam stuff has a five minute timeout */ +#define BNXT_NVM_TIMEO (5 * 60 * 1000) + +static int +bnxt_hwrm_err_map(uint16_t err) +{ + int rc; + + switch (err) { + case HWRM_ERR_CODE_SUCCESS: + return 0; + case HWRM_ERR_CODE_INVALID_PARAMS: + case HWRM_ERR_CODE_INVALID_FLAGS: + case HWRM_ERR_CODE_INVALID_ENABLES: + return EINVAL; + case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED: + return EACCES; + case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR: + return ENOMEM; + case HWRM_ERR_CODE_CMD_NOT_SUPPORTED: + return ENOSYS; + case HWRM_ERR_CODE_FAIL: + return EIO; + case HWRM_ERR_CODE_HWRM_ERROR: + case HWRM_ERR_CODE_UNKNOWN_ERR: + default: + return EDOOFUS; + } + + return rc; +} + +int +bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc) +{ + int rc; + + rc = iflib_dma_alloc(softc->ctx, PAGE_SIZE, &softc->hwrm_cmd_resp, + BUS_DMA_NOWAIT); + return rc; +} + +void +bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc) +{ + if (softc->hwrm_cmd_resp.idi_vaddr) + iflib_dma_free(&softc->hwrm_cmd_resp); + softc->hwrm_cmd_resp.idi_vaddr = NULL; + return; +} + +static void +bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request, + uint16_t req_type) +{ + struct input *req = request; + + req->req_type = htole16(req_type); + req->cmpl_ring = 0xffff; + req->target_id = 0xffff; + req->resp_addr = htole64(softc->hwrm_cmd_resp.idi_paddr); +} + +static int +_hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) +{ + struct input *req = msg; + struct hwrm_err_output *resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + uint32_t *data = msg; + int i; + uint16_t cp_ring_id; + uint8_t *valid; + uint16_t err; + + /* TODO: DMASYNC in here. */ + req->seq_id = htole16(softc->hwrm_cmd_seq++); + memset(resp, 0, PAGE_SIZE); + cp_ring_id = le16toh(req->cmpl_ring); + + /* Write request msg to hwrm channel */ + for (i = 0; i < msg_len; i += 4) { + bus_space_write_4(softc->hwrm_bar.tag, + softc->hwrm_bar.handle, + i, *data); + data++; + } + + /* Clear to the end of the request buffer */ + for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4) + bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle, + i, 0); + + /* Ring channel doorbell */ + bus_space_write_4(softc->hwrm_bar.tag, + softc->hwrm_bar.handle, + 0x100, htole32(1)); + + /* Check if response len is updated */ + for (i = 0; i < softc->hwrm_cmd_timeo; i++) { + if (resp->resp_len && resp->resp_len <= 4096) + break; + DELAY(1000); + } + if (i >= softc->hwrm_cmd_timeo) { + device_printf(softc->dev, + "Timeout sending %s: (timeout: %u) seq: %d\n", + GET_HWRM_REQ_TYPE(req->req_type), softc->hwrm_cmd_timeo, + le16toh(req->seq_id)); + return ETIMEDOUT; + } + /* Last byte of resp contains the valid key */ + valid = (uint8_t *)resp + resp->resp_len - 1; + for (i = 0; i < softc->hwrm_cmd_timeo; i++) { + if (*valid == HWRM_RESP_VALID_KEY) + break; + DELAY(1000); + } + if (i >= softc->hwrm_cmd_timeo) { + device_printf(softc->dev, "Timeout sending %s: " + "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n", + GET_HWRM_REQ_TYPE(req->req_type), + softc->hwrm_cmd_timeo, le16toh(req->req_type), + le16toh(req->seq_id), msg_len, + *valid); + return ETIMEDOUT; + } + + err = le16toh(resp->error_code); + if (err) { + /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */ + if (err != HWRM_ERR_CODE_FAIL) { + device_printf(softc->dev, + "%s command returned %s error.\n", + GET_HWRM_REQ_TYPE(req->req_type), + GET_HWRM_ERROR_CODE(err)); + } + return bnxt_hwrm_err_map(err); + } + + return 0; +} + +static int +hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) +{ + int rc; + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, msg, msg_len); + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc) +{ + struct hwrm_queue_qportcfg_input req = {0}; + struct hwrm_queue_qportcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + + int rc = 0; + uint8_t *qptr; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto qportcfg_exit; + + if (!resp->max_configurable_queues) { + rc = -EINVAL; + goto qportcfg_exit; + } + softc->max_tc = resp->max_configurable_queues; + if (softc->max_tc > BNXT_MAX_QUEUE) + softc->max_tc = BNXT_MAX_QUEUE; + + qptr = &resp->queue_id0; + for (int i = 0; i < softc->max_tc; i++) { + softc->q_info[i].id = *qptr++; + softc->q_info[i].profile = *qptr++; + } + +qportcfg_exit: + BNXT_HWRM_UNLOCK(softc); + return (rc); +} + + +int +bnxt_hwrm_ver_get(struct bnxt_softc *softc) +{ + struct hwrm_ver_get_input req = {0}; + struct hwrm_ver_get_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + const char nastr[] = ""; + const char naver[] = ""; + + softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN; + softc->hwrm_cmd_timeo = 1000; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET); + + req.hwrm_intf_maj = HWRM_VERSION_MAJOR; + req.hwrm_intf_min = HWRM_VERSION_MINOR; + req.hwrm_intf_upd = HWRM_VERSION_UPDATE; + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d", + resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd); + softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj; + softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min; + softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd; + snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d", + resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld); + strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR, + BNXT_VERSTR_SIZE); + strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name, + BNXT_NAME_SIZE); + + if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 && + resp->mgmt_fw_bld == 0) { + strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE); + strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE); + } + else { + snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE, + "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min, + resp->mgmt_fw_bld); + strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name, + BNXT_NAME_SIZE); + } + if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 && + resp->netctrl_fw_bld == 0) { + strlcpy(softc->ver_info->netctrl_fw_ver, naver, + BNXT_VERSTR_SIZE); + strlcpy(softc->ver_info->netctrl_fw_name, nastr, + BNXT_NAME_SIZE); + } + else { + snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE, + "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min, + resp->netctrl_fw_bld); + strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name, + BNXT_NAME_SIZE); + } + if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 && + resp->roce_fw_bld == 0) { + strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE); + strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE); + } + else { + snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE, + "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min, + resp->roce_fw_bld); + strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name, + BNXT_NAME_SIZE); + } + softc->ver_info->chip_num = le16toh(resp->chip_num); + softc->ver_info->chip_rev = resp->chip_rev; + softc->ver_info->chip_metal = resp->chip_metal; + softc->ver_info->chip_bond_id = resp->chip_bond_id; + softc->ver_info->chip_type = resp->chip_platform_type; + + if (resp->max_req_win_len) + softc->hwrm_max_req_len = le16toh(resp->max_req_win_len); + if (resp->def_req_timeout) + softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout); + +fail: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc) +{ + struct hwrm_func_drv_rgtr_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR); + + req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER | + HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE); + req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD); + + req.ver_maj = __FreeBSD_version / 100000; + req.ver_min = (__FreeBSD_version / 1000) % 100; + req.ver_upd = (__FreeBSD_version / 100) % 10; + + return hwrm_send_message(softc, &req, sizeof(req)); +} + + +int +bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown) +{ + struct hwrm_func_drv_unrgtr_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR); + if (shutdown == true) + req.flags |= + HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN; + return hwrm_send_message(softc, &req, sizeof(req)); +} + + +static inline int +_is_valid_ether_addr(uint8_t *addr) +{ + char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; + + if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) + return (FALSE); + + return (TRUE); +} + +static inline void +get_random_ether_addr(uint8_t *addr) +{ + uint8_t temp[ETHER_ADDR_LEN]; + + arc4rand(&temp, sizeof(temp), 0); + temp[0] &= 0xFE; + temp[0] |= 0x02; + bcopy(temp, addr, sizeof(temp)); +} + +int +bnxt_hwrm_func_qcaps(struct bnxt_softc *softc) +{ + int rc = 0; + struct hwrm_func_qcaps_input req = {0}; + struct hwrm_func_qcaps_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct bnxt_func_info *func = &softc->func; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS); + req.fid = htole16(0xffff); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + func->fw_fid = le16toh(resp->fid); + memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN); + func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx); + func->max_cp_rings = le16toh(resp->max_cmpl_rings); + func->max_tx_rings = le16toh(resp->max_tx_rings); + func->max_rx_rings = le16toh(resp->max_rx_rings); + func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps); + if (!func->max_hw_ring_grps) + func->max_hw_ring_grps = func->max_tx_rings; + func->max_l2_ctxs = le16toh(resp->max_l2_ctxs); + func->max_vnics = le16toh(resp->max_vnics); + func->max_stat_ctxs = le16toh(resp->max_stat_ctx); + if (BNXT_PF(softc)) { + struct bnxt_pf_info *pf = &softc->pf; + + pf->port_id = le16toh(resp->port_id); + pf->first_vf_id = le16toh(resp->first_vf_id); + pf->max_vfs = le16toh(resp->max_vfs); + pf->max_encap_records = le32toh(resp->max_encap_records); + pf->max_decap_records = le32toh(resp->max_decap_records); + pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows); + pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows); + pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows); + pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows); + } + if (!_is_valid_ether_addr(func->mac_addr)) { + device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n"); + get_random_ether_addr(func->mac_addr); + } + +fail: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_func_reset(struct bnxt_softc *softc) +{ + struct hwrm_func_reset_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET); + req.enables = 0; + + return hwrm_send_message(softc, &req, sizeof(req)); +} + +static void +bnxt_hwrm_set_link_common(struct bnxt_softc *softc, + struct hwrm_port_phy_cfg_input *req) +{ + uint8_t autoneg = softc->link_info.autoneg; + uint16_t fw_link_speed = softc->link_info.req_link_speed; + + if (autoneg & BNXT_AUTONEG_SPEED) { + req->auto_mode |= + HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS; + + req->enables |= + htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE); + req->flags |= + htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG); + } else { + req->force_link_speed = htole16(fw_link_speed); + req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE); + } + + /* tell chimp that the setting takes effect immediately */ + req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY); +} + + +static void +bnxt_hwrm_set_pause_common(struct bnxt_softc *softc, + struct hwrm_port_phy_cfg_input *req) +{ + if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) { + req->auto_pause = + HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE; + if (softc->link_info.req_flow_ctrl & + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) + req->auto_pause |= + HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX; + if (softc->link_info.req_flow_ctrl & + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) + req->auto_pause |= + HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX; + req->enables |= + htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE); + } else { + if (softc->link_info.req_flow_ctrl & + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) + req->force_pause |= + HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX; + if (softc->link_info.req_flow_ctrl & + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) + req->force_pause |= + HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX; + req->enables |= + htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE); + req->auto_pause = req->force_pause; + req->enables |= htole32( + HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE); + } +} + + +/* JFV this needs interface connection */ +static void +bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input *req) +{ + /* struct ethtool_eee *eee = &softc->eee; */ + bool eee_enabled = false; + + if (eee_enabled) { +#if 0 + uint16_t eee_speeds; + uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE; + + if (eee->tx_lpi_enabled) + flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI; + + req->flags |= htole32(flags); + eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised); + req->eee_link_speed_mask = htole16(eee_speeds); + req->tx_lpi_timer = htole32(eee->tx_lpi_timer); +#endif + } else { + req->flags |= + htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE); + } +} + + +int +bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause, + bool set_eee) +{ + struct hwrm_port_phy_cfg_input req = {0}; + + if (softc->flags & BNXT_FLAG_NPAR) + return ENOTSUP; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG); + if (set_pause) + bnxt_hwrm_set_pause_common(softc, &req); + + bnxt_hwrm_set_link_common(softc, &req); + if (set_eee) + bnxt_hwrm_set_eee(softc, &req); + return hwrm_send_message(softc, &req, sizeof(req)); +} + + +int +bnxt_hwrm_set_pause(struct bnxt_softc *softc) +{ + struct hwrm_port_phy_cfg_input req = {0}; + int rc; + + if (softc->flags & BNXT_FLAG_NPAR) + return ENOTSUP; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG); + bnxt_hwrm_set_pause_common(softc, &req); + + if (softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) + bnxt_hwrm_set_link_common(softc, &req); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (!rc && !(softc->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)) { + /* since changing of pause setting doesn't trigger any link + * change event, the driver needs to update the current pause + * result upon successfully return of the phy_cfg command */ + softc->link_info.pause = + softc->link_info.force_pause = softc->link_info.req_flow_ctrl; + softc->link_info.auto_pause = 0; + bnxt_report_link(softc); + } + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic) +{ + struct hwrm_vnic_cfg_input req = {0}; + struct hwrm_vnic_cfg_output *resp; + + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG); + + if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT) + req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT); + if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL) + req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE); + if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP) + req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE); + req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP | + HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE | + HWRM_VNIC_CFG_INPUT_ENABLES_MRU); + req.vnic_id = htole16(vnic->id); + req.dflt_ring_grp = htole16(vnic->def_ring_grp); + req.rss_rule = htole16(vnic->rss_id); + req.cos_rule = htole16(vnic->cos_rule); + req.lb_rule = htole16(vnic->lb_rule); + req.mru = htole16(vnic->mru); + + return hwrm_send_message(softc, &req, sizeof(req)); +} + +int +bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic) +{ + struct hwrm_vnic_alloc_input req = {0}; + struct hwrm_vnic_alloc_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + + if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) { + device_printf(softc->dev, + "Attempt to re-allocate vnic %04x\n", vnic->id); + return EDOOFUS; + } + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC); + + if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT) + req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + vnic->id = le32toh(resp->vnic_id); + +fail: + BNXT_HWRM_UNLOCK(softc); + return (rc); +} + +int +bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id) +{ + struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0}; + struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + + if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) { + device_printf(softc->dev, + "Attempt to re-allocate vnic ctx %04x\n", *ctx_id); + return EDOOFUS; + } + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + *ctx_id = le32toh(resp->rss_cos_lb_ctx_id); + +fail: + BNXT_HWRM_UNLOCK(softc); + return (rc); +} + +int +bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp) +{ + struct hwrm_ring_grp_alloc_input req = {0}; + struct hwrm_ring_grp_alloc_output *resp; + int rc = 0; + + if (grp->grp_id != (uint16_t)HWRM_NA_SIGNATURE) { + device_printf(softc->dev, + "Attempt to re-allocate ring group %04x\n", grp->grp_id); + return EDOOFUS; + } + + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC); + req.cr = htole16(grp->cp_ring_id); + req.rr = htole16(grp->rx_ring_id); + req.ar = htole16(grp->ag_ring_id); + req.sc = htole16(grp->stats_ctx); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + grp->grp_id = le32toh(resp->ring_group_id); + +fail: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +/* + * Ring allocation message to the firmware + */ +int +bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type, + struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id, + bool irq) +{ + struct hwrm_ring_alloc_input req = {0}; + struct hwrm_ring_alloc_output *resp; + int rc; + + if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) { + device_printf(softc->dev, + "Attempt to re-allocate ring %04x\n", ring->phys_id); + return EDOOFUS; + } + + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC); + req.enables = htole32(0); + req.fbo = htole32(0); + + if (stat_ctx_id != HWRM_NA_SIGNATURE) { + req.enables |= htole32( + HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID); + req.stat_ctx_id = htole32(stat_ctx_id); + } + req.ring_type = type; + req.page_tbl_addr = htole64(ring->paddr); + req.length = htole32(ring->ring_size); + req.logical_id = htole16(ring->id); + req.cmpl_ring_id = htole16(cmpl_ring_id); + req.queue_id = htole16(softc->q_info[0].id); +#if 0 + /* MODE_POLL appears to crash the firmware */ + if (irq) + req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; + else + req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL; +#else + req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX; +#endif + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + ring->phys_id = le16toh(resp->ring_id); + +fail: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr, + uint64_t paddr) +{ + struct hwrm_stat_ctx_alloc_input req = {0}; + struct hwrm_stat_ctx_alloc_output *resp; + int rc = 0; + + if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) { + device_printf(softc->dev, + "Attempt to re-allocate stats ctx %08x\n", + cpr->stats_ctx_id); + return EDOOFUS; + } + + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC); + + req.update_period_ms = htole32(1000); + req.stats_dma_addr = htole64(paddr); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + cpr->stats_ctx_id = le32toh(resp->stat_ctx_id); + +fail: + BNXT_HWRM_UNLOCK(softc); + + return rc; +} + +int +bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc, + struct bnxt_vnic_info *vnic) +{ + struct hwrm_cfa_l2_set_rx_mask_input req = {0}; + struct bnxt_vlan_tag *tag; + uint32_t *tags; + uint32_t num_vlan_tags = 0;; + uint32_t i; + uint32_t mask = vnic->rx_mask; + int rc; + + SLIST_FOREACH(tag, &vnic->vlan_tags, next) + num_vlan_tags++; + + if (num_vlan_tags) { + if (!(mask & + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) { + if (!vnic->vlan_only) + mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN; + else + mask |= + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY; + } + if (vnic->vlan_tag_list.idi_vaddr) { + iflib_dma_free(&vnic->vlan_tag_list); + vnic->vlan_tag_list.idi_vaddr = NULL; + } + rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags, + &vnic->vlan_tag_list, BUS_DMA_NOWAIT); + if (rc) + return rc; + tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr; + + i = 0; + SLIST_FOREACH(tag, &vnic->vlan_tags, next) { + tags[i] = htole32((tag->tpid << 16) | tag->tag); + i++; + } + } + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK); + + req.vnic_id = htole32(vnic->id); + req.mask = htole32(mask); + req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr); + req.num_mc_entries = htole32(vnic->mc_list_count); + req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr); + req.num_vlan_tags = htole32(num_vlan_tags); + return hwrm_send_message(softc, &req, sizeof(req)); +} + + +int +bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic) +{ + struct hwrm_cfa_l2_filter_alloc_input req = {0}; + struct hwrm_cfa_l2_filter_alloc_output *resp; + uint32_t enables = 0; + int rc = 0; + + if (vnic->filter_id != -1) { + device_printf(softc->dev, + "Attempt to re-allocate l2 ctx filter\n"); + return EDOOFUS; + } + + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC); + + req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX); + enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR + | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK + | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID; + req.enables = htole32(enables); + req.dst_id = htole16(vnic->id); + memcpy(req.l2_addr, if_getlladdr(iflib_get_ifp(softc->ctx)), + ETHER_ADDR_LEN); + memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask)); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto fail; + + vnic->filter_id = le64toh(resp->l2_filter_id); + vnic->flow_id = le64toh(resp->flow_id); + +fail: + BNXT_HWRM_UNLOCK(softc); + return (rc); +} + +int +bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic, + uint32_t hash_type) +{ + struct hwrm_vnic_rss_cfg_input req = {0}; + struct hwrm_vnic_rss_cfg_output *resp; + + resp = (void *)softc->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG); + + req.hash_type = htole32(hash_type); + req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr); + req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr); + req.rss_ctx_idx = htole16(vnic->rss_id); + + return hwrm_send_message(softc, &req, sizeof(req)); +} + +int +bnxt_hwrm_func_cfg(struct bnxt_softc *softc) +{ + struct hwrm_func_cfg_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG); + + req.fid = 0xffff; + req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR); + + req.async_event_cr = softc->def_cp_ring.ring.phys_id; + + return hwrm_send_message(softc, &req, sizeof(req)); +} + +int +bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic, + uint32_t flags) +{ + struct hwrm_vnic_tpa_cfg_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG); + + req.flags = htole32(flags); + req.vnic_id = htole16(vnic->id); + req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS | + HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS | + /* HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER | */ + HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN); + /* TODO: Calculate this based on ring size? */ + req.max_agg_segs = htole16(3); + /* Base this in the allocated TPA start size... */ + req.max_aggs = htole16(2); + /* + * TODO: max_agg_timer? + * req.mag_agg_timer = htole32(XXX); + */ + req.min_agg_len = htole32(0); + + return hwrm_send_message(softc, &req, sizeof(req)); +} + +int +bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type, + uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index, + uint8_t search_opt, uint32_t *data_length, uint32_t *item_length, + uint32_t *fw_ver) +{ + struct hwrm_nvm_find_dir_entry_input req = {0}; + struct hwrm_nvm_find_dir_entry_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc = 0; + uint32_t old_timeo; + + MPASS(ordinal); + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY); + if (use_index) { + req.enables = htole32( + HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID); + req.dir_idx = htole16(*index); + } + req.dir_type = htole16(type); + req.dir_ordinal = htole16(*ordinal); + req.dir_ext = htole16(ext); + req.opt_ordinal = search_opt; + + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + if (rc) + goto exit; + + if (item_length) + *item_length = le32toh(resp->dir_item_length); + if (data_length) + *data_length = le32toh(resp->dir_data_length); + if (fw_ver) + *fw_ver = le32toh(resp->fw_ver); + *ordinal = le16toh(resp->dir_ordinal); + if (index) + *index = le16toh(resp->dir_idx); + +exit: + BNXT_HWRM_UNLOCK(softc); + return (rc); +} + +int +bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset, + uint32_t length, struct iflib_dma_info *data) +{ + struct hwrm_nvm_read_input req = {0}; + int rc; + uint32_t old_timeo; + + if (length > data->idi_size) { + rc = EINVAL; + goto exit; + } + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ); + req.host_dest_addr = htole64(data->idi_paddr); + req.dir_idx = htole16(index); + req.offset = htole32(offset); + req.len = htole32(length); + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + BNXT_HWRM_UNLOCK(softc); + if (rc) + goto exit; + bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD); + + goto exit; + +exit: + return rc; +} + +int +bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t offset, + void *data, bool cpyin, uint32_t length) +{ + struct hwrm_nvm_modify_input req = {0}; + struct iflib_dma_info dma_data; + int rc; + uint32_t old_timeo; + + if (length == 0 || !data) + return EINVAL; + rc = iflib_dma_alloc(softc->ctx, length, &dma_data, + BUS_DMA_NOWAIT); + if (rc) + return ENOMEM; + if (cpyin) { + rc = copyin(data, dma_data.idi_vaddr, length); + if (rc) + goto exit; + } + else + memcpy(dma_data.idi_vaddr, data, length); + bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY); + req.host_src_addr = htole64(dma_data.idi_paddr); + req.dir_idx = htole16(index); + req.offset = htole32(offset); + req.len = htole32(length); + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + BNXT_HWRM_UNLOCK(softc); + +exit: + iflib_dma_free(&dma_data); + return rc; +} + +int +bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor, + uint8_t *selfreset) +{ + struct hwrm_fw_reset_input req = {0}; + struct hwrm_fw_reset_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + + MPASS(selfreset); + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET); + req.embedded_proc_type = processor; + req.selfrst_status = *selfreset; + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto exit; + *selfreset = resp->selfrst_status; + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset) +{ + struct hwrm_fw_qstatus_input req = {0}; + struct hwrm_fw_qstatus_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + + MPASS(selfreset); + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS); + req.embedded_proc_type = type; + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto exit; + *selfreset = resp->selfrst_status; + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin, + uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr, + uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length, + uint16_t *index) +{ + struct hwrm_nvm_write_input req = {0}; + struct hwrm_nvm_write_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + struct iflib_dma_info dma_data; + int rc; + uint32_t old_timeo; + + if (data_length) { + rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data, + BUS_DMA_NOWAIT); + if (rc) + return ENOMEM; + if (cpyin) { + rc = copyin(data, dma_data.idi_vaddr, data_length); + if (rc) + goto early_exit; + } + else + memcpy(dma_data.idi_vaddr, data, data_length); + bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + } + else + dma_data.idi_paddr = 0; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE); + + req.host_src_addr = htole64(dma_data.idi_paddr); + req.dir_type = htole16(type); + req.dir_ordinal = htole16(ordinal); + req.dir_ext = htole16(ext); + req.dir_attr = htole16(attr); + req.dir_data_length = htole32(data_length); + req.option = htole16(option); + if (keep) { + req.flags = + htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG); + } + if (item_length) + req.dir_item_length = htole32(*item_length); + + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + if (rc) + goto exit; + if (item_length) + *item_length = le32toh(resp->dir_item_length); + if (index) + *index = le16toh(resp->dir_idx); + +exit: + BNXT_HWRM_UNLOCK(softc); +early_exit: + if (data_length) + iflib_dma_free(&dma_data); + return rc; +} + +int +bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index) +{ + struct hwrm_nvm_erase_dir_entry_input req = {0}; + uint32_t old_timeo; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY); + req.dir_idx = htole16(index); + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries, + uint32_t *entry_length) +{ + struct hwrm_nvm_get_dir_info_input req = {0}; + struct hwrm_nvm_get_dir_info_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + uint32_t old_timeo; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO); + + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + if (rc) + goto exit; + + if (entries) + *entries = le32toh(resp->entries); + if (entry_length) + *entry_length = le32toh(resp->entry_length); + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries, + uint32_t *entry_length, struct iflib_dma_info *dma_data) +{ + struct hwrm_nvm_get_dir_entries_input req = {0}; + uint32_t ent; + uint32_t ent_len; + int rc; + uint32_t old_timeo; + + if (!entries) + entries = &ent; + if (!entry_length) + entry_length = &ent_len; + + rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length); + if (rc) + goto exit; + if (*entries * *entry_length > dma_data->idi_size) { + rc = EINVAL; + goto exit; + } + + /* + * TODO: There's a race condition here that could blow up DMA memory... + * we need to allocate the max size, not the currently in use + * size. The command should totally have a max size here. + */ + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES); + req.host_dest_addr = htole64(dma_data->idi_paddr); + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + BNXT_HWRM_UNLOCK(softc); + if (rc) + goto exit; + bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map, + BUS_DMASYNC_POSTWRITE); + +exit: + return rc; +} + +int +bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id, + uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size, + uint32_t *reserved_size, uint32_t *available_size) +{ + struct hwrm_nvm_get_dev_info_input req = {0}; + struct hwrm_nvm_get_dev_info_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + uint32_t old_timeo; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO); + + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + if (rc) + goto exit; + + if (mfg_id) + *mfg_id = le16toh(resp->manufacturer_id); + if (device_id) + *device_id = le16toh(resp->device_id); + if (sector_size) + *sector_size = le32toh(resp->sector_size); + if (nvram_size) + *nvram_size = le32toh(resp->nvram_size); + if (reserved_size) + *reserved_size = le32toh(resp->reserved_size); + if (available_size) + *available_size = le32toh(resp->available_size); + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc, + uint32_t install_type, uint64_t *installed_items, uint8_t *result, + uint8_t *problem_item, uint8_t *reset_required) +{ + struct hwrm_nvm_install_update_input req = {0}; + struct hwrm_nvm_install_update_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + uint32_t old_timeo; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE); + req.install_type = htole32(install_type); + + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + if (rc) + goto exit; + + if (installed_items) + *installed_items = le32toh(resp->installed_items); + if (result) + *result = resp->result; + if (problem_item) + *problem_item = resp->problem_item; + if (reset_required) + *reset_required = resp->reset_required; + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type, + uint16_t ordinal, uint16_t ext) +{ + struct hwrm_nvm_verify_update_input req = {0}; + uint32_t old_timeo; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE); + + req.dir_type = htole16(type); + req.dir_ordinal = htole16(ordinal); + req.dir_ext = htole16(ext); + + BNXT_HWRM_LOCK(softc); + old_timeo = softc->hwrm_cmd_timeo; + softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO; + rc = _hwrm_send_message(softc, &req, sizeof(req)); + softc->hwrm_cmd_timeo = old_timeo; + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month, + uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second, + uint16_t *millisecond, uint16_t *zone) +{ + struct hwrm_fw_get_time_input req = {0}; + struct hwrm_fw_get_time_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME); + + BNXT_HWRM_LOCK(softc); + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto exit; + + if (year) + *year = le16toh(resp->year); + if (month) + *month = resp->month; + if (day) + *day = resp->day; + if (hour) + *hour = resp->hour; + if (minute) + *minute = resp->minute; + if (second) + *second = resp->second; + if (millisecond) + *millisecond = le16toh(resp->millisecond); + if (zone) + *zone = le16toh(resp->zone); + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} + +int +bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month, + uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, + uint16_t millisecond, uint16_t zone) +{ + struct hwrm_fw_set_time_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME); + + req.year = htole16(year); + req.month = month; + req.day = day; + req.hour = hour; + req.minute = minute; + req.second = second; + req.millisecond = htole16(millisecond); + req.zone = htole16(zone); + return hwrm_send_message(softc, &req, sizeof(req)); +} + +int +bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc) +{ + struct bnxt_link_info *link_info = &softc->link_info; + struct hwrm_port_phy_qcfg_input req = {0}; + struct hwrm_port_phy_qcfg_output *resp = + (void *)softc->hwrm_cmd_resp.idi_vaddr; + int rc = 0; + + BNXT_HWRM_LOCK(softc); + bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG); + + rc = _hwrm_send_message(softc, &req, sizeof(req)); + if (rc) + goto exit; + + link_info->phy_link_status = resp->link; + link_info->duplex = resp->duplex; + link_info->pause = resp->pause; + link_info->auto_mode = resp->auto_mode; + link_info->auto_pause = resp->auto_pause; + link_info->force_pause = resp->force_pause; + link_info->duplex_setting = resp->duplex; + if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) + link_info->link_speed = le16toh(resp->link_speed); + else + link_info->link_speed = 0; + link_info->force_link_speed = le16toh(resp->force_link_speed); + link_info->auto_link_speed = le16toh(resp->auto_link_speed); + link_info->support_speeds = le16toh(resp->support_speeds); + link_info->auto_link_speeds = le16toh(resp->auto_link_speed_mask); + link_info->preemphasis = le32toh(resp->preemphasis); + link_info->phy_ver[0] = resp->phy_maj; + link_info->phy_ver[1] = resp->phy_min; + link_info->phy_ver[2] = resp->phy_bld; + snprintf(softc->ver_info->phy_ver, sizeof(softc->ver_info->phy_ver), + "%d.%d.%d", link_info->phy_ver[0], link_info->phy_ver[1], + link_info->phy_ver[2]); + strlcpy(softc->ver_info->phy_vendor, resp->phy_vendor_name, + BNXT_NAME_SIZE); + strlcpy(softc->ver_info->phy_partnumber, resp->phy_vendor_partnumber, + BNXT_NAME_SIZE); + link_info->media_type = resp->media_type; + link_info->phy_type = resp->phy_type; + link_info->transceiver = resp->xcvr_pkg_type; + link_info->phy_addr = resp->eee_config_phy_addr & + HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK; + +exit: + BNXT_HWRM_UNLOCK(softc); + return rc; +} diff --git a/sys/dev/bnxt/bnxt_hwrm.h b/sys/dev/bnxt/bnxt_hwrm.h new file mode 100644 index 00000000000..21fc2272c85 --- /dev/null +++ b/sys/dev/bnxt/bnxt_hwrm.h @@ -0,0 +1,102 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef _BNXT_HWRM_H +#define _BNXT_HWRM_H + +/* HWRM Function Prototypes */ +int bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc); +void bnxt_free_hwrm_dma_mem(struct bnxt_softc *softc); +int bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type, + struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id, + bool irq); +int bnxt_hwrm_ver_get(struct bnxt_softc *softc); +int bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc); +int bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc); +int bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown); +int bnxt_hwrm_func_qcaps(struct bnxt_softc *softc); +int bnxt_hwrm_func_reset(struct bnxt_softc *softc); +int bnxt_hwrm_set_link_setting(struct bnxt_softc *, bool set_pause, + bool set_eee); +int bnxt_hwrm_set_pause(struct bnxt_softc *softc); +int bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id); +int bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic); +int bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr, + uint64_t paddr); +int bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, + struct bnxt_grp_info *grp); +int bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic); +int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc, + struct bnxt_vnic_info *vnic); +int bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic); +int bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic, + uint32_t hash_type); +int bnxt_hwrm_func_cfg(struct bnxt_softc *softc); +int bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc, + struct bnxt_vnic_info *vnic, uint32_t flags); +int bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type, + uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index, + uint8_t search_opt, uint32_t *data_length, uint32_t *item_length, + uint32_t *fw_ver); +int bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, + uint32_t offset, uint32_t length, struct iflib_dma_info *data); +int bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, + uint32_t offset, void *data, bool cpyin, uint32_t length); +int bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor, + uint8_t *selfreset); +int bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, + uint8_t *selfreset); +int bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin, + uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr, + uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length, + uint16_t *index); +int bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index); +int bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries, + uint32_t *entry_length); +int bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, + uint32_t *entries, uint32_t *entry_length, struct iflib_dma_info *dma_data); +int bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id, + uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size, + uint32_t *reserved_size, uint32_t *available_size); +int bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc, + uint32_t install_type, uint64_t *installed_items, uint8_t *result, + uint8_t *problem_item, uint8_t *reset_required); +int bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type, + uint16_t ordinal, uint16_t ext); +int bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, + uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute, + uint8_t *second, uint16_t *millisecond, uint16_t *zone); +int bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, + uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, + uint16_t millisecond, uint16_t zone); +int bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc); + +#endif diff --git a/sys/dev/bnxt/bnxt_ioctl.h b/sys/dev/bnxt/bnxt_ioctl.h new file mode 100644 index 00000000000..af6c719b914 --- /dev/null +++ b/sys/dev/bnxt/bnxt_ioctl.h @@ -0,0 +1,192 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#ifndef _BNXT_IOCTL_H +#define _BNXT_IOCTL_H + +enum bnxt_ioctl_type { + BNXT_HWRM_NVM_FIND_DIR_ENTRY, + BNXT_HWRM_NVM_READ, + BNXT_HWRM_FW_RESET, + BNXT_HWRM_FW_QSTATUS, + BNXT_HWRM_NVM_WRITE, + BNXT_HWRM_NVM_ERASE_DIR_ENTRY, + BNXT_HWRM_NVM_GET_DIR_INFO, + BNXT_HWRM_NVM_GET_DIR_ENTRIES, + BNXT_HWRM_NVM_MODIFY, + BNXT_HWRM_NVM_VERIFY_UPDATE, + BNXT_HWRM_NVM_INSTALL_UPDATE, + BNXT_HWRM_FW_GET_TIME, + BNXT_HWRM_FW_SET_TIME, +}; + +struct bnxt_ioctl_header { + enum bnxt_ioctl_type type; + int rc; +}; + +struct bnxt_ioctl_hwrm_nvm_find_dir_entry { + struct bnxt_ioctl_header hdr; + uint32_t data_length; + uint32_t fw_ver; + uint32_t item_length; + uint16_t ext; + uint16_t index; + uint16_t ordinal; + uint16_t type; + uint8_t search_opt; + bool use_index; +}; + +struct bnxt_ioctl_hwrm_nvm_read { + struct bnxt_ioctl_header hdr; + uint8_t *data; + uint32_t length; + uint32_t offset; + uint16_t index; +}; + +struct bnxt_ioctl_hwrm_fw_reset { + struct bnxt_ioctl_header hdr; + uint8_t processor; + uint8_t selfreset; +}; + +struct bnxt_ioctl_hwrm_fw_qstatus { + struct bnxt_ioctl_header hdr; + uint8_t processor; + uint8_t selfreset; +}; + +struct bnxt_ioctl_hwrm_nvm_write { + struct bnxt_ioctl_header hdr; + uint8_t *data; + uint32_t data_length; + uint32_t item_length; + uint16_t attr; + uint16_t ext; + uint16_t index; + uint16_t option; + uint16_t ordinal; + uint16_t type; + bool keep; +}; + +struct bnxt_ioctl_hwrm_nvm_erase_dir_entry { + struct bnxt_ioctl_header hdr; + enum bnxt_ioctl_type type; + int rc; + uint16_t index; +}; + +struct bnxt_ioctl_hwrm_nvm_get_dir_info { + struct bnxt_ioctl_header hdr; + uint32_t entries; + uint32_t entry_length; +}; + +struct bnxt_ioctl_hwrm_nvm_get_dir_entries { + struct bnxt_ioctl_header hdr; + uint8_t *data; + size_t max_size; + uint32_t entries; + uint32_t entry_length; +}; + +struct bnxt_ioctl_hwrm_nvm_install_update { + struct bnxt_ioctl_header hdr; + uint64_t installed_items; + uint32_t install_type; + uint8_t problem_item; + uint8_t reset_required; + uint8_t result; +}; + +struct bnxt_ioctl_hwrm_nvm_verify_update { + struct bnxt_ioctl_header hdr; + uint16_t ext; + uint16_t ordinal; + uint16_t type; +}; + +struct bnxt_ioctl_hwrm_nvm_modify { + struct bnxt_ioctl_header hdr; + uint8_t *data; + uint32_t length; + uint32_t offset; + uint16_t index; +}; + +struct bnxt_ioctl_hwrm_fw_get_time { + struct bnxt_ioctl_header hdr; + uint16_t millisecond; + uint16_t year; + uint16_t zone; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t month; + uint8_t second; +}; + +struct bnxt_ioctl_hwrm_fw_set_time { + struct bnxt_ioctl_header hdr; + uint16_t millisecond; + uint16_t year; + uint16_t zone; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t month; + uint8_t second; +}; + +/* IOCTL interface */ +struct bnxt_ioctl_data { + union { + struct bnxt_ioctl_header hdr; + struct bnxt_ioctl_hwrm_nvm_find_dir_entry find; + struct bnxt_ioctl_hwrm_nvm_read read; + struct bnxt_ioctl_hwrm_fw_reset reset; + struct bnxt_ioctl_hwrm_fw_qstatus status; + struct bnxt_ioctl_hwrm_nvm_write write; + struct bnxt_ioctl_hwrm_nvm_erase_dir_entry erase; + struct bnxt_ioctl_hwrm_nvm_get_dir_info dir_info; + struct bnxt_ioctl_hwrm_nvm_get_dir_entries dir_entries; + struct bnxt_ioctl_hwrm_nvm_install_update install; + struct bnxt_ioctl_hwrm_nvm_verify_update verify; + struct bnxt_ioctl_hwrm_nvm_modify modify; + struct bnxt_ioctl_hwrm_fw_get_time get_time; + struct bnxt_ioctl_hwrm_fw_set_time set_time; + }; +}; + +#endif diff --git a/sys/dev/bnxt/bnxt_sysctl.c b/sys/dev/bnxt/bnxt_sysctl.c new file mode 100644 index 00000000000..6f79b56f07e --- /dev/null +++ b/sys/dev/bnxt/bnxt_sysctl.c @@ -0,0 +1,618 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "bnxt.h" +#include "bnxt_hwrm.h" +#include "bnxt_sysctl.h" + +static int bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS); +/* + * We want to create: + * dev.bnxt.0.hwstats.txq0 + * dev.bnxt.0.hwstats.txq0.txmbufs + * dev.bnxt.0.hwstats.rxq0 + * dev.bnxt.0.hwstats.txq0.rxmbufs + * so the hwstats ctx list needs to be created in attach_post and populated + * during init. + * + * Then, it needs to be cleaned up in stop. + */ + +int +bnxt_init_sysctl_ctx(struct bnxt_softc *softc) +{ + struct sysctl_ctx_list *ctx; + + sysctl_ctx_init(&softc->hw_stats); + ctx = device_get_sysctl_ctx(softc->dev); + softc->hw_stats_oid = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO, + "hwstats", CTLFLAG_RD, 0, "hardware statistics"); + if (!softc->hw_stats_oid) { + sysctl_ctx_free(&softc->hw_stats); + return ENOMEM; + } + + sysctl_ctx_init(&softc->ver_info->ver_ctx); + ctx = device_get_sysctl_ctx(softc->dev); + softc->ver_info->ver_oid = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO, + "ver", CTLFLAG_RD, 0, "hardware/firmware version information"); + if (!softc->ver_info->ver_oid) { + sysctl_ctx_free(&softc->ver_info->ver_ctx); + return ENOMEM; + } + + sysctl_ctx_init(&softc->nvm_info->nvm_ctx); + ctx = device_get_sysctl_ctx(softc->dev); + softc->nvm_info->nvm_oid = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO, + "nvram", CTLFLAG_RD, 0, "nvram information"); + if (!softc->nvm_info->nvm_oid) { + sysctl_ctx_free(&softc->nvm_info->nvm_ctx); + return ENOMEM; + } + + return 0; +} + +int +bnxt_free_sysctl_ctx(struct bnxt_softc *softc) +{ + int orc; + int rc = 0; + + if (softc->hw_stats_oid != NULL) { + orc = sysctl_ctx_free(&softc->hw_stats); + if (orc) + rc = orc; + else + softc->hw_stats_oid = NULL; + } + if (softc->ver_info->ver_oid != NULL) { + orc = sysctl_ctx_free(&softc->ver_info->ver_ctx); + if (orc) + rc = orc; + else + softc->ver_info->ver_oid = NULL; + } + if (softc->nvm_info->nvm_oid != NULL) { + orc = sysctl_ctx_free(&softc->nvm_info->nvm_ctx); + if (orc) + rc = orc; + else + softc->nvm_info->nvm_oid = NULL; + } + + return rc; +} + +int +bnxt_create_tx_sysctls(struct bnxt_softc *softc, int txr) +{ + struct sysctl_oid *oid; + struct ctx_hw_stats *tx_stats = (void *)softc->tx_stats.idi_vaddr; + char name[32]; + char desc[64]; + + sprintf(name, "txq%d", txr); + sprintf(desc, "transmit queue %d", txr); + oid = SYSCTL_ADD_NODE(&softc->hw_stats, + SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0, + desc); + if (!oid) + return ENOMEM; + + + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "ucast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_ucast_pkts, + "unicast packets sent"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "mcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_mcast_pkts, + "multicast packets sent"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "bcast_pkts", CTLFLAG_RD, &tx_stats[txr].tx_bcast_pkts, + "broadcast packets sent"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "discard_pkts", CTLFLAG_RD, + &tx_stats[txr].tx_discard_pkts, "discarded transmit packets"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "drop_pkts", CTLFLAG_RD, &tx_stats[txr].tx_drop_pkts, + "dropped transmit packets"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "ucast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_ucast_bytes, + "unicast bytes sent"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "mcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_mcast_bytes, + "multicast bytes sent"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "bcast_bytes", CTLFLAG_RD, &tx_stats[txr].tx_bcast_bytes, + "broadcast bytes sent"); + + return 0; +} + +int +bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr) +{ + struct sysctl_oid *oid; + struct ctx_hw_stats *rx_stats = (void *)softc->rx_stats.idi_vaddr; + char name[32]; + char desc[64]; + + sprintf(name, "rxq%d", rxr); + sprintf(desc, "receive queue %d", rxr); + oid = SYSCTL_ADD_NODE(&softc->hw_stats, + SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name, CTLFLAG_RD, 0, + desc); + if (!oid) + return ENOMEM; + + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "ucast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_pkts, + "unicast packets received"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "mcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_pkts, + "multicast packets received"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "bcast_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_pkts, + "broadcast packets received"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "discard_pkts", CTLFLAG_RD, + &rx_stats[rxr].rx_discard_pkts, "discarded receive packets"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "drop_pkts", CTLFLAG_RD, &rx_stats[rxr].rx_drop_pkts, + "dropped receive packets"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "ucast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_ucast_bytes, + "unicast bytes received"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "mcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_mcast_bytes, + "multicast bytes received"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "bcast_bytes", CTLFLAG_RD, &rx_stats[rxr].rx_bcast_bytes, + "broadcast bytes received"); + + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tpa_pkts", CTLFLAG_RD, &rx_stats[rxr].tpa_pkts, + "TPA packets"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tpa_bytes", CTLFLAG_RD, &rx_stats[rxr].tpa_bytes, + "TPA bytes"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tpa_events", CTLFLAG_RD, &rx_stats[rxr].tpa_events, + "TPA events"); + SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO, + "tpa_aborts", CTLFLAG_RD, &rx_stats[rxr].tpa_aborts, + "TPA aborts"); + + return 0; +} + +static char *bnxt_chip_type[] = { + "ASIC", + "FPGA", + "Palladium", + "Unknown" +}; +#define MAX_CHIP_TYPE 3 + +static int +bnxt_package_ver_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + struct iflib_dma_info dma_data; + char *pkglog = NULL; + char *p; + char *next; + char unk[] = ""; + char *buf = unk; + int rc; + int field; + uint16_t ordinal = BNX_DIR_ORDINAL_FIRST; + uint16_t index; + uint32_t data_len; + + rc = bnxt_hwrm_nvm_find_dir_entry(softc, BNX_DIR_TYPE_PKG_LOG, + &ordinal, BNX_DIR_EXT_NONE, &index, false, + HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_EQ, + &data_len, NULL, NULL); + dma_data.idi_vaddr = NULL; + if (rc == 0 && data_len) { + rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data, + BUS_DMA_NOWAIT); + if (rc == 0) { + rc = bnxt_hwrm_nvm_read(softc, index, 0, data_len, + &dma_data); + if (rc == 0) { + pkglog = dma_data.idi_vaddr; + /* NULL terminate (removes last \n) */ + pkglog[data_len-1] = 0; + + /* Set p = start of last line */ + p = strrchr(pkglog, '\n'); + if (p == NULL) + p = pkglog; + + /* Now find the correct tab delimited field */ + for (field = 0, next = p, + p = strsep(&next, "\t"); + field < + BNX_PKG_LOG_FIELD_IDX_PKG_VERSION && p; + p = strsep(&next, "\t")) { + field++; + } + if (field == BNX_PKG_LOG_FIELD_IDX_PKG_VERSION) + buf = p; + } + } + else + dma_data.idi_vaddr = NULL; + } + + rc = sysctl_handle_string(oidp, buf, 0, req); + if (dma_data.idi_vaddr) + iflib_dma_free(&dma_data); + return rc; +} + +static int +bnxt_hwrm_min_ver_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + char buf[16]; + uint8_t newver[3]; + int rc; + + sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major, + softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update); + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + if (sscanf(buf, "%hhu.%hhu.%hhu%*c", &newver[0], &newver[1], + &newver[2]) != 3) + return EINVAL; + softc->ver_info->hwrm_min_major = newver[0]; + softc->ver_info->hwrm_min_minor = newver[1]; + softc->ver_info->hwrm_min_update = newver[2]; + bnxt_check_hwrm_version(softc); + + return rc; +} + +int +bnxt_create_ver_sysctls(struct bnxt_softc *softc) +{ + struct bnxt_ver_info *vi = softc->ver_info; + struct sysctl_oid *oid = vi->ver_oid; + + if (!oid) + return ENOMEM; + + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "hwrm_if", CTLFLAG_RD, vi->hwrm_if_ver, 0, + "HWRM interface version"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "driver_hwrm_if", CTLFLAG_RD, vi->driver_hwrm_if_ver, 0, + "HWRM firmware version"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "hwrm_fw", CTLFLAG_RD, vi->hwrm_fw_ver, 0, + "HWRM firmware version"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "mgmt_fw", CTLFLAG_RD, vi->mgmt_fw_ver, 0, + "management firmware version"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "netctrl_fw", CTLFLAG_RD, vi->netctrl_fw_ver, 0, + "network control firmware version"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "roce_fw", CTLFLAG_RD, vi->roce_fw_ver, 0, + "RoCE firmware version"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "phy", CTLFLAG_RD, vi->phy_ver, 0, + "PHY version"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "hwrm_fw_name", CTLFLAG_RD, vi->hwrm_fw_name, 0, + "HWRM firmware name"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "mgmt_fw_name", CTLFLAG_RD, vi->mgmt_fw_name, 0, + "management firmware name"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "netctrl_fw_name", CTLFLAG_RD, vi->netctrl_fw_name, 0, + "network control firmware name"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "roce_fw_name", CTLFLAG_RD, vi->roce_fw_name, 0, + "RoCE firmware name"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "phy_vendor", CTLFLAG_RD, vi->phy_vendor, 0, + "PHY vendor name"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "phy_partnumber", CTLFLAG_RD, vi->phy_partnumber, 0, + "PHY vendor part number"); + SYSCTL_ADD_U16(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "chip_num", CTLFLAG_RD, &vi->chip_num, 0, "chip number"); + SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "chip_rev", CTLFLAG_RD, &vi->chip_rev, 0, "chip revision"); + SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "chip_metal", CTLFLAG_RD, &vi->chip_metal, 0, "chip metal number"); + SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "chip_bond_id", CTLFLAG_RD, &vi->chip_bond_id, 0, + "chip bond id"); + SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "chip_type", CTLFLAG_RD, vi->chip_type > MAX_CHIP_TYPE ? + bnxt_chip_type[MAX_CHIP_TYPE] : bnxt_chip_type[vi->chip_type], 0, + "RoCE firmware name"); + SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "package_ver", CTLTYPE_STRING|CTLFLAG_RD, softc, 0, + bnxt_package_ver_sysctl, "A", + "currently installed package version"); + SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "hwrm_min_ver", CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, + bnxt_hwrm_min_ver_sysctl, "A", + "minimum hwrm API vesion to support"); + + return 0; +} + +int +bnxt_create_nvram_sysctls(struct bnxt_nvram_info *ni) +{ + struct sysctl_oid *oid = ni->nvm_oid; + + if (!oid) + return ENOMEM; + + SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "mfg_id", CTLFLAG_RD, &ni->mfg_id, 0, "manufacturer id"); + SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "device_id", CTLFLAG_RD, &ni->device_id, 0, "device id"); + SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "sector_size", CTLFLAG_RD, &ni->sector_size, 0, "sector size"); + SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "size", CTLFLAG_RD, &ni->size, 0, "nvram total size"); + SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "reserved_size", CTLFLAG_RD, &ni->reserved_size, 0, + "total reserved space"); + SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "available_size", CTLFLAG_RD, &ni->available_size, 0, + "total available space"); + + return 0; +} + +static int +bnxt_rss_key_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + char buf[HW_HASH_KEY_SIZE*2+1] = {0}; + char *p; + int i; + int rc; + + for (p = buf, i=0; ivnic_info.rss_hash_key[i]); + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + + if (strspn(buf, "0123456789abcdefABCDEF") != (HW_HASH_KEY_SIZE * 2)) + return EINVAL; + + for (p = buf, i=0; ivnic_info.rss_hash_key[i]) != 1) + return EINVAL; + p += 2; + } + + if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) + bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, + softc->vnic_info.rss_hash_type); + + return rc; +} + +static const char *bnxt_hash_types[] = {"ipv4", "tcp_ipv4", "udp_ipv4", "ipv6", + "tcp_ipv6", "udp_ipv6", NULL}; + +static int bnxt_get_rss_type_str_bit(char *str) +{ + int i; + + for (i=0; bnxt_hash_types[i]; i++) + if (strcmp(bnxt_hash_types[i], str) == 0) + return i; + + return -1; +} + +static int +bnxt_rss_type_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct bnxt_softc *softc = arg1; + char buf[256] = {0}; + char *p; + char *next; + int rc; + int type; + int bit; + + for (type = softc->vnic_info.rss_hash_type; type; + type &= ~(1<= sizeof(bnxt_hash_types) / sizeof(const char *)) + continue; + if (type != softc->vnic_info.rss_hash_type) + strcat(buf, ","); + strcat(buf, bnxt_hash_types[bit]); + } + + rc = sysctl_handle_string(oidp, buf, sizeof(buf), req); + if (rc || req->newptr == NULL) + return rc; + + for (type = 0, next = buf, p = strsep(&next, " ,"); p; + p = strsep(&next, " ,")) { + bit = bnxt_get_rss_type_str_bit(p); + if (bit == -1) + return EINVAL; + type |= 1<vnic_info.rss_hash_type) { + softc->vnic_info.rss_hash_type = type; + if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) + bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, + softc->vnic_info.rss_hash_type); + } + + return rc; +} + +static int +bnxt_rx_stall_sysctl(SYSCTL_HANDLER_ARGS) { + struct bnxt_softc *softc = arg1; + int rc; + int val; + + if (softc == NULL) + return EBUSY; + + val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_BD_STALL); + rc = sysctl_handle_int(oidp, &val, 0, req); + if (rc || !req->newptr) + return rc; + + if (val) + softc->vnic_info.flags |= BNXT_VNIC_FLAG_BD_STALL; + else + softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_BD_STALL; + + if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) + rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info); + + return rc; +} + +static int +bnxt_vlan_strip_sysctl(SYSCTL_HANDLER_ARGS) { + struct bnxt_softc *softc = arg1; + int rc; + int val; + + if (softc == NULL) + return EBUSY; + + val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_VLAN_STRIP); + rc = sysctl_handle_int(oidp, &val, 0, req); + if (rc || !req->newptr) + return rc; + + if (val) + softc->vnic_info.flags |= BNXT_VNIC_FLAG_VLAN_STRIP; + else + softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_VLAN_STRIP; + + if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) + rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info); + + return rc; +} + +int +bnxt_create_config_sysctls_pre(struct bnxt_softc *softc) +{ + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev); + struct sysctl_oid_list *children; + + children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));; + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_key", + CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_key_sysctl, "A", + "RSS key"); + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_type", + CTLTYPE_STRING|CTLFLAG_RWTUN, softc, 0, bnxt_rss_type_sysctl, "A", + "RSS type bits"); + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_stall", + CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_rx_stall_sysctl, "I", + "buffer rx packets in hardware until the host posts new buffers"); + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_strip", + CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_strip_sysctl, "I", + "strip VLAN tag in the RX path"); + SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "if_name", CTLFLAG_RD, + iflib_get_ifp(softc->ctx)->if_xname, 0, "interface name"); + + return 0; +} + +static int +bnxt_vlan_only_sysctl(SYSCTL_HANDLER_ARGS) { + struct bnxt_softc *softc = arg1; + int rc; + int val; + + if (softc == NULL) + return EBUSY; + + val = softc->vnic_info.vlan_only; + rc = sysctl_handle_int(oidp, &val, 0, req); + if (rc || !req->newptr) + return rc; + + if (val) + val = 1; + + if (val != softc->vnic_info.vlan_only) { + softc->vnic_info.vlan_only = val; + if (if_getdrvflags(iflib_get_ifp(softc->ctx)) & IFF_DRV_RUNNING) + rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc, + &softc->vnic_info); + } + + return rc; +} + +int +bnxt_create_config_sysctls_post(struct bnxt_softc *softc) +{ + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev); + struct sysctl_oid_list *children; + + children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));; + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_only", + CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_vlan_only_sysctl, "I", + "require vlan tag on received packets when vlan is enabled"); + + return 0; +} diff --git a/sys/dev/bnxt/bnxt_sysctl.h b/sys/dev/bnxt/bnxt_sysctl.h new file mode 100644 index 00000000000..62b7dcf1e37 --- /dev/null +++ b/sys/dev/bnxt/bnxt_sysctl.h @@ -0,0 +1,41 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "bnxt.h" + +int bnxt_init_sysctl_ctx(struct bnxt_softc *softc); +int bnxt_free_sysctl_ctx(struct bnxt_softc *softc); +int bnxt_create_tx_sysctls(struct bnxt_softc *softc, int txr); +int bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr); +int bnxt_create_ver_sysctls(struct bnxt_softc *softc); +int bnxt_create_nvram_sysctls(struct bnxt_nvram_info *ni); +int bnxt_create_config_sysctls_pre(struct bnxt_softc *softc); +int bnxt_create_config_sysctls_post(struct bnxt_softc *softc); diff --git a/sys/dev/bnxt/bnxt_txrx.c b/sys/dev/bnxt/bnxt_txrx.c new file mode 100644 index 00000000000..b3e8a12b71b --- /dev/null +++ b/sys/dev/bnxt/bnxt_txrx.c @@ -0,0 +1,641 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include "opt_inet.h" +#include "opt_inet6.h" +#include "opt_rss.h" + +#include "bnxt.h" + +/* + * Function prototypes + */ + +static int bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi); +static void bnxt_isc_txd_flush(void *sc, uint16_t txqid, uint32_t pidx); +static int bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, uint32_t cidx, + bool clear); + +static void bnxt_isc_rxd_refill(void *sc, uint16_t rxqid, uint8_t flid, + uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs, uint16_t count, + uint16_t buf_size); +static void bnxt_isc_rxd_flush(void *sc, uint16_t rxqid, uint8_t flid, + uint32_t pidx); +static int bnxt_isc_rxd_available(void *sc, uint16_t rxqid, uint32_t idx, + int budget); +static int bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri); + +static int bnxt_intr(void *sc); + +struct if_txrx bnxt_txrx = { + bnxt_isc_txd_encap, + bnxt_isc_txd_flush, + bnxt_isc_txd_credits_update, + bnxt_isc_rxd_available, + bnxt_isc_rxd_pkt_get, + bnxt_isc_rxd_refill, + bnxt_isc_rxd_flush, + bnxt_intr +}; + +/* + * Device Dependent Packet Transmit and Receive Functions + */ + +static const uint16_t bnxt_tx_lhint[] = { + TX_BD_SHORT_FLAGS_LHINT_LT512, + TX_BD_SHORT_FLAGS_LHINT_LT1K, + TX_BD_SHORT_FLAGS_LHINT_LT2K, + TX_BD_SHORT_FLAGS_LHINT_LT2K, + TX_BD_SHORT_FLAGS_LHINT_GTE2K, +}; + +static int +bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + struct bnxt_ring *txr = &softc->tx_rings[pi->ipi_qsidx]; + struct tx_bd_long *tbd; + struct tx_bd_long_hi *tbdh; + bool need_hi = false; + uint16_t flags_type; + uint16_t lflags; + uint32_t cfa_meta; + int seg = 0; + + /* If we have offloads enabled, we need to use two BDs. */ + if ((pi->ipi_csum_flags & (CSUM_OFFLOAD | CSUM_TSO | CSUM_IP)) || + pi->ipi_mflags & M_VLANTAG) + need_hi = true; + + /* TODO: Devices before Cu+B1 need to not mix long and short BDs */ + need_hi = true; + + pi->ipi_new_pidx = pi->ipi_pidx; + tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx]; + pi->ipi_ndescs = 0; + /* No need to byte-swap the opaque value */ + tbd->opaque = ((pi->ipi_nsegs + need_hi) << 24) | pi->ipi_new_pidx; + tbd->len = htole16(pi->ipi_segs[seg].ds_len); + tbd->addr = htole64(pi->ipi_segs[seg++].ds_addr); + flags_type = ((pi->ipi_nsegs + need_hi) << + TX_BD_SHORT_FLAGS_BD_CNT_SFT) & TX_BD_SHORT_FLAGS_BD_CNT_MASK; + if (pi->ipi_len >= 2048) + flags_type |= TX_BD_SHORT_FLAGS_LHINT_GTE2K; + else + flags_type |= bnxt_tx_lhint[pi->ipi_len >> 9]; + + if (need_hi) { + flags_type |= TX_BD_LONG_TYPE_TX_BD_LONG; + + pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx); + tbdh = &((struct tx_bd_long_hi *)txr->vaddr)[pi->ipi_new_pidx]; + tbdh->mss = htole16(pi->ipi_tso_segsz); + tbdh->hdr_size = htole16((pi->ipi_ehdrlen + pi->ipi_ip_hlen + + pi->ipi_tcp_hlen) >> 1); + tbdh->cfa_action = 0; + lflags = 0; + cfa_meta = 0; + if (pi->ipi_mflags & M_VLANTAG) { + /* TODO: Do we need to byte-swap the vtag here? */ + cfa_meta = TX_BD_LONG_CFA_META_KEY_VLAN_TAG | + pi->ipi_vtag; + cfa_meta |= TX_BD_LONG_CFA_META_VLAN_TPID_TPID8100; + } + tbdh->cfa_meta = htole32(cfa_meta); + if (pi->ipi_csum_flags & CSUM_TSO) { + lflags |= TX_BD_LONG_LFLAGS_LSO | + TX_BD_LONG_LFLAGS_T_IPID; + } + else if(pi->ipi_csum_flags & CSUM_OFFLOAD) { + lflags |= TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM | + TX_BD_LONG_LFLAGS_IP_CHKSUM; + } + else if(pi->ipi_csum_flags & CSUM_IP) { + lflags |= TX_BD_LONG_LFLAGS_IP_CHKSUM; + } + tbdh->lflags = htole16(lflags); + } + else { + flags_type |= TX_BD_SHORT_TYPE_TX_BD_SHORT; + } + + for (; seg < pi->ipi_nsegs; seg++) { + tbd->flags_type = htole16(flags_type); + pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx); + tbd = &((struct tx_bd_long *)txr->vaddr)[pi->ipi_new_pidx]; + tbd->len = htole16(pi->ipi_segs[seg].ds_len); + tbd->addr = htole64(pi->ipi_segs[seg].ds_addr); + flags_type = TX_BD_SHORT_TYPE_TX_BD_SHORT; + } + flags_type |= TX_BD_SHORT_FLAGS_PACKET_END; + tbd->flags_type = htole16(flags_type); + pi->ipi_new_pidx = RING_NEXT(txr, pi->ipi_new_pidx); + + return 0; +} + +static void +bnxt_isc_txd_flush(void *sc, uint16_t txqid, uint32_t pidx) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + struct bnxt_ring *tx_ring = &softc->tx_rings[txqid]; + + /* pidx is what we last set ipi_new_pidx to */ + BNXT_TX_DB(tx_ring, pidx); + /* TODO: Cumulus+ doesn't need the double doorbell */ + BNXT_TX_DB(tx_ring, pidx); + return; +} + +static int +bnxt_isc_txd_credits_update(void *sc, uint16_t txqid, uint32_t idx, bool clear) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + struct bnxt_cp_ring *cpr = &softc->tx_cp_rings[txqid]; + struct tx_cmpl *cmpl = (struct tx_cmpl *)cpr->ring.vaddr; + int avail = 0; + uint32_t cons = cpr->cons; + bool v_bit = cpr->v_bit; + bool last_v_bit; + uint32_t last_cons; + uint16_t type; + uint16_t err; + + for (;;) { + last_cons = cons; + last_v_bit = v_bit; + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + + if (!CMP_VALID(&cmpl[cons], v_bit)) + goto done; + + type = cmpl[cons].flags_type & TX_CMPL_TYPE_MASK; + switch (type) { + case TX_CMPL_TYPE_TX_L2: + err = (le16toh(cmpl[cons].errors_v) & + TX_CMPL_ERRORS_BUFFER_ERROR_MASK) >> + TX_CMPL_ERRORS_BUFFER_ERROR_SFT; + if (err) + device_printf(softc->dev, + "TX completion error %u\n", err); + /* No need to byte-swap the opaque value */ + avail += cmpl[cons].opaque >> 24; + /* + * If we're not clearing, iflib only cares if there's + * at least one buffer. Don't scan the whole ring in + * this case. + */ + if (!clear) + goto done; + break; + default: + if (type & 1) { + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + if (!CMP_VALID(&cmpl[cons], v_bit)) + goto done; + } + device_printf(softc->dev, + "Unhandled TX completion type %u\n", type); + break; + } + } +done: + + if (clear && avail) { + cpr->cons = last_cons; + cpr->v_bit = last_v_bit; + BNXT_CP_IDX_DISABLE_DB(&cpr->ring, cpr->cons); + } + + return avail; +} + +static void +bnxt_isc_rxd_refill(void *sc, uint16_t rxqid, uint8_t flid, + uint32_t pidx, uint64_t *paddrs, + caddr_t *vaddrs, uint16_t count, uint16_t len) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + struct bnxt_ring *rx_ring; + struct rx_prod_pkt_bd *rxbd; + uint16_t type; + uint16_t i; + + if (flid == 0) { + rx_ring = &softc->rx_rings[rxqid]; + type = RX_PROD_PKT_BD_TYPE_RX_PROD_PKT; + } + else { + rx_ring = &softc->ag_rings[rxqid]; + type = RX_PROD_AGG_BD_TYPE_RX_PROD_AGG; + } + rxbd = (void *)rx_ring->vaddr; + + for (i=0; iring_size) + pidx = 0; + } + return; +} + +static void +bnxt_isc_rxd_flush(void *sc, uint16_t rxqid, uint8_t flid, + uint32_t pidx) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + struct bnxt_ring *rx_ring; + + if (flid == 0) + rx_ring = &softc->rx_rings[rxqid]; + else + rx_ring = &softc->ag_rings[rxqid]; + + /* + * We *must* update the completion ring before updating the RX ring + * or we will overrun the completion ring and the device will wedge for + * RX. + */ + if (softc->rx_cp_rings[rxqid].cons != UINT32_MAX) + BNXT_CP_IDX_DISABLE_DB(&softc->rx_cp_rings[rxqid].ring, + softc->rx_cp_rings[rxqid].cons); + /* We're given the last filled RX buffer here, not the next empty one */ + BNXT_RX_DB(rx_ring, RING_NEXT(rx_ring, pidx)); + /* TODO: Cumulus+ doesn't need the double doorbell */ + BNXT_RX_DB(rx_ring, RING_NEXT(rx_ring, pidx)); + return; +} + +static int +bnxt_isc_rxd_available(void *sc, uint16_t rxqid, uint32_t idx, int budget) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + struct bnxt_cp_ring *cpr = &softc->rx_cp_rings[rxqid]; + struct rx_pkt_cmpl *rcp; + struct rx_tpa_start_cmpl *rtpa; + struct rx_tpa_end_cmpl *rtpae; + struct cmpl_base *cmp = (struct cmpl_base *)cpr->ring.vaddr; + int avail = 0; + uint32_t cons = cpr->cons; + bool v_bit = cpr->v_bit; + uint8_t ags; + int i; + uint16_t type; + uint8_t agg_id; + + for (;;) { + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + + if (!CMP_VALID(&cmp[cons], v_bit)) + goto cmpl_invalid; + + type = le16toh(cmp[cons].type) & CMPL_BASE_TYPE_MASK; + switch (type) { + case CMPL_BASE_TYPE_RX_L2: + rcp = (void *)&cmp[cons]; + ags = (rcp->agg_bufs_v1 & RX_PKT_CMPL_AGG_BUFS_MASK) >> + RX_PKT_CMPL_AGG_BUFS_SFT; + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + + if (!CMP_VALID(&cmp[cons], v_bit)) + goto cmpl_invalid; + + /* Now account for all the AG completions */ + for (i=0; iring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + if (!CMP_VALID(&cmp[cons], v_bit)) + goto cmpl_invalid; + } + avail++; + break; + case CMPL_BASE_TYPE_RX_TPA_END: + rtpae = (void *)&cmp[cons]; + ags = (rtpae->agg_bufs_v1 & + RX_TPA_END_CMPL_AGG_BUFS_MASK) >> + RX_TPA_END_CMPL_AGG_BUFS_SFT; + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + + if (!CMP_VALID(&cmp[cons], v_bit)) + goto cmpl_invalid; + /* Now account for all the AG completions */ + for (i=0; iring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + if (!CMP_VALID(&cmp[cons], v_bit)) + goto cmpl_invalid; + } + avail++; + break; + case CMPL_BASE_TYPE_RX_TPA_START: + rtpa = (void *)&cmp[cons]; + agg_id = (rtpa->agg_id & + RX_TPA_START_CMPL_AGG_ID_MASK) >> + RX_TPA_START_CMPL_AGG_ID_SFT; + softc->tpa_start[agg_id].low = *rtpa; + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + + if (!CMP_VALID(&cmp[cons], v_bit)) + goto cmpl_invalid; + softc->tpa_start[agg_id].high = + ((struct rx_tpa_start_cmpl_hi *)cmp)[cons]; + break; + case CMPL_BASE_TYPE_RX_AGG: + break; + default: + device_printf(softc->dev, + "Unhandled completion type %d on RXQ %d\n", + type, rxqid); + + /* Odd completion types use two completions */ + if (type & 1) { + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + CMPL_PREFETCH_NEXT(cpr, cons); + + if (!CMP_VALID(&cmp[cons], v_bit)) + goto cmpl_invalid; + } + break; + } + if (avail > budget) + break; + } +cmpl_invalid: + + return avail; +} + +static int +bnxt_pkt_get_l2(struct bnxt_softc *softc, if_rxd_info_t ri, + struct bnxt_cp_ring *cpr, uint16_t flags_type) +{ + struct rx_pkt_cmpl *rcp; + struct rx_pkt_cmpl_hi *rcph; + struct rx_abuf_cmpl *acp; + uint32_t flags2; + uint32_t errors; + uint8_t ags; + int i; + + rcp = &((struct rx_pkt_cmpl *)cpr->ring.vaddr)[cpr->cons]; + + /* Extract from the first 16-byte BD */ + if (flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) { + ri->iri_flowid = le32toh(rcp->rss_hash); + /* + * TODO: Extract something useful from rcp->rss_hash_type + * (undocumented) + * May be documented in the "LSI ES" + * also check the firmware code. + */ + ri->iri_rsstype = M_HASHTYPE_OPAQUE; + } + else { + ri->iri_rsstype = M_HASHTYPE_NONE; + } + ags = (rcp->agg_bufs_v1 & RX_PKT_CMPL_AGG_BUFS_MASK) >> + RX_PKT_CMPL_AGG_BUFS_SFT; + ri->iri_nfrags = ags + 1; + /* No need to byte-swap the opaque value */ + ri->iri_frags[0].irf_flid = (rcp->opaque >> 16) & 0xff; + ri->iri_frags[0].irf_idx = rcp->opaque & 0xffff; + ri->iri_frags[0].irf_len = le16toh(rcp->len); + ri->iri_len = le16toh(rcp->len); + + /* Now the second 16-byte BD */ + NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); + rcph = &((struct rx_pkt_cmpl_hi *)cpr->ring.vaddr)[cpr->cons]; + + flags2 = le32toh(rcph->flags2); + errors = le16toh(rcph->errors_v2); + if ((flags2 & RX_PKT_CMPL_FLAGS2_META_FORMAT_MASK) == + RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN) { + ri->iri_flags |= M_VLANTAG; + /* TODO: Should this be the entire 16-bits? */ + ri->iri_vtag = le32toh(rcph->metadata) & + (RX_PKT_CMPL_METADATA_VID_MASK | RX_PKT_CMPL_METADATA_DE | + RX_PKT_CMPL_METADATA_PRI_MASK); + } + if (flags2 & RX_PKT_CMPL_FLAGS2_IP_CS_CALC) { + ri->iri_csum_flags |= CSUM_IP_CHECKED; + if (!(errors & RX_PKT_CMPL_ERRORS_IP_CS_ERROR)) + ri->iri_csum_flags |= CSUM_IP_VALID; + } + if (flags2 & RX_PKT_CMPL_FLAGS2_L4_CS_CALC) { + ri->iri_csum_flags |= CSUM_L4_CALC; + if (!(errors & RX_PKT_CMPL_ERRORS_L4_CS_ERROR)) { + ri->iri_csum_flags |= CSUM_L4_VALID; + ri->iri_csum_data = 0xffff; + } + } + + /* And finally the ag ring stuff. */ + for (i=1; i < ri->iri_nfrags; i++) { + NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); + acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons]; + + /* No need to byte-swap the opaque value */ + ri->iri_frags[i].irf_flid = (acp->opaque >> 16 & 0xff); + ri->iri_frags[i].irf_idx = acp->opaque & 0xffff; + ri->iri_frags[i].irf_len = le16toh(acp->len); + ri->iri_len += le16toh(acp->len); + } + + return 0; +} + +static int +bnxt_pkt_get_tpa(struct bnxt_softc *softc, if_rxd_info_t ri, + struct bnxt_cp_ring *cpr, uint16_t flags_type) +{ + struct rx_tpa_end_cmpl *agend = + &((struct rx_tpa_end_cmpl *)cpr->ring.vaddr)[cpr->cons]; + struct rx_tpa_end_cmpl_hi *agendh; + struct rx_abuf_cmpl *acp; + struct bnxt_full_tpa_start *tpas; + uint32_t flags2; + uint8_t ags; + uint8_t agg_id; + int i; + + /* Get the agg_id */ + agg_id = (agend->agg_id & RX_TPA_END_CMPL_AGG_ID_MASK) >> + RX_TPA_END_CMPL_AGG_ID_SFT; + tpas = &softc->tpa_start[agg_id]; + + /* Extract from the first 16-byte BD */ + if (le16toh(tpas->low.flags_type) & RX_TPA_START_CMPL_FLAGS_RSS_VALID) { + ri->iri_flowid = le32toh(tpas->low.rss_hash); + /* + * TODO: Extract something useful from tpas->low.rss_hash_type + * (undocumented) + * May be documented in the "LSI ES" + * also check the firmware code. + */ + ri->iri_rsstype = M_HASHTYPE_OPAQUE; + } + else { + ri->iri_rsstype = M_HASHTYPE_NONE; + } + ags = (agend->agg_bufs_v1 & RX_TPA_END_CMPL_AGG_BUFS_MASK) >> + RX_TPA_END_CMPL_AGG_BUFS_SFT; + ri->iri_nfrags = ags + 1; + /* No need to byte-swap the opaque value */ + ri->iri_frags[0].irf_flid = (tpas->low.opaque >> 16) & 0xff; + ri->iri_frags[0].irf_idx = tpas->low.opaque & 0xffff; + ri->iri_frags[0].irf_len = le16toh(tpas->low.len); + ri->iri_len = le16toh(tpas->low.len); + + /* Now the second 16-byte BD */ + NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); + agendh = &((struct rx_tpa_end_cmpl_hi *)cpr->ring.vaddr)[cpr->cons]; + + flags2 = le32toh(tpas->high.flags2); + if ((flags2 & RX_TPA_START_CMPL_FLAGS2_META_FORMAT_MASK) == + RX_TPA_START_CMPL_FLAGS2_META_FORMAT_VLAN) { + ri->iri_flags |= M_VLANTAG; + /* TODO: Should this be the entire 16-bits? */ + ri->iri_vtag = le32toh(tpas->high.metadata) & + (RX_TPA_START_CMPL_METADATA_VID_MASK | + RX_TPA_START_CMPL_METADATA_DE | + RX_TPA_START_CMPL_METADATA_PRI_MASK); + } + if (flags2 & RX_TPA_START_CMPL_FLAGS2_IP_CS_CALC) { + ri->iri_csum_flags |= CSUM_IP_CHECKED; + ri->iri_csum_flags |= CSUM_IP_VALID; + } + if (flags2 & RX_TPA_START_CMPL_FLAGS2_L4_CS_CALC) { + ri->iri_csum_flags |= CSUM_L4_CALC; + ri->iri_csum_flags |= CSUM_L4_VALID; + ri->iri_csum_data = 0xffff; + } + + /* Now the ag ring stuff. */ + for (i=1; i < ri->iri_nfrags; i++) { + NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); + acp = &((struct rx_abuf_cmpl *)cpr->ring.vaddr)[cpr->cons]; + + /* No need to byte-swap the opaque value */ + ri->iri_frags[i].irf_flid = (acp->opaque >> 16) & 0xff; + ri->iri_frags[i].irf_idx = acp->opaque & 0xffff; + ri->iri_frags[i].irf_len = le16toh(acp->len); + ri->iri_len += le16toh(acp->len); + } + + /* And finally, the empty BD at the end... */ + ri->iri_nfrags++; + /* No need to byte-swap the opaque value */ + ri->iri_frags[i].irf_flid = (agend->opaque >> 16) % 0xff; + ri->iri_frags[i].irf_idx = agend->opaque & 0xffff; + ri->iri_frags[i].irf_len = le16toh(agend->len); + ri->iri_len += le16toh(agend->len); + + return 0; +} + +/* If we return anything but zero, iflib will assert... */ +static int +bnxt_isc_rxd_pkt_get(void *sc, if_rxd_info_t ri) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + struct bnxt_cp_ring *cpr = &softc->rx_cp_rings[ri->iri_qsidx]; + struct cmpl_base *cmp; + uint16_t flags_type; + uint16_t type; + + for (;;) { + NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); + CMPL_PREFETCH_NEXT(cpr, cpr->cons); + cmp = &((struct cmpl_base *)cpr->ring.vaddr)[cpr->cons]; + + flags_type = le16toh(cmp->type); + type = flags_type & CMPL_BASE_TYPE_MASK; + + switch (type) { + case CMPL_BASE_TYPE_RX_L2: + return bnxt_pkt_get_l2(softc, ri, cpr, flags_type); + case CMPL_BASE_TYPE_RX_TPA_END: + return bnxt_pkt_get_tpa(softc, ri, cpr, flags_type); + case CMPL_BASE_TYPE_RX_TPA_START: + NEXT_CP_CONS_V(&cpr->ring, cpr->cons, cpr->v_bit); + ri->iri_cidx = RING_NEXT(&cpr->ring, ri->iri_cidx); + CMPL_PREFETCH_NEXT(cpr, cpr->cons); + break; + default: + device_printf(softc->dev, + "Unhandled completion type %d on RXQ %d get\n", + type, ri->iri_qsidx); + if (type & 1) { + NEXT_CP_CONS_V(&cpr->ring, cpr->cons, + cpr->v_bit); + ri->iri_cidx = RING_NEXT(&cpr->ring, + ri->iri_cidx); + CMPL_PREFETCH_NEXT(cpr, cpr->cons); + } + break; + } + } + + return 0; +} + +static int +bnxt_intr(void *sc) +{ + struct bnxt_softc *softc = (struct bnxt_softc *)sc; + + device_printf(softc->dev, "STUB: %s @ %s:%d\n", __func__, __FILE__, __LINE__); + return ENOSYS; +} diff --git a/sys/dev/bnxt/convert_hsi.pl b/sys/dev/bnxt/convert_hsi.pl new file mode 100755 index 00000000000..b8a9887d720 --- /dev/null +++ b/sys/dev/bnxt/convert_hsi.pl @@ -0,0 +1,356 @@ +#!/usr/bin/env perl + +# This script cleans up the "official" Broadcom hsi_struct_defs.h file as distributed +# to something somewhat more programmer friendly. +# +# $FreeBSD$ + +my $do_decode = 0; + +if (! -f $ARGV[0]) { + print "Input file not specified (should be path to hsi_struct_defs.h)\n"; + exit 1; +} + +if (!open(IN, "<", $ARGV[0])) { + print "Failure to open input file\n"; + exit 1; +} + +if (!open(OUT, ">", "hsi_struct_def.h")) { + print "Failure to open output file\n"; + exit 1; +} + +$/=undef; +my $header = ; +close IN; + +print OUT < +__FBSDID("\$FreeBSD\$"); + +END_OF_NOTICE + +# Convert line endings +$header =~ s/\r\n/\n/gs; + +# Convert arrays of two u32_t to a single uint64_t +$header =~ s/\bu32_t(\s+[a-zA-Z0-9_]+)\[2\]/uint64_t$1/gs; + +# Convert uint32_t *_lo/uint32_t *_hi to a single uint64_t +$header =~ s/\bu32_t(\s+[a-zA-Z0-9_]+)_lo;\s*\r?\n\s*u32_t(\s+[a-zA-Z0-9_]+)_hi/uint64_t$1/gs; + +# Convert types +$header =~ s/\bu([0-9]+)_t\b/uint$1_t/gs; + +# Convert literals +$header =~ s/\b((?:0x)?[0-9a-f]+)UL/UINT32_C($1)/gs; + +# Strip comments +#$header =~ s/^(\s*[^\/\s][^\/]+?)\s*\/\*.*?\*\/\s*?$/$1/gm; +#$header =~ s/[ \t]*\/\*.*?\*\/\s*?\n?//gs; + +# Pack structs +#$header =~ s/}(\s+)([^\s]+_t[,;])/} __attribute__((packed))$1$2/gs; + +# Normalize indent +$header =~ s/( ) +(#define)/$1$2/gs; +$header =~ s/^(}[^\n]*;)\n([^\n])/$1\n\n$2/gsm; +$header =~ s/([^\n])\n(typedef)/$1\n\n$2/gs; +$header =~ s/ /\t/g; +$header =~ s/ /\t/g; +$header =~ s/([^\s]\t+) +/$1/g; + +# Remove typedefs and pack structs +$header =~ s/^typedef struct (.*?)\n{\n(.*?)}[^\n]*;/struct $1 {\n$2} __attribute__((packed));/gsm; + +print OUT $header; +close OUT; + +if ($do_decode) { + if(!open(OUT, ">", "hsi_struct_decode.c")) { + print "Failure to open decoder output file\n"; + exit 1; + } + + print OUT < + __FBSDID("\$FreeBSD\$"); + +END_OF_NOTICE + + if(!open(HDR, ">", "hsi_struct_decode.h")) { + print "Failure to open decoder output header file\n"; + exit 1; + } + + print HDR <\n#include \n#include \n#include \"hsi_struct_def_dpdk.h\"\n#include \"hsi_struct_decode.h\"\n#include \"hsi_struct_decode.h\"\n\n"; + print HDR "#ifdef HSI_DEBUG\n#include \"hsi_struct_def_dpdk.h\"\n\n"; + + my $hdr_defs = ''; + + sub print_single_val + { + my $field=shift; + my $type=shift; + my $max_field_len=shift; + my $name = shift; + my $macroshash = shift; + my %macros = %$macroshash; + $macrosref = shift; + my @macros = @$macrosref; + $macrosref = shift; + my @fields = @$macrosref; + + if ($type eq 'uint32_t') { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%08\"PRIX32\"\\n\", data->$field);\n",$max_field_len,$field; + } + elsif ($type eq 'uint16_t') { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%04\"PRIX16\"\\n\", data->$field);\n",$max_field_len,$field; + } + elsif ($type eq 'uint8_t') { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%02\"PRIX8\"\\n\", data->$field);\n",$max_field_len,$field; + } + elsif ($type eq 'uint64_t') { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%016\"PRIX64\"\\n\", data->$field);\n",$max_field_len,$field; + } + elsif ($type eq 'char') { + if ($field =~ s/\[([0-9]+)\]//) { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = \\\"%%.$1s\\\"\\n\", data->$field);\n",$max_field_len,$field; + } + else { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s = 0x%%02\"PRIX8\"\\n\", data->$field);\n",$max_field_len,$field; + } + } + else { + print "Unhandled type: '$type'\n"; + } + + my $macro_prefix = uc($name).'_'.uc($field).'_'; + # Special handling for the common flags_type field + $macro_prefix =~ s/FLAGS_TYPE_$/FLAGS_/ if ($field eq 'flags_type'); + # Special handling for _hi types + $macro_prefix =~ s/_HI_/_/ if ($name =~ /_hi$/); + + $macro_prefix =~ s/\[[0-9]+\]//; + my %vmacros; + my $vmacros_have_mask = 0; + my @vmacros; + my %subfields; + my $all_single_bits=1; + MACRO: + foreach my $macro (@macros) { + if ($macro =~ /^$macro_prefix(.*)_MASK$/) { + my $macro = $&; + my $maskdef = $macros{$macro}; + my $subfield = $1; + my $subfield_value = "(data->$field & $macro)"; + if (defined $macros{"$macro_prefix$subfield\_SFT"}) { + $subfield_value = "($subfield_value >> $macro_prefix$subfield\_SFT)"; + } + $maskdef =~ s/[x0 ]//g; + if ($type eq 'uint64_t') { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s $subfield = %%0*\" PRIX64 \"\\n\", %u, $subfield_value);\n", $max_field_len, '', length($maskdef); + } + else { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s $subfield = %%0*X\\n\", %u, $subfield_value);\n", $max_field_len, '', length($maskdef); + } + delete $$macroshash{$macro}; + } + elsif ($macro =~ /^$macro_prefix(.*)_SFT$/) { + delete $$macroshash{$macro}; + } + elsif ($macro =~ /^$macro_prefix\MASK$/) { + $vmacros_have_mask = 1; + delete $$macroshash{$macro}; + } + elsif ($macro =~ /^$macro_prefix(.*)$/) { + my $macro = $&; + my $subfield = $1; + + # Check for longer fields with the same base... ie: link and link_speed + foreach my $extra_field (@fields) { + next if ($extra_field eq $field); + if ($extra_field =~ /^$field/) { + my $extra_prefix = uc($name).'_'.uc($extra_field).'_'; + next MACRO if ($macro =~ /^$extra_prefix/); + } + } + + push @vmacros, $macro; + my $macroeval = $macros{$macro}; + $macroeval =~ s/UINT32_C\((.*?)\)/$1/g; + $vmacros{$macro} = eval("$macroeval"); + $subfields{$macro} = $subfield; + + $all_single_bits = 0 if ($vmacros{$macro} & ($vmacros{$macro}-1)); + $all_single_bits = 0 if ($vmacros{$macro} == 0); + } + } + if ($all_single_bits) { + foreach my $macro (@vmacros) { + my $subfield_value = "(data->$field & $macro)"; + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s $subfields{$macro} : %%s\\n\", $subfield_value?\"ON\":\"OFF\");\n", $max_field_len, ''; + delete $$macroshash{$macro}; + } + } + else { + printf OUT "\tRTE_LOG(DEBUG, PMD, \" % *s Value : %%s\\n\",\n", $max_field_len, ''; + foreach my $macro (@vmacros) { + my $subfield_value = "data->$field"; + $subfield_value = "($subfield_value & $macro_prefix\MASK)" if $vmacros_have_mask; + print OUT "\t\t$subfield_value == $macro ? \"$subfields{$macro}\" :\n"; + delete $$macroshash{$macro}; + } + print OUT "\t\t\"Unknown\");\n"; + } + } + + while ($header =~ /^typedef\s+struct\s+(.*?)\s+{(.*?)^}/msg) { + my ($name,$def) = ($1, $2); + my @fields=(); + my %type=(); + my @macros=(); + my %macros=(); + my $max_field_len=0; + + # First, pull out all the fields in order... + while($def =~ /^\s*([^\s#\/]+?)\s+([^;\/\s]+?)\s*;/mg) { + my ($type, $name) = ($1, $2); + push @fields, $name; + $type{$name}=$type; + $max_field_len = length($name) if length($name) > $max_field_len; + } + # Now, pull out the macros... + while($def =~ /^\s*\#define\s+([^\s]+?)\s+(.*?)\s*$/mg) { + push @macros, $1; + $macros{$1}=$2; + } + + # Now, generate code to print the struct... + print OUT "void decode_$name(const char *string __rte_unused, struct $name *data) {\n\tRTE_LOG(DEBUG, PMD, \"$name\\n\");\n"; + print HDR "void decode_$name(const char *string __rte_unused, struct $name *data);\n"; + $hdr_defs .= "#define decode_$name(x, y) {}\n"; + foreach my $field (@fields) { + if ($field =~ /\[([0-9]+)\]/) { + if ($type{$field} eq 'char') { + print_single_val($field, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields); + } + else { + foreach my $idx (0..$1-1) { + my $item = $field; + $item =~ s/\[[0-9]+\]/[$idx]/; + print_single_val($item, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields); + } + } + } + else { + print_single_val($field, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields); + } + } + # print "Unhandled macros:\n",join("\n", keys %macros),"\n" if (keys %macros > 0); + print OUT "}\n\n"; + } + print OUT "#endif\n"; + + print HDR "#else\n"; + print HDR $hdr_defs; + print HDR "#endif\n"; + close OUT; + close HDR; +} diff --git a/sys/dev/bnxt/hsi_struct_def.h b/sys/dev/bnxt/hsi_struct_def.h new file mode 100644 index 00000000000..d55efee3e6c --- /dev/null +++ b/sys/dev/bnxt/hsi_struct_def.h @@ -0,0 +1,17576 @@ +/*- + * BSD LICENSE + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +/**************************************************************************** + * + * Description: Definition of HSI data structures + * + * Date: 07/26/16 21:30:37 + * + * Note: This file is scripted generated by hsi_decode.py. + * DO NOT modify this file manually !!!! + * + ****************************************************************************/ +#ifndef _HSI_STRUCT_DEF_EXTERNAL_H_ +#define _HSI_STRUCT_DEF_EXTERNAL_H_ + +/* + * per-context HW statistics -- chip view + * Reference to stat_ctx_stat_xxx for + */ + +struct ctx_hw_stats { + uint64_t rx_ucast_pkts; + uint64_t rx_mcast_pkts; + uint64_t rx_bcast_pkts; + uint64_t rx_discard_pkts; + uint64_t rx_drop_pkts; + uint64_t rx_ucast_bytes; + uint64_t rx_mcast_bytes; + uint64_t rx_bcast_bytes; + uint64_t tx_ucast_pkts; + uint64_t tx_mcast_pkts; + uint64_t tx_bcast_pkts; + uint64_t tx_discard_pkts; + uint64_t tx_drop_pkts; + uint64_t tx_ucast_bytes; + uint64_t tx_mcast_bytes; + uint64_t tx_bcast_bytes; + uint64_t tpa_pkts; + uint64_t tpa_bytes; + uint64_t tpa_events; + uint64_t tpa_aborts; +} __attribute__((packed)); + +/* BD Ring Structures */ +/* + * Description: This structure is used to inform the NIC of a location for and + * an aggregation buffer that will be used for packet data that is received. An + * aggregation buffer creates a different kind of completion operation for a + * packet where a variable number of BDs may be used to place the packet in the + * host. RX Rings that have aggregation buffers are known as aggregation rings + * and must contain only aggregation buffers. + */ +/* + * Note: BD Ring structures are written by the driver to TX Rings and RX Rings + * to indicate to the chip there is more buffer space in the host that needs to + * be transmitted or is available for receive data. + */ +/* BD Base (8 bytes) */ + +struct bd_base { + uint8_t type; + /* This value identifies the type of buffer descriptor. */ + #define BD_BASE_TYPE_MASK UINT32_C(0x3f) + #define BD_BASE_TYPE_SFT 0 + /* + * Indicates that this BD is 16B long and is used for normal L2 + * packet transmission. + */ + #define BD_BASE_TYPE_TX_BD_SHORT UINT32_C(0x0) + /* + * Indicates that this BD is 1BB long and is an empty TX BD. Not + * valid for use by the driver. + */ + #define BD_BASE_TYPE_TX_BD_EMPTY UINT32_C(0x1) + /* + * Indicates that this BD is 16B long and is an RX Producer (ie. + * empty) buffer descriptor. + */ + #define BD_BASE_TYPE_RX_PROD_PKT UINT32_C(0x4) + /* + * Indicates that this BD is 16B long and is an RX Producer + * Buffer BD. + */ + #define BD_BASE_TYPE_RX_PROD_BFR UINT32_C(0x5) + /* + * Indicates that this BD is 16B long and is an RX Producer + * Assembly Buffer Descriptor. + */ + #define BD_BASE_TYPE_RX_PROD_AGG UINT32_C(0x6) + /* + * Indicates that this BD is 32B long and is used for normal L2 + * packet transmission. + */ + #define BD_BASE_TYPE_TX_BD_LONG UINT32_C(0x10) + uint8_t unused_1[7]; +} __attribute__((packed)); + +/* Short TX BD (16 bytes) */ + +struct tx_bd_short { + uint16_t flags_type; + /* + * All bits in this field must be valid on the first BD of a packet. + * Only the packet_end bit must be valid for the remaining BDs of a + * packet. + */ + /* This value identifies the type of buffer descriptor. */ + #define TX_BD_SHORT_TYPE_MASK UINT32_C(0x3f) + #define TX_BD_SHORT_TYPE_SFT 0 + /* + * Indicates that this BD is 16B long and is used for normal L2 + * packet transmission. + */ + #define TX_BD_SHORT_TYPE_TX_BD_SHORT UINT32_C(0x0) + /* + * If set to 1, the packet ends with the data in the buffer pointed to + * by this descriptor. This flag must be valid on every BD. + */ + #define TX_BD_SHORT_FLAGS_PACKET_END UINT32_C(0x40) + /* + * If set to 1, the device will not generate a completion for this + * transmit packet unless there is an error in it's processing. If this + * bit is set to 0, then the packet will be completed normally. This bit + * must be valid only on the first BD of a packet. + */ + #define TX_BD_SHORT_FLAGS_NO_CMPL UINT32_C(0x80) + /* + * This value indicates how many 16B BD locations are consumed in the + * ring by this packet. A value of 1 indicates that this BD is the only + * BD (and that the it is a short BD). A value of 3 indicates either 3 + * short BDs or 1 long BD and one short BD in the packet. A value of 0 + * indicates that there are 32 BD locations in the packet (the maximum). + * This field is valid only on the first BD of a packet. + */ + #define TX_BD_SHORT_FLAGS_BD_CNT_MASK UINT32_C(0x1f00) + #define TX_BD_SHORT_FLAGS_BD_CNT_SFT 8 + /* + * This value is a hint for the length of the entire packet. It is used + * by the chip to optimize internal processing. The packet will be + * dropped if the hint is too short. This field is valid only on the + * first BD of a packet. + */ + #define TX_BD_SHORT_FLAGS_LHINT_MASK UINT32_C(0x6000) + #define TX_BD_SHORT_FLAGS_LHINT_SFT 13 + /* indicates packet length < 512B */ + #define TX_BD_SHORT_FLAGS_LHINT_LT512 (UINT32_C(0x0) << 13) + /* indicates 512 <= packet length < 1KB */ + #define TX_BD_SHORT_FLAGS_LHINT_LT1K (UINT32_C(0x1) << 13) + /* indicates 1KB <= packet length < 2KB */ + #define TX_BD_SHORT_FLAGS_LHINT_LT2K (UINT32_C(0x2) << 13) + /* indicates packet length >= 2KB */ + #define TX_BD_SHORT_FLAGS_LHINT_GTE2K (UINT32_C(0x3) << 13) + #define TX_BD_SHORT_FLAGS_LHINT_LAST TX_BD_SHORT_FLAGS_LHINT_GTE2K + /* + * If set to 1, the device immediately updates the Send Consumer Index + * after the buffer associated with this descriptor has been transferred + * via DMA to NIC memory from host memory. An interrupt may or may not + * be generated according to the state of the interrupt avoidance + * mechanisms. If this bit is set to 0, then the Consumer Index is only + * updated as soon as one of the host interrupt coalescing conditions + * has been met. This bit must be valid on the first BD of a packet. + */ + #define TX_BD_SHORT_FLAGS_COAL_NOW UINT32_C(0x8000) + /* + * All bits in this field must be valid on the first BD of a packet. + * Only the packet_end bit must be valid for the remaining BDs of a + * packet. + */ + #define TX_BD_SHORT_FLAGS_MASK UINT32_C(0xffc0) + #define TX_BD_SHORT_FLAGS_SFT 6 + uint16_t len; + /* + * This is the length of the host physical buffer this BD describes in + * bytes. This field must be valid on all BDs of a packet. + */ + uint32_t opaque; + /* + * The opaque data field is pass through to the completion and can be + * used for any data that the driver wants to associate with the + * transmit BD. This field must be valid on the first BD of a packet. + */ + uint64_t addr; + /* + * This is the host physical address for the portion of the packet + * described by this TX BD. This value must be valid on all BDs of a + * packet. + */ +} __attribute__((packed)); + +/* Long TX BD (32 bytes split to 2 16-byte struct) */ + +struct tx_bd_long { + uint16_t flags_type; + /* + * All bits in this field must be valid on the first BD of a packet. + * Only the packet_end bit must be valid for the remaining BDs of a + * packet. + */ + /* This value identifies the type of buffer descriptor. */ + #define TX_BD_LONG_TYPE_MASK UINT32_C(0x3f) + #define TX_BD_LONG_TYPE_SFT 0 + /* + * Indicates that this BD is 32B long and is used for normal L2 + * packet transmission. + */ + #define TX_BD_LONG_TYPE_TX_BD_LONG UINT32_C(0x10) + /* + * If set to 1, the packet ends with the data in the buffer pointed to + * by this descriptor. This flag must be valid on every BD. + */ + #define TX_BD_LONG_FLAGS_PACKET_END UINT32_C(0x40) + /* + * If set to 1, the device will not generate a completion for this + * transmit packet unless there is an error in it's processing. If this + * bit is set to 0, then the packet will be completed normally. This bit + * must be valid only on the first BD of a packet. + */ + #define TX_BD_LONG_FLAGS_NO_CMPL UINT32_C(0x80) + /* + * This value indicates how many 16B BD locations are consumed in the + * ring by this packet. A value of 1 indicates that this BD is the only + * BD (and that the it is a short BD). A value of 3 indicates either 3 + * short BDs or 1 long BD and one short BD in the packet. A value of 0 + * indicates that there are 32 BD locations in the packet (the maximum). + * This field is valid only on the first BD of a packet. + */ + #define TX_BD_LONG_FLAGS_BD_CNT_MASK UINT32_C(0x1f00) + #define TX_BD_LONG_FLAGS_BD_CNT_SFT 8 + /* + * This value is a hint for the length of the entire packet. It is used + * by the chip to optimize internal processing. The packet will be + * dropped if the hint is too short. This field is valid only on the + * first BD of a packet. + */ + #define TX_BD_LONG_FLAGS_LHINT_MASK UINT32_C(0x6000) + #define TX_BD_LONG_FLAGS_LHINT_SFT 13 + /* indicates packet length < 512B */ + #define TX_BD_LONG_FLAGS_LHINT_LT512 (UINT32_C(0x0) << 13) + /* indicates 512 <= packet length < 1KB */ + #define TX_BD_LONG_FLAGS_LHINT_LT1K (UINT32_C(0x1) << 13) + /* indicates 1KB <= packet length < 2KB */ + #define TX_BD_LONG_FLAGS_LHINT_LT2K (UINT32_C(0x2) << 13) + /* indicates packet length >= 2KB */ + #define TX_BD_LONG_FLAGS_LHINT_GTE2K (UINT32_C(0x3) << 13) + #define TX_BD_LONG_FLAGS_LHINT_LAST TX_BD_LONG_FLAGS_LHINT_GTE2K + /* + * If set to 1, the device immediately updates the Send Consumer Index + * after the buffer associated with this descriptor has been transferred + * via DMA to NIC memory from host memory. An interrupt may or may not + * be generated according to the state of the interrupt avoidance + * mechanisms. If this bit is set to 0, then the Consumer Index is only + * updated as soon as one of the host interrupt coalescing conditions + * has been met. This bit must be valid on the first BD of a packet. + */ + #define TX_BD_LONG_FLAGS_COAL_NOW UINT32_C(0x8000) + /* + * All bits in this field must be valid on the first BD of a packet. + * Only the packet_end bit must be valid for the remaining BDs of a + * packet. + */ + #define TX_BD_LONG_FLAGS_MASK UINT32_C(0xffc0) + #define TX_BD_LONG_FLAGS_SFT 6 + uint16_t len; + /* + * This is the length of the host physical buffer this BD describes in + * bytes. This field must be valid on all BDs of a packet. + */ + uint32_t opaque; + /* + * The opaque data field is pass through to the completion and can be + * used for any data that the driver wants to associate with the + * transmit BD. This field must be valid on the first BD of a packet. + */ + uint64_t addr; + /* + * This is the host physical address for the portion of the packet + * described by this TX BD. This value must be valid on all BDs of a + * packet. + */ +} __attribute__((packed)); + +/* last 16 bytes of Long TX BD */ + +struct tx_bd_long_hi { + uint16_t lflags; + /* + * All bits in this field must be valid on the first BD of a packet. + * Their value on other BDs of the packet will be ignored. + */ + /* + * If set to 1, the controller replaces the TCP/UPD checksum fields of + * normal TCP/UPD checksum, or the inner TCP/UDP checksum field of the + * encapsulated TCP/UDP packets with the hardware calculated TCP/UDP + * checksum for the packet associated with this descriptor. The flag is + * ignored if the LSO flag is set. This bit must be valid on the first + * BD of a packet. + */ + #define TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1) + /* + * If set to 1, the controller replaces the IP checksum of the normal + * packets, or the inner IP checksum of the encapsulated packets with + * the hardware calculated IP checksum for the packet associated with + * this descriptor. This bit must be valid on the first BD of a packet. + */ + #define TX_BD_LONG_LFLAGS_IP_CHKSUM UINT32_C(0x2) + /* + * If set to 1, the controller will not append an Ethernet CRC to the + * end of the frame. This bit must be valid on the first BD of a packet. + * Packet must be 64B or longer when this flag is set. It is not useful + * to use this bit with any form of TX offload such as CSO or LSO. The + * intent is that the packet from the host already has a valid Ethernet + * CRC on the packet. + */ + #define TX_BD_LONG_LFLAGS_NOCRC UINT32_C(0x4) + /* + * If set to 1, the device will record the time at which the packet was + * actually transmitted at the TX MAC. This bit must be valid on the + * first BD of a packet. + */ + #define TX_BD_LONG_LFLAGS_STAMP UINT32_C(0x8) + /* + * If set to 1, The controller replaces the tunnel IP checksum field + * with hardware calculated IP checksum for the IP header of the packet + * associated with this descriptor. For outer UDP checksum, global outer + * UDP checksum TE_NIC register needs to be enabled. If the global outer + * UDP checksum TE_NIC register bit is set, outer UDP checksum will be + * calculated for the following cases: 1. Packets with tcp_udp_chksum + * flag set to offload checksum for inner packet AND the inner packet is + * TCP/UDP. If the inner packet is ICMP for example (non-TCP/UDP), even + * if the tcp_udp_chksum is set, the outer UDP checksum will not be + * calculated. 2. Packets with lso flag set which implies inner TCP + * checksum calculation as part of LSO operation. + */ + #define TX_BD_LONG_LFLAGS_T_IP_CHKSUM UINT32_C(0x10) + /* + * If set to 1, the device will treat this packet with LSO(Large Send + * Offload) processing for both normal or encapsulated packets, which is + * a form of TCP segmentation. When this bit is 1, the hdr_size and mss + * fields must be valid. The driver doesn't need to set t_ip_chksum, + * ip_chksum, and tcp_udp_chksum flags since the controller will replace + * the appropriate checksum fields for segmented packets. When this bit + * is 1, the hdr_size and mss fields must be valid. + */ + #define TX_BD_LONG_LFLAGS_LSO UINT32_C(0x20) + /* + * If set to zero when LSO is '1', then the IPID will be treated as a + * 16b number and will be wrapped if it exceeds a value of 0xffff. If + * set to one when LSO is '1', then the IPID will be treated as a 15b + * number and will be wrapped if it exceeds a value 0f 0x7fff. + */ + #define TX_BD_LONG_LFLAGS_IPID_FMT UINT32_C(0x40) + /* + * If set to zero when LSO is '1', then the IPID of the tunnel IP header + * will not be modified during LSO operations. If set to one when LSO is + * '1', then the IPID of the tunnel IP header will be incremented for + * each subsequent segment of an LSO operation. The flag is ignored if + * the LSO packet is a normal (non-tunneled) TCP packet. + */ + #define TX_BD_LONG_LFLAGS_T_IPID UINT32_C(0x80) + /* + * If set to '1', then the RoCE ICRC will be appended to the packet. + * Packet must be a valid RoCE format packet. + */ + #define TX_BD_LONG_LFLAGS_ROCE_CRC UINT32_C(0x100) + /* + * If set to '1', then the FCoE CRC will be appended to the packet. + * Packet must be a valid FCoE format packet. + */ + #define TX_BD_LONG_LFLAGS_FCOE_CRC UINT32_C(0x200) + uint16_t hdr_size; + /* + * When LSO is '1', this field must contain the offset of the TCP + * payload from the beginning of the packet in as 16b words. In case of + * encapsulated/tunneling packet, this field contains the offset of the + * inner TCP payload from beginning of the packet as 16-bit words. This + * value must be valid on the first BD of a packet. + */ + #define TX_BD_LONG_HDR_SIZE_MASK UINT32_C(0x1ff) + #define TX_BD_LONG_HDR_SIZE_SFT 0 + uint32_t mss; + /* + * This is the MSS value that will be used to do the LSO processing. The + * value is the length in bytes of the TCP payload for each segment + * generated by the LSO operation. This value must be valid on the first + * BD of a packet. + */ + #define TX_BD_LONG_MSS_MASK UINT32_C(0x7fff) + #define TX_BD_LONG_MSS_SFT 0 + uint16_t unused_2; + uint16_t cfa_action; + /* + * This value selects a CFA action to perform on the packet. Set this + * value to zero if no CFA action is desired. This value must be valid + * on the first BD of a packet. + */ + uint32_t cfa_meta; + /* + * This value is action meta-data that defines CFA edit operations that + * are done in addition to any action editing. + */ + /* When key=1, This is the VLAN tag VID value. */ + #define TX_BD_LONG_CFA_META_VLAN_VID_MASK UINT32_C(0xfff) + #define TX_BD_LONG_CFA_META_VLAN_VID_SFT 0 + /* When key=1, This is the VLAN tag DE value. */ + #define TX_BD_LONG_CFA_META_VLAN_DE UINT32_C(0x1000) + /* When key=1, This is the VLAN tag PRI value. */ + #define TX_BD_LONG_CFA_META_VLAN_PRI_MASK UINT32_C(0xe000) + #define TX_BD_LONG_CFA_META_VLAN_PRI_SFT 13 + /* When key=1, This is the VLAN tag TPID select value. */ + #define TX_BD_LONG_CFA_META_VLAN_TPID_MASK UINT32_C(0x70000) + #define TX_BD_LONG_CFA_META_VLAN_TPID_SFT 16 + /* 0x88a8 */ + #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID88A8 (UINT32_C(0x0) << 16) + /* 0x8100 */ + #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID8100 (UINT32_C(0x1) << 16) + /* 0x9100 */ + #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID9100 (UINT32_C(0x2) << 16) + /* 0x9200 */ + #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID9200 (UINT32_C(0x3) << 16) + /* 0x9300 */ + #define TX_BD_LONG_CFA_META_VLAN_TPID_TPID9300 (UINT32_C(0x4) << 16) + /* Value programmed in CFA VLANTPID register. */ + #define TX_BD_LONG_CFA_META_VLAN_TPID_TPIDCFG (UINT32_C(0x5) << 16) + #define TX_BD_LONG_CFA_META_VLAN_TPID_LAST TX_BD_LONG_CFA_META_VLAN_TPID_TPIDCFG + /* When key=1, This is the VLAN tag TPID select value. */ + #define TX_BD_LONG_CFA_META_VLAN_RESERVED_MASK UINT32_C(0xff80000) + #define TX_BD_LONG_CFA_META_VLAN_RESERVED_SFT 19 + /* + * This field identifies the type of edit to be performed on the packet. + * This value must be valid on the first BD of a packet. + */ + #define TX_BD_LONG_CFA_META_KEY_MASK UINT32_C(0xf0000000) + #define TX_BD_LONG_CFA_META_KEY_SFT 28 + /* No editing */ + #define TX_BD_LONG_CFA_META_KEY_NONE (UINT32_C(0x0) << 28) + /* + * - meta[17:16] - TPID select value (0 = 0x8100). - meta[15:12] + * - PRI/DE value. - meta[11:0] - VID value. + */ + #define TX_BD_LONG_CFA_META_KEY_VLAN_TAG (UINT32_C(0x1) << 28) + #define TX_BD_LONG_CFA_META_KEY_LAST TX_BD_LONG_CFA_META_KEY_VLAN_TAG +} __attribute__((packed)); + +/* Empty TX BD (16 bytes) */ + +struct tx_bd_empty { + uint8_t type; + /* This value identifies the type of buffer descriptor. */ + #define TX_BD_EMPTY_TYPE_MASK UINT32_C(0x3f) + #define TX_BD_EMPTY_TYPE_SFT 0 + /* + * Indicates that this BD is 1BB long and is an empty TX BD. Not + * valid for use by the driver. + */ + #define TX_BD_EMPTY_TYPE_TX_BD_EMPTY UINT32_C(0x1) + uint8_t unused_1[3]; + uint8_t unused_2; + uint8_t unused_3[3]; + uint64_t unused_4; +} __attribute__((packed)); + +/* RX Producer Packet BD (16 bytes) */ + +struct rx_prod_pkt_bd { + uint16_t flags_type; + /* This value identifies the type of buffer descriptor. */ + #define RX_PROD_PKT_BD_TYPE_MASK UINT32_C(0x3f) + #define RX_PROD_PKT_BD_TYPE_SFT 0 + /* + * Indicates that this BD is 16B long and is an RX Producer (ie. + * empty) buffer descriptor. + */ + #define RX_PROD_PKT_BD_TYPE_RX_PROD_PKT UINT32_C(0x4) + /* + * If set to 1, the packet will be placed at the address plus 2B. The 2 + * Bytes of padding will be written as zero. + */ + /* + * This is intended to be used when the host buffer is cache-line + * aligned to produce packets that are easy to parse in host memory + * while still allowing writes to be cache line aligned. + */ + #define RX_PROD_PKT_BD_FLAGS_SOP_PAD UINT32_C(0x40) + /* + * If set to 1, the packet write will be padded out to the nearest + * cache-line with zero value padding. + */ + /* + * If receive buffers start/end on cache-line boundaries, this feature + * will ensure that all data writes on the PCI bus start/end on cache + * line boundaries. + */ + #define RX_PROD_PKT_BD_FLAGS_EOP_PAD UINT32_C(0x80) + /* + * This value is the number of additional buffers in the ring that + * describe the buffer space to be consumed for the this packet. If the + * value is zero, then the packet must fit within the space described by + * this BD. If this value is 1 or more, it indicates how many additional + * "buffer" BDs are in the ring immediately following this BD to be used + * for the same network packet. Even if the packet to be placed does not + * need all the additional buffers, they will be consumed anyway. + */ + #define RX_PROD_PKT_BD_FLAGS_BUFFERS_MASK UINT32_C(0x300) + #define RX_PROD_PKT_BD_FLAGS_BUFFERS_SFT 8 + #define RX_PROD_PKT_BD_FLAGS_MASK UINT32_C(0xffc0) + #define RX_PROD_PKT_BD_FLAGS_SFT 6 + uint16_t len; + /* + * This is the length in Bytes of the host physical buffer where data + * for the packet may be placed in host memory. + */ + /* + * While this is a Byte resolution value, it is often advantageous to + * ensure that the buffers provided end on a host cache line. + */ + uint32_t opaque; + /* + * The opaque data field is pass through to the completion and can be + * used for any data that the driver wants to associate with this + * receive buffer set. + */ + uint64_t addr; + /* + * This is the host physical address where data for the packet may by + * placed in host memory. + */ + /* + * While this is a Byte resolution value, it is often advantageous to + * ensure that the buffers provide start on a host cache line. + */ +} __attribute__((packed)); + +/* RX Producer Buffer BD (16 bytes) */ + +struct rx_prod_bfr_bd { + uint16_t flags_type; + /* This value identifies the type of buffer descriptor. */ + #define RX_PROD_BFR_BD_TYPE_MASK UINT32_C(0x3f) + #define RX_PROD_BFR_BD_TYPE_SFT 0 + /* + * Indicates that this BD is 16B long and is an RX Producer + * Buffer BD. + */ + #define RX_PROD_BFR_BD_TYPE_RX_PROD_BFR UINT32_C(0x5) + #define RX_PROD_BFR_BD_FLAGS_MASK UINT32_C(0xffc0) + #define RX_PROD_BFR_BD_FLAGS_SFT 6 + uint16_t len; + /* + * This is the length in Bytes of the host physical buffer where data + * for the packet may be placed in host memory. + */ + /* + * While this is a Byte resolution value, it is often advantageous to + * ensure that the buffers provided end on a host cache line. + */ + uint32_t opaque; + /* This field is not used. */ + uint64_t addr; + /* + * This is the host physical address where data for the packet may by + * placed in host memory. + */ + /* + * While this is a Byte resolution value, it is often advantageous to + * ensure that the buffers provide start on a host cache line. + */ +} __attribute__((packed)); + +/* RX Producer Aggregation BD (16 bytes) */ + +struct rx_prod_agg_bd { + uint16_t flags_type; + /* This value identifies the type of buffer descriptor. */ + #define RX_PROD_AGG_BD_TYPE_MASK UINT32_C(0x3f) + #define RX_PROD_AGG_BD_TYPE_SFT 0 + /* + * Indicates that this BD is 16B long and is an RX Producer + * Assembly Buffer Descriptor. + */ + #define RX_PROD_AGG_BD_TYPE_RX_PROD_AGG UINT32_C(0x6) + /* + * If set to 1, the packet write will be padded out to the nearest + * cache-line with zero value padding. + */ + /* + * If receive buffers start/end on cache-line boundaries, this feature + * will ensure that all data writes on the PCI bus end on cache line + * boundaries. + */ + #define RX_PROD_AGG_BD_FLAGS_EOP_PAD UINT32_C(0x40) + #define RX_PROD_AGG_BD_FLAGS_MASK UINT32_C(0xffc0) + #define RX_PROD_AGG_BD_FLAGS_SFT 6 + uint16_t len; + /* + * This is the length in Bytes of the host physical buffer where data + * for the packet may be placed in host memory. + */ + /* + * While this is a Byte resolution value, it is often advantageous to + * ensure that the buffers provided end on a host cache line. + */ + uint32_t opaque; + /* + * The opaque data field is pass through to the completion and can be + * used for any data that the driver wants to associate with this + * receive assembly buffer. + */ + uint64_t addr; + /* + * This is the host physical address where data for the packet may by + * placed in host memory. + */ + /* + * While this is a Byte resolution value, it is often advantageous to + * ensure that the buffers provide start on a host cache line. + */ +} __attribute__((packed)); + +/* Completion Ring Structures */ +/* Note: This structure is used by the HWRM to communicate HWRM Error. */ +/* Base Completion Record (16 bytes) */ + +struct cmpl_base { + uint16_t type; + /* unused is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define CMPL_BASE_TYPE_MASK UINT32_C(0x3f) + #define CMPL_BASE_TYPE_SFT 0 + /* TX L2 completion: Completion of TX packet. Length = 16B */ + #define CMPL_BASE_TYPE_TX_L2 UINT32_C(0x0) + /* RX L2 completion: Completion of and L2 RX packet. Length = 32B */ + #define CMPL_BASE_TYPE_RX_L2 UINT32_C(0x11) + /* + * RX Aggregation Buffer completion : Completion of an L2 + * aggregation buffer in support of TPA, HDS, or Jumbo packet + * completion. Length = 16B + */ + #define CMPL_BASE_TYPE_RX_AGG UINT32_C(0x12) + /* + * RX L2 TPA Start Completion: Completion at the beginning of a + * TPA operation. Length = 32B + */ + #define CMPL_BASE_TYPE_RX_TPA_START UINT32_C(0x13) + /* + * RX L2 TPA End Completion: Completion at the end of a TPA + * operation. Length = 32B + */ + #define CMPL_BASE_TYPE_RX_TPA_END UINT32_C(0x15) + /* + * Statistics Ejection Completion: Completion of statistics data + * ejection buffer. Length = 16B + */ + #define CMPL_BASE_TYPE_STAT_EJECT UINT32_C(0x1a) + /* HWRM Command Completion: Completion of an HWRM command. */ + #define CMPL_BASE_TYPE_HWRM_DONE UINT32_C(0x20) + /* Forwarded HWRM Request */ + #define CMPL_BASE_TYPE_HWRM_FWD_REQ UINT32_C(0x22) + /* Forwarded HWRM Response */ + #define CMPL_BASE_TYPE_HWRM_FWD_RESP UINT32_C(0x24) + /* HWRM Asynchronous Event Information */ + #define CMPL_BASE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* CQ Notification */ + #define CMPL_BASE_TYPE_CQ_NOTIFICATION UINT32_C(0x30) + /* SRQ Threshold Event */ + #define CMPL_BASE_TYPE_SRQ_EVENT UINT32_C(0x32) + /* DBQ Threshold Event */ + #define CMPL_BASE_TYPE_DBQ_EVENT UINT32_C(0x34) + /* QP Async Notification */ + #define CMPL_BASE_TYPE_QP_EVENT UINT32_C(0x38) + /* Function Async Notification */ + #define CMPL_BASE_TYPE_FUNC_EVENT UINT32_C(0x3a) + /* unused is 10 b */ + uint16_t info1; + /* info1 is 16 b */ + uint32_t info2; + /* info2 is 32 b */ + uint32_t info3_v; + /* info3 is 31 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define CMPL_BASE_V UINT32_C(0x1) + /* info3 is 31 b */ + #define CMPL_BASE_INFO3_MASK UINT32_C(0xfffffffe) + #define CMPL_BASE_INFO3_SFT 1 + uint32_t info4; + /* info4 is 32 b */ +} __attribute__((packed)); + +/* TX Completion Record (16 bytes) */ + +struct tx_cmpl { + uint16_t flags_type; + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define TX_CMPL_TYPE_MASK UINT32_C(0x3f) + #define TX_CMPL_TYPE_SFT 0 + /* TX L2 completion: Completion of TX packet. Length = 16B */ + #define TX_CMPL_TYPE_TX_L2 UINT32_C(0x0) + /* + * When this bit is '1', it indicates a packet that has an error of some + * type. Type of error is indicated in error_flags. + */ + #define TX_CMPL_FLAGS_ERROR UINT32_C(0x40) + /* + * When this bit is '1', it indicates that the packet completed was + * transmitted using the push acceleration data provided by the driver. + * When this bit is '0', it indicates that the packet had not push + * acceleration data written or was executed as a normal packet even + * though push data was provided. + */ + #define TX_CMPL_FLAGS_PUSH UINT32_C(0x80) + #define TX_CMPL_FLAGS_MASK UINT32_C(0xffc0) + #define TX_CMPL_FLAGS_SFT 6 + uint16_t unused_0; + /* unused1 is 16 b */ + uint32_t opaque; + /* + * This is a copy of the opaque field from the first TX BD of this + * transmitted packet. + */ + uint16_t errors_v; + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define TX_CMPL_V UINT32_C(0x1) + /* + * This error indicates that there was some sort of problem with the BDs + * for the packet. + */ + #define TX_CMPL_ERRORS_BUFFER_ERROR_MASK UINT32_C(0xe) + #define TX_CMPL_ERRORS_BUFFER_ERROR_SFT 1 + /* No error */ + #define TX_CMPL_ERRORS_BUFFER_ERROR_NO_ERROR (UINT32_C(0x0) << 1) + /* Bad Format: BDs were not formatted correctly. */ + #define TX_CMPL_ERRORS_BUFFER_ERROR_BAD_FMT (UINT32_C(0x2) << 1) + #define TX_CMPL_ERRORS_BUFFER_ERROR_LAST TX_CMPL_ERRORS_BUFFER_ERROR_BAD_FMT + /* + * When this bit is '1', it indicates that the length of the packet was + * zero. No packet was transmitted. + */ + #define TX_CMPL_ERRORS_ZERO_LENGTH_PKT UINT32_C(0x10) + /* + * When this bit is '1', it indicates that the packet was longer than + * the programmed limit in TDI. No packet was transmitted. + */ + #define TX_CMPL_ERRORS_EXCESSIVE_BD_LENGTH UINT32_C(0x20) + /* + * When this bit is '1', it indicates that one or more of the BDs + * associated with this packet generated a PCI error. This probably + * means the address was not valid. + */ + #define TX_CMPL_ERRORS_DMA_ERROR UINT32_C(0x40) + /* + * When this bit is '1', it indicates that the packet was longer than + * indicated by the hint. No packet was transmitted. + */ + #define TX_CMPL_ERRORS_HINT_TOO_SHORT UINT32_C(0x80) + /* + * When this bit is '1', it indicates that the packet was dropped due to + * Poison TLP error on one or more of the TLPs in the PXP completion. + */ + #define TX_CMPL_ERRORS_POISON_TLP_ERROR UINT32_C(0x100) + #define TX_CMPL_ERRORS_MASK UINT32_C(0xfffe) + #define TX_CMPL_ERRORS_SFT 1 + uint16_t unused_1; + /* unused2 is 16 b */ + uint32_t unused_2; + /* unused3 is 32 b */ +} __attribute__((packed)); + +/* RX Packet Completion Record (32 bytes split to 2 16-byte struct) */ + +struct rx_pkt_cmpl { + uint16_t flags_type; + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define RX_PKT_CMPL_TYPE_MASK UINT32_C(0x3f) + #define RX_PKT_CMPL_TYPE_SFT 0 + /* RX L2 completion: Completion of and L2 RX packet. Length = 32B */ + #define RX_PKT_CMPL_TYPE_RX_L2 UINT32_C(0x11) + /* + * When this bit is '1', it indicates a packet that has an error of some + * type. Type of error is indicated in error_flags. + */ + #define RX_PKT_CMPL_FLAGS_ERROR UINT32_C(0x40) + /* This field indicates how the packet was placed in the buffer. */ + #define RX_PKT_CMPL_FLAGS_PLACEMENT_MASK UINT32_C(0x380) + #define RX_PKT_CMPL_FLAGS_PLACEMENT_SFT 7 + /* Normal: Packet was placed using normal algorithm. */ + #define RX_PKT_CMPL_FLAGS_PLACEMENT_NORMAL (UINT32_C(0x0) << 7) + /* Jumbo: Packet was placed using jumbo algorithm. */ + #define RX_PKT_CMPL_FLAGS_PLACEMENT_JUMBO (UINT32_C(0x1) << 7) + /* + * Header/Data Separation: Packet was placed using Header/Data + * separation algorithm. The separation location is indicated by + * the itype field. + */ + #define RX_PKT_CMPL_FLAGS_PLACEMENT_HDS (UINT32_C(0x2) << 7) + #define RX_PKT_CMPL_FLAGS_PLACEMENT_LAST RX_PKT_CMPL_FLAGS_PLACEMENT_HDS + /* This bit is '1' if the RSS field in this completion is valid. */ + #define RX_PKT_CMPL_FLAGS_RSS_VALID UINT32_C(0x400) + /* unused is 1 b */ + /* + * This value indicates what the inner packet determined for the packet + * was. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_MASK UINT32_C(0xf000) + #define RX_PKT_CMPL_FLAGS_ITYPE_SFT 12 + /* Not Known: Indicates that the packet type was not known. */ + #define RX_PKT_CMPL_FLAGS_ITYPE_NOT_KNOWN (UINT32_C(0x0) << 12) + /* + * IP Packet: Indicates that the packet was an IP packet, but + * further classification was not possible. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_IP (UINT32_C(0x1) << 12) + /* + * TCP Packet: Indicates that the packet was IP and TCP. This + * indicates that the payload_offset field is valid. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_TCP (UINT32_C(0x2) << 12) + /* + * UDP Packet: Indicates that the packet was IP and UDP. This + * indicates that the payload_offset field is valid. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_UDP (UINT32_C(0x3) << 12) + /* + * FCoE Packet: Indicates that the packet was recognized as a + * FCoE. This also indicates that the payload_offset field is + * valid. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_FCOE (UINT32_C(0x4) << 12) + /* + * RoCE Packet: Indicates that the packet was recognized as a + * RoCE. This also indicates that the payload_offset field is + * valid. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_ROCE (UINT32_C(0x5) << 12) + /* + * ICMP Packet: Indicates that the packet was recognized as + * ICMP. This indicates that the payload_offset field is valid. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_ICMP (UINT32_C(0x7) << 12) + /* + * PtP packet wo/timestamp: Indicates that the packet was + * recognized as a PtP packet. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP (UINT32_C(0x8) << 12) + /* + * PtP packet w/timestamp: Indicates that the packet was + * recognized as a PtP packet and that a timestamp was taken for + * the packet. + */ + #define RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP (UINT32_C(0x9) << 12) + #define RX_PKT_CMPL_FLAGS_ITYPE_LAST RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP + #define RX_PKT_CMPL_FLAGS_MASK UINT32_C(0xffc0) + #define RX_PKT_CMPL_FLAGS_SFT 6 + uint16_t len; + /* + * This is the length of the data for the packet stored in the buffer(s) + * identified by the opaque value. This includes the packet BD and any + * associated buffer BDs. This does not include the the length of any + * data places in aggregation BDs. + */ + uint32_t opaque; + /* + * This is a copy of the opaque field from the RX BD this completion + * corresponds to. + */ + uint8_t agg_bufs_v1; + /* unused1 is 2 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define RX_PKT_CMPL_V1 UINT32_C(0x1) + /* + * This value is the number of aggregation buffers that follow this + * entry in the completion ring that are a part of this packet. If the + * value is zero, then the packet is completely contained in the buffer + * space provided for the packet in the RX ring. + */ + #define RX_PKT_CMPL_AGG_BUFS_MASK UINT32_C(0x3e) + #define RX_PKT_CMPL_AGG_BUFS_SFT 1 + /* unused1 is 2 b */ + uint8_t rss_hash_type; + /* + * This is the RSS hash type for the packet. The value is packed + * {tuple_extrac_op[1:0],rss_profile_id[4:0],tuple_extrac_op[2]}. + */ + uint8_t payload_offset; + /* + * This value indicates the offset in bytes from the beginning of the + * packet where the inner payload starts. This value is valid for TCP, + * UDP, FCoE, and RoCE packets. A value of zero indicates that header is + * 256B into the packet. + */ + uint8_t unused_1; + /* unused2 is 8 b */ + uint32_t rss_hash; + /* + * This value is the RSS hash value calculated for the packet based on + * the mode bits and key value in the VNIC. + */ +} __attribute__((packed)); + +/* last 16 bytes of RX Packet Completion Record */ + +struct rx_pkt_cmpl_hi { + uint32_t flags2; + /* + * This indicates that the ip checksum was calculated for the inner + * packet and that the ip_cs_error field indicates if there was an + * error. + */ + #define RX_PKT_CMPL_FLAGS2_IP_CS_CALC UINT32_C(0x1) + /* + * This indicates that the TCP, UDP or ICMP checksum was calculated for + * the inner packet and that the l4_cs_error field indicates if there + * was an error. + */ + #define RX_PKT_CMPL_FLAGS2_L4_CS_CALC UINT32_C(0x2) + /* + * This indicates that the ip checksum was calculated for the tunnel + * header and that the t_ip_cs_error field indicates if there was an + * error. + */ + #define RX_PKT_CMPL_FLAGS2_T_IP_CS_CALC UINT32_C(0x4) + /* + * This indicates that the UDP checksum was calculated for the tunnel + * packet and that the t_l4_cs_error field indicates if there was an + * error. + */ + #define RX_PKT_CMPL_FLAGS2_T_L4_CS_CALC UINT32_C(0x8) + /* This value indicates what format the metadata field is. */ + #define RX_PKT_CMPL_FLAGS2_META_FORMAT_MASK UINT32_C(0xf0) + #define RX_PKT_CMPL_FLAGS2_META_FORMAT_SFT 4 + /* No metadata informtaion. Value is zero. */ + #define RX_PKT_CMPL_FLAGS2_META_FORMAT_NONE (UINT32_C(0x0) << 4) + /* + * The metadata field contains the VLAN tag and TPID value. - + * metadata[11:0] contains the vlan VID value. - metadata[12] + * contains the vlan DE value. - metadata[15:13] contains the + * vlan PRI value. - metadata[31:16] contains the vlan TPID + * value. + */ + #define RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN (UINT32_C(0x1) << 4) + #define RX_PKT_CMPL_FLAGS2_META_FORMAT_LAST RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN + /* + * This field indicates the IP type for the inner-most IP header. A + * value of '0' indicates IPv4. A value of '1' indicates IPv6. This + * value is only valid if itype indicates a packet with an IP header. + */ + #define RX_PKT_CMPL_FLAGS2_IP_TYPE UINT32_C(0x100) + uint32_t metadata; + /* + * This is data from the CFA block as indicated by the meta_format + * field. + */ + /* When meta_format=1, this value is the VLAN VID. */ + #define RX_PKT_CMPL_METADATA_VID_MASK UINT32_C(0xfff) + #define RX_PKT_CMPL_METADATA_VID_SFT 0 + /* When meta_format=1, this value is the VLAN DE. */ + #define RX_PKT_CMPL_METADATA_DE UINT32_C(0x1000) + /* When meta_format=1, this value is the VLAN PRI. */ + #define RX_PKT_CMPL_METADATA_PRI_MASK UINT32_C(0xe000) + #define RX_PKT_CMPL_METADATA_PRI_SFT 13 + /* When meta_format=1, this value is the VLAN TPID. */ + #define RX_PKT_CMPL_METADATA_TPID_MASK UINT32_C(0xffff0000) + #define RX_PKT_CMPL_METADATA_TPID_SFT 16 + uint16_t errors_v2; + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define RX_PKT_CMPL_V2 UINT32_C(0x1) + /* + * This error indicates that there was some sort of problem with the BDs + * for the packet that was found after part of the packet was already + * placed. The packet should be treated as invalid. + */ + #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_MASK UINT32_C(0xe) + #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_SFT 1 + /* No buffer error */ + #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_NO_BUFFER (UINT32_C(0x0) << 1) + /* + * Did Not Fit: Packet did not fit into packet buffer provided. + * For regular placement, this means the packet did not fit in + * the buffer provided. For HDS and jumbo placement, this means + * that the packet could not be placed into 7 physical buffers + * or less. + */ + #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_DID_NOT_FIT (UINT32_C(0x1) << 1) + /* + * Not On Chip: All BDs needed for the packet were not on-chip + * when the packet arrived. + */ + #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (UINT32_C(0x2) << 1) + /* Bad Format: BDs were not formatted correctly. */ + #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT (UINT32_C(0x3) << 1) + #define RX_PKT_CMPL_ERRORS_BUFFER_ERROR_LAST RX_PKT_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT + /* This indicates that there was an error in the IP header checksum. */ + #define RX_PKT_CMPL_ERRORS_IP_CS_ERROR UINT32_C(0x10) + /* + * This indicates that there was an error in the TCP, UDP or ICMP + * checksum. + */ + #define RX_PKT_CMPL_ERRORS_L4_CS_ERROR UINT32_C(0x20) + /* + * This indicates that there was an error in the tunnel IP header + * checksum. + */ + #define RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR UINT32_C(0x40) + /* This indicates that there was an error in the tunnel UDP checksum. */ + #define RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR UINT32_C(0x80) + /* + * This indicates that there was a CRC error on either an FCoE or RoCE + * packet. The itype indicates the packet type. + */ + #define RX_PKT_CMPL_ERRORS_CRC_ERROR UINT32_C(0x100) + /* + * This indicates that there was an error in the tunnel portion of the + * packet when this field is non-zero. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_MASK UINT32_C(0xe00) + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_SFT 9 + /* + * No additional error occurred on the tunnel portion of the + * packet of the packet does not have a tunnel. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_NO_ERROR (UINT32_C(0x0) << 9) + /* + * Indicates that IP header version does not match expectation + * from L2 Ethertype for IPv4 and IPv6 in the tunnel header. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION (UINT32_C(0x1) << 9) + /* + * Indicates that header length is out of range in the tunnel + * header. Valid for IPv4. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN (UINT32_C(0x2) << 9) + /* + * Indicates that the physical packet is shorter than that + * claimed by the PPPoE header length for a tunnel PPPoE packet. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_TUNNEL_TOTAL_ERROR (UINT32_C(0x3) << 9) + /* + * Indicates that physical packet is shorter than that claimed + * by the tunnel l3 header length. Valid for IPv4, or IPv6 + * tunnel packet packets. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR (UINT32_C(0x4) << 9) + /* + * Indicates that the physical packet is shorter than that + * claimed by the tunnel UDP header length for a tunnel UDP + * packet that is not fragmented. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR (UINT32_C(0x5) << 9) + /* + * indicates that the IPv4 TTL or IPv6 hop limit check have + * failed (e.g. TTL = 0) in the tunnel header. Valid for IPv4, + * and IPv6. + */ + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (UINT32_C(0x6) << 9) + #define RX_PKT_CMPL_ERRORS_T_PKT_ERROR_LAST RX_PKT_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL + /* + * This indicates that there was an error in the inner portion of the + * packet when this field is non-zero. + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_MASK UINT32_C(0xf000) + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_SFT 12 + /* + * No additional error occurred on the tunnel portion of the + * packet of the packet does not have a tunnel. + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_NO_ERROR (UINT32_C(0x0) << 12) + /* + * Indicates that IP header version does not match expectation + * from L2 Ethertype for IPv4 and IPv6 or that option other than + * VFT was parsed on FCoE packet. + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_VERSION (UINT32_C(0x1) << 12) + /* + * indicates that header length is out of range. Valid for IPv4 + * and RoCE + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN (UINT32_C(0x2) << 12) + /* + * indicates that the IPv4 TTL or IPv6 hop limit check have + * failed (e.g. TTL = 0). Valid for IPv4, and IPv6 + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L3_BAD_TTL (UINT32_C(0x3) << 12) + /* + * Indicates that physical packet is shorter than that claimed + * by the l3 header length. Valid for IPv4, IPv6 packet or RoCE + * packets. + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_IP_TOTAL_ERROR (UINT32_C(0x4) << 12) + /* + * Indicates that the physical packet is shorter than that + * claimed by the UDP header length for a UDP packet that is not + * fragmented. + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR (UINT32_C(0x5) << 12) + /* + * Indicates that TCP header length > IP payload. Valid for TCP + * packets only. + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN (UINT32_C(0x6) << 12) + /* Indicates that TCP header length < 5. Valid for TCP. */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (UINT32_C(0x7) << 12) + /* + * Indicates that TCP option headers result in a TCP header size + * that does not match data offset in TCP header. Valid for TCP. + */ + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (UINT32_C(0x8) << 12) + #define RX_PKT_CMPL_ERRORS_PKT_ERROR_LAST RX_PKT_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN + #define RX_PKT_CMPL_ERRORS_MASK UINT32_C(0xfffe) + #define RX_PKT_CMPL_ERRORS_SFT 1 + uint16_t cfa_code; + /* + * This field identifies the CFA action rule that was used for this + * packet. + */ + uint32_t reorder; + /* + * This value holds the reordering sequence number for the packet. If + * the reordering sequence is not valid, then this value is zero. The + * reordering domain for the packet is in the bottom 8 to 10b of the + * rss_hash value. The bottom 20b of this value contain the ordering + * domain value for the packet. + */ + #define RX_PKT_CMPL_REORDER_MASK UINT32_C(0xffffff) + #define RX_PKT_CMPL_REORDER_SFT 0 +} __attribute__((packed)); + +/* RX L2 TPA Start Completion Record (32 bytes split to 2 16-byte struct) */ + +struct rx_tpa_start_cmpl { + uint16_t flags_type; + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define RX_TPA_START_CMPL_TYPE_MASK UINT32_C(0x3f) + #define RX_TPA_START_CMPL_TYPE_SFT 0 + /* + * RX L2 TPA Start Completion: Completion at the beginning of a + * TPA operation. Length = 32B + */ + #define RX_TPA_START_CMPL_TYPE_RX_TPA_START UINT32_C(0x13) + /* This bit will always be '0' for TPA start completions. */ + #define RX_TPA_START_CMPL_FLAGS_ERROR UINT32_C(0x40) + /* This field indicates how the packet was placed in the buffer. */ + #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_MASK UINT32_C(0x380) + #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_SFT 7 + /* + * Jumbo: TPA Packet was placed using jumbo algorithm. This + * means that the first buffer will be filled with data before + * moving to aggregation buffers. Each aggregation buffer will + * be filled before moving to the next aggregation buffer. + */ + #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_JUMBO (UINT32_C(0x1) << 7) + /* + * Header/Data Separation: Packet was placed using Header/Data + * separation algorithm. The separation location is indicated by + * the itype field. + */ + #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_HDS (UINT32_C(0x2) << 7) + /* + * GRO/Jumbo: Packet will be placed using GRO/Jumbo where the + * first packet is filled with data. Subsequent packets will be + * placed such that any one packet does not span two aggregation + * buffers unless it starts at the beginning of an aggregation + * buffer. + */ + #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_GRO_JUMBO (UINT32_C(0x5) << 7) + /* + * GRO/Header-Data Separation: Packet will be placed using + * GRO/HDS where the header is in the first packet. Payload of + * each packet will be placed such that any one packet does not + * span two aggregation buffers unless it starts at the + * beginning of an aggregation buffer. + */ + #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_GRO_HDS (UINT32_C(0x6) << 7) + #define RX_TPA_START_CMPL_FLAGS_PLACEMENT_LAST RX_TPA_START_CMPL_FLAGS_PLACEMENT_GRO_HDS + /* This bit is '1' if the RSS field in this completion is valid. */ + #define RX_TPA_START_CMPL_FLAGS_RSS_VALID UINT32_C(0x400) + /* unused is 1 b */ + /* + * This value indicates what the inner packet determined for the packet + * was. + */ + #define RX_TPA_START_CMPL_FLAGS_ITYPE_MASK UINT32_C(0xf000) + #define RX_TPA_START_CMPL_FLAGS_ITYPE_SFT 12 + /* TCP Packet: Indicates that the packet was IP and TCP. */ + #define RX_TPA_START_CMPL_FLAGS_ITYPE_TCP (UINT32_C(0x2) << 12) + #define RX_TPA_START_CMPL_FLAGS_ITYPE_LAST RX_TPA_START_CMPL_FLAGS_ITYPE_TCP + #define RX_TPA_START_CMPL_FLAGS_MASK UINT32_C(0xffc0) + #define RX_TPA_START_CMPL_FLAGS_SFT 6 + uint16_t len; + /* + * This value indicates the amount of packet data written to the buffer + * the opaque field in this completion corresponds to. + */ + uint32_t opaque; + /* + * This is a copy of the opaque field from the RX BD this completion + * corresponds to. + */ + uint8_t v1; + /* unused1 is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define RX_TPA_START_CMPL_V1 UINT32_C(0x1) + /* unused1 is 7 b */ + uint8_t rss_hash_type; + /* + * This is the RSS hash type for the packet. The value is packed + * {tuple_extrac_op[1:0],rss_profile_id[4:0],tuple_extrac_op[2]}. + */ + uint16_t agg_id; + /* + * This is the aggregation ID that the completion is associated with. + * Use this number to correlate the TPA start completion with the TPA + * end completion. + */ + /* unused2 is 9 b */ + /* + * This is the aggregation ID that the completion is associated with. + * Use this number to correlate the TPA start completion with the TPA + * end completion. + */ + #define RX_TPA_START_CMPL_AGG_ID_MASK UINT32_C(0xfe00) + #define RX_TPA_START_CMPL_AGG_ID_SFT 9 + uint32_t rss_hash; + /* + * This value is the RSS hash value calculated for the packet based on + * the mode bits and key value in the VNIC. + */ +} __attribute__((packed)); + +/* last 16 bytes of RX L2 TPA Start Completion Record */ + +struct rx_tpa_start_cmpl_hi { + uint32_t flags2; + /* + * This indicates that the ip checksum was calculated for the inner + * packet and that the sum passed for all segments included in the + * aggregation. + */ + #define RX_TPA_START_CMPL_FLAGS2_IP_CS_CALC UINT32_C(0x1) + /* + * This indicates that the TCP, UDP or ICMP checksum was calculated for + * the inner packet and that the sum passed for all segments included in + * the aggregation. + */ + #define RX_TPA_START_CMPL_FLAGS2_L4_CS_CALC UINT32_C(0x2) + /* + * This indicates that the ip checksum was calculated for the tunnel + * header and that the sum passed for all segments included in the + * aggregation. + */ + #define RX_TPA_START_CMPL_FLAGS2_T_IP_CS_CALC UINT32_C(0x4) + /* + * This indicates that the UDP checksum was calculated for the tunnel + * packet and that the sum passed for all segments included in the + * aggregation. + */ + #define RX_TPA_START_CMPL_FLAGS2_T_L4_CS_CALC UINT32_C(0x8) + /* This value indicates what format the metadata field is. */ + #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_MASK UINT32_C(0xf0) + #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_SFT 4 + /* No metadata informtaion. Value is zero. */ + #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_NONE (UINT32_C(0x0) << 4) + /* + * The metadata field contains the VLAN tag and TPID value. - + * metadata[11:0] contains the vlan VID value. - metadata[12] + * contains the vlan DE value. - metadata[15:13] contains the + * vlan PRI value. - metadata[31:16] contains the vlan TPID + * value. + */ + #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_VLAN (UINT32_C(0x1) << 4) + #define RX_TPA_START_CMPL_FLAGS2_META_FORMAT_LAST RX_TPA_START_CMPL_FLAGS2_META_FORMAT_VLAN + /* + * This field indicates the IP type for the inner-most IP header. A + * value of '0' indicates IPv4. A value of '1' indicates IPv6. + */ + #define RX_TPA_START_CMPL_FLAGS2_IP_TYPE UINT32_C(0x100) + uint32_t metadata; + /* + * This is data from the CFA block as indicated by the meta_format + * field. + */ + /* When meta_format=1, this value is the VLAN VID. */ + #define RX_TPA_START_CMPL_METADATA_VID_MASK UINT32_C(0xfff) + #define RX_TPA_START_CMPL_METADATA_VID_SFT 0 + /* When meta_format=1, this value is the VLAN DE. */ + #define RX_TPA_START_CMPL_METADATA_DE UINT32_C(0x1000) + /* When meta_format=1, this value is the VLAN PRI. */ + #define RX_TPA_START_CMPL_METADATA_PRI_MASK UINT32_C(0xe000) + #define RX_TPA_START_CMPL_METADATA_PRI_SFT 13 + /* When meta_format=1, this value is the VLAN TPID. */ + #define RX_TPA_START_CMPL_METADATA_TPID_MASK UINT32_C(0xffff0000) + #define RX_TPA_START_CMPL_METADATA_TPID_SFT 16 + uint16_t v2; + /* unused4 is 15 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define RX_TPA_START_CMPL_V2 UINT32_C(0x1) + /* unused4 is 15 b */ + uint16_t cfa_code; + /* + * This field identifies the CFA action rule that was used for this + * packet. + */ + uint32_t inner_l4_size_inner_l3_offset_inner_l2_offset_outer_l3_offset; + /* + * This is the size in bytes of the inner most L4 header. This can be + * subtracted from the payload_offset to determine the start of the + * inner most L4 header. + */ + /* + * This is the offset from the beginning of the packet in bytes for the + * outer L3 header. If there is no outer L3 header, then this value is + * zero. + */ + #define RX_TPA_START_CMPL_OUTER_L3_OFFSET_MASK UINT32_C(0x1ff) + #define RX_TPA_START_CMPL_OUTER_L3_OFFSET_SFT 0 + /* + * This is the offset from the beginning of the packet in bytes for the + * inner most L2 header. + */ + #define RX_TPA_START_CMPL_INNER_L2_OFFSET_MASK UINT32_C(0x3fe00) + #define RX_TPA_START_CMPL_INNER_L2_OFFSET_SFT 9 + /* + * This is the offset from the beginning of the packet in bytes for the + * inner most L3 header. + */ + #define RX_TPA_START_CMPL_INNER_L3_OFFSET_MASK UINT32_C(0x7fc0000) + #define RX_TPA_START_CMPL_INNER_L3_OFFSET_SFT 18 + /* + * This is the size in bytes of the inner most L4 header. This can be + * subtracted from the payload_offset to determine the start of the + * inner most L4 header. + */ + #define RX_TPA_START_CMPL_INNER_L4_SIZE_MASK UINT32_C(0xf8000000) + #define RX_TPA_START_CMPL_INNER_L4_SIZE_SFT 27 +} __attribute__((packed)); + +/* RX TPA End Completion Record (32 bytes split to 2 16-byte struct) */ + +struct rx_tpa_end_cmpl { + uint16_t flags_type; + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define RX_TPA_END_CMPL_TYPE_MASK UINT32_C(0x3f) + #define RX_TPA_END_CMPL_TYPE_SFT 0 + /* + * RX L2 TPA End Completion: Completion at the end of a TPA + * operation. Length = 32B + */ + #define RX_TPA_END_CMPL_TYPE_RX_TPA_END UINT32_C(0x15) + /* + * When this bit is '1', it indicates a packet that has an error of some + * type. Type of error is indicated in error_flags. + */ + #define RX_TPA_END_CMPL_FLAGS_ERROR UINT32_C(0x40) + /* This field indicates how the packet was placed in the buffer. */ + #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_MASK UINT32_C(0x380) + #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_SFT 7 + /* + * Jumbo: TPA Packet was placed using jumbo algorithm. This + * means that the first buffer will be filled with data before + * moving to aggregation buffers. Each aggregation buffer will + * be filled before moving to the next aggregation buffer. + */ + #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_JUMBO (UINT32_C(0x1) << 7) + /* + * Header/Data Separation: Packet was placed using Header/Data + * separation algorithm. The separation location is indicated by + * the itype field. + */ + #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_HDS (UINT32_C(0x2) << 7) + /* + * GRO/Jumbo: Packet will be placed using GRO/Jumbo where the + * first packet is filled with data. Subsequent packets will be + * placed such that any one packet does not span two aggregation + * buffers unless it starts at the beginning of an aggregation + * buffer. + */ + #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_GRO_JUMBO (UINT32_C(0x5) << 7) + /* + * GRO/Header-Data Separation: Packet will be placed using + * GRO/HDS where the header is in the first packet. Payload of + * each packet will be placed such that any one packet does not + * span two aggregation buffers unless it starts at the + * beginning of an aggregation buffer. + */ + #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_GRO_HDS (UINT32_C(0x6) << 7) + #define RX_TPA_END_CMPL_FLAGS_PLACEMENT_LAST RX_TPA_END_CMPL_FLAGS_PLACEMENT_GRO_HDS + /* unused is 2 b */ + /* + * This value indicates what the inner packet determined for the packet + * was. - 2 TCP Packet Indicates that the packet was IP and TCP. This + * indicates that the ip_cs field is valid and that the tcp_udp_cs field + * is valid and contains the TCP checksum. This also indicates that the + * payload_offset field is valid. + */ + #define RX_TPA_END_CMPL_FLAGS_ITYPE_MASK UINT32_C(0xf000) + #define RX_TPA_END_CMPL_FLAGS_ITYPE_SFT 12 + #define RX_TPA_END_CMPL_FLAGS_MASK UINT32_C(0xffc0) + #define RX_TPA_END_CMPL_FLAGS_SFT 6 + uint16_t len; + /* + * This value is zero for TPA End completions. There is no data in the + * buffer that corresponds to the opaque value in this completion. + */ + uint32_t opaque; + /* + * This is a copy of the opaque field from the RX BD this completion + * corresponds to. + */ + uint8_t agg_bufs_v1; + /* unused1 is 1 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define RX_TPA_END_CMPL_V1 UINT32_C(0x1) + /* + * This value is the number of aggregation buffers that follow this + * entry in the completion ring that are a part of this aggregation + * packet. If the value is zero, then the packet is completely contained + * in the buffer space provided in the aggregation start completion. + */ + #define RX_TPA_END_CMPL_AGG_BUFS_MASK UINT32_C(0x7e) + #define RX_TPA_END_CMPL_AGG_BUFS_SFT 1 + /* unused1 is 1 b */ + uint8_t tpa_segs; + /* This value is the number of segments in the TPA operation. */ + uint8_t payload_offset; + /* + * This value indicates the offset in bytes from the beginning of the + * packet where the inner payload starts. This value is valid for TCP, + * UDP, FCoE, and RoCE packets. A value of zero indicates an offset of + * 256 bytes. + */ + uint8_t agg_id; + /* + * This is the aggregation ID that the completion is associated with. + * Use this number to correlate the TPA start completion with the TPA + * end completion. + */ + /* unused2 is 1 b */ + /* + * This is the aggregation ID that the completion is associated with. + * Use this number to correlate the TPA start completion with the TPA + * end completion. + */ + #define RX_TPA_END_CMPL_AGG_ID_MASK UINT32_C(0xfe) + #define RX_TPA_END_CMPL_AGG_ID_SFT 1 + uint32_t tsdelta; + /* + * For non-GRO packets, this value is the timestamp delta between + * earliest and latest timestamp values for TPA packet. If packets were + * not time stamped, then delta will be zero. For GRO packets, this + * field is zero except for the following sub-fields. - tsdelta[31] + * Timestamp present indication. When '0', no Timestamp option is in the + * packet. When '1', then a Timestamp option is present in the packet. + */ +} __attribute__((packed)); + +/* last 16 bytes of RX TPA End Completion Record */ + +struct rx_tpa_end_cmpl_hi { + uint32_t tpa_dup_acks; + /* unused3 is 28 b */ + /* + * This value is the number of duplicate ACKs that have been received as + * part of the TPA operation. + */ + #define RX_TPA_END_CMPL_TPA_DUP_ACKS_MASK UINT32_C(0xf) + #define RX_TPA_END_CMPL_TPA_DUP_ACKS_SFT 0 + /* unused3 is 28 b */ + uint16_t tpa_seg_len; + /* + * This value is the valid when TPA completion is active. It indicates + * the length of the longest segment of the TPA operation for LRO mode + * and the length of the first segment in GRO mode. This value may be + * used by GRO software to re-construct the original packet stream from + * the TPA packet. This is the length of all but the last segment for + * GRO. In LRO mode this value may be used to indicate MSS size to the + * stack. + */ + uint16_t unused_3; + /* unused4 is 16 b */ + uint16_t errors_v2; + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define RX_TPA_END_CMPL_V2 UINT32_C(0x1) + /* + * This error indicates that there was some sort of problem with the BDs + * for the packet that was found after part of the packet was already + * placed. The packet should be treated as invalid. + */ + #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_MASK UINT32_C(0xe) + #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_SFT 1 + /* + * This error occurs when there is a fatal HW problem in the + * chip only. It indicates that there were not BDs on chip but + * that there was adequate reservation. provided by the TPA + * block. + */ + #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (UINT32_C(0x2) << 1) + /* + * This error occurs when TPA block was not configured to + * reserve adequate BDs for TPA operations on this RX ring. All + * data for the TPA operation was not placed. This error can + * also be generated when the number of segments is not + * programmed correctly in TPA and the 33 total aggregation + * buffers allowed for the TPA operation has been exceeded. + */ + #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_RSV_ERROR (UINT32_C(0x4) << 1) + #define RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_LAST RX_TPA_END_CMPL_ERRORS_BUFFER_ERROR_RSV_ERROR + #define RX_TPA_END_CMPL_ERRORS_MASK UINT32_C(0xfffe) + #define RX_TPA_END_CMPL_ERRORS_SFT 1 + uint16_t unused_4; + /* unused5 is 16 b */ + uint32_t start_opaque; + /* + * This is the opaque value that was completed for the TPA start + * completion that corresponds to this TPA end completion. + */ +} __attribute__((packed)); + +/* RX Aggregation Buffer Completion Record (16 bytes) */ + +struct rx_abuf_cmpl { + uint16_t type; + /* unused is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define RX_ABUF_CMPL_TYPE_MASK UINT32_C(0x3f) + #define RX_ABUF_CMPL_TYPE_SFT 0 + /* + * RX Aggregation Buffer completion : Completion of an L2 + * aggregation buffer in support of TPA, HDS, or Jumbo packet + * completion. Length = 16B + */ + #define RX_ABUF_CMPL_TYPE_RX_AGG UINT32_C(0x12) + /* unused is 10 b */ + uint16_t len; + /* + * This is the length of the data for the packet stored in this + * aggregation buffer identified by the opaque value. This does not + * include the length of any data placed in other aggregation BDs or in + * the packet or buffer BDs. This length does not include any space + * added due to hdr_offset register during HDS placement mode. + */ + uint32_t opaque; + /* + * This is a copy of the opaque field from the RX BD this aggregation + * buffer corresponds to. + */ + uint32_t v; + /* unused2 is 31 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define RX_ABUF_CMPL_V UINT32_C(0x1) + /* unused2 is 31 b */ + uint32_t unused_2; + /* unused3 is 32 b */ +} __attribute__((packed)); + +/* Statistics Ejection Buffer Completion Record (16 bytes) */ + +struct eject_cmpl { + uint16_t type; + /* unused is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define EJECT_CMPL_TYPE_MASK UINT32_C(0x3f) + #define EJECT_CMPL_TYPE_SFT 0 + /* + * Statistics Ejection Completion: Completion of statistics data + * ejection buffer. Length = 16B + */ + #define EJECT_CMPL_TYPE_STAT_EJECT UINT32_C(0x1a) + /* unused is 10 b */ + uint16_t len; + /* This is the length of the statistics data stored in this buffer. */ + uint32_t opaque; + /* + * This is a copy of the opaque field from the RX BD this ejection + * buffer corresponds to. + */ + uint32_t v; + /* unused2 is 31 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define EJECT_CMPL_V UINT32_C(0x1) + /* unused2 is 31 b */ + uint32_t unused_2; + /* unused3 is 32 b */ +} __attribute__((packed)); + +/* HWRM Completion Record (16 bytes) */ + +struct hwrm_cmpl { + uint16_t type; + /* unused is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_CMPL_TYPE_MASK UINT32_C(0x3f) + #define HWRM_CMPL_TYPE_SFT 0 + /* HWRM Command Completion: Completion of an HWRM command. */ + #define HWRM_CMPL_TYPE_HWRM_DONE UINT32_C(0x20) + /* unused is 10 b */ + uint16_t sequence_id; + /* This is the sequence_id of the HWRM command that has completed. */ + uint32_t unused_1; + /* unused2 is 32 b */ + uint32_t v; + /* unused3 is 31 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_CMPL_V UINT32_C(0x1) + /* unused3 is 31 b */ + uint32_t unused_3; + /* unused4 is 32 b */ +} __attribute__((packed)); + +/* HWRM Forwarded Request (16 bytes) */ + +struct hwrm_fwd_req_cmpl { + uint16_t req_len_type; + /* Length of forwarded request in bytes. */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_FWD_REQ_CMPL_TYPE_MASK UINT32_C(0x3f) + #define HWRM_FWD_REQ_CMPL_TYPE_SFT 0 + /* Forwarded HWRM Request */ + #define HWRM_FWD_REQ_CMPL_TYPE_HWRM_FWD_REQ UINT32_C(0x22) + /* Length of forwarded request in bytes. */ + #define HWRM_FWD_REQ_CMPL_REQ_LEN_MASK UINT32_C(0xffc0) + #define HWRM_FWD_REQ_CMPL_REQ_LEN_SFT 6 + uint16_t source_id; + /* + * Source ID of this request. Typically used in forwarding requests and + * responses. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE - + * Reserved for internal processors 0xFFFF - HWRM + */ + uint32_t unused_0; + /* unused1 is 32 b */ + uint64_t req_buf_addr_v; + /* Address of forwarded request. */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_FWD_REQ_CMPL_V UINT32_C(0x1) + /* Address of forwarded request. */ + #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_MASK UINT32_C(0xfffffffe) + #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_SFT 1 +} __attribute__((packed)); + +/* HWRM Forwarded Response (16 bytes) */ + +struct hwrm_fwd_resp_cmpl { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_FWD_RESP_CMPL_TYPE_MASK UINT32_C(0x3f) + #define HWRM_FWD_RESP_CMPL_TYPE_SFT 0 + /* Forwarded HWRM Response */ + #define HWRM_FWD_RESP_CMPL_TYPE_HWRM_FWD_RESP UINT32_C(0x24) + /* unused1 is 10 b */ + uint16_t source_id; + /* + * Source ID of this response. Typically used in forwarding requests and + * responses. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE - + * Reserved for internal processors 0xFFFF - HWRM + */ + uint16_t resp_len; + /* Length of forwarded response in bytes. */ + uint16_t unused_1; + /* unused2 is 16 b */ + uint64_t resp_buf_addr_v; + /* Address of forwarded response. */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_FWD_RESP_CMPL_V UINT32_C(0x1) + /* Address of forwarded response. */ + #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_MASK UINT32_C(0xfffffffe) + #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_SFT 1 +} __attribute__((packed)); + +#define GET_EVENT_ID(x) \ + ((x) == 0x30 ? "VF_FLR": \ + ((x) == 0x20 ? "PF_DRVR_UNLOAD": \ + ((x) == 0x10 ? "FUNC_DRVR_UNLOAD": \ + ((x) == 0xff ? "HWRM_ERROR": \ + ((x) == 0x32 ? "PF_VF_COMM_STATUS_CHANGE": \ + ((x) == 0x33 ? "VF_CFG_CHANGE": \ + ((x) == 0x11 ? "FUNC_DRVR_LOAD": \ + ((x) == 0x31 ? "VF_MAC_ADDR_CHANGE": \ + ((x) == 0x4 ? "PORT_CONN_NOT_ALLOWED": \ + ((x) == 0x5 ? "LINK_SPEED_CFG_NOT_ALLOWED": \ + ((x) == 0x6 ? "LINK_SPEED_CFG_CHANGE": \ + ((x) == 0x7 ? "PORT_PHY_CFG_CHANGE": \ + ((x) == 0x0 ? "LINK_STATUS_CHANGE": \ + ((x) == 0x1 ? "LINK_MTU_CHANGE": \ + ((x) == 0x2 ? "LINK_SPEED_CHANGE": \ + ((x) == 0x3 ? "DCB_CONFIG_CHANGE": \ + ((x) == 0x12 ? "FUNC_FLR_PROC_CMPLT": \ + ((x) == 0x21 ? "PF_DRVR_LOAD": \ + "Unknown event_id")))))))))))))))))) + +/* HWRM Asynchronous Event Completion Record (16 bytes) */ + +struct hwrm_async_event_cmpl { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Link status changed */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE UINT32_C(0x0) + /* Link MTU changed */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE UINT32_C(0x1) + /* Link speed changed */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE UINT32_C(0x2) + /* DCB Configuration changed */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE UINT32_C(0x3) + /* Port connection not allowed */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED UINT32_C(0x4) + /* Link speed configuration was not allowed */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED UINT32_C(0x5) + /* Link speed configuration change */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE UINT32_C(0x6) + /* Port PHY configuration change */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE UINT32_C(0x7) + /* Function driver unloaded */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD UINT32_C(0x10) + /* Function driver loaded */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD UINT32_C(0x11) + /* Function FLR related processing has completed */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT UINT32_C(0x12) + /* PF driver unloaded */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD UINT32_C(0x20) + /* PF driver loaded */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD UINT32_C(0x21) + /* VF Function Level Reset (FLR) */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR UINT32_C(0x30) + /* VF MAC Address Change */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE UINT32_C(0x31) + /* PF-VF communication channel status change. */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE UINT32_C(0x32) + /* VF Configuration Change */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE UINT32_C(0x33) + /* HWRM Error */ + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR UINT32_C(0xff) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for link status change (16 bytes) */ + +struct hwrm_async_event_cmpl_link_status_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Link status changed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE UINT32_C(0x0) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* Indicates link status change */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE UINT32_C(0x1) + /* + * If this bit set to 0, then it indicates that the link was up + * and it went down. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_DOWN (UINT32_C(0x0) << 0) + /* + * If this bit is set to 1, then it indicates that the link was + * down and it went up. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP (UINT32_C(0x1) << 0) + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_LAST HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP + /* Indicates the physical port this link status change occur */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_MASK UINT32_C(0xe) + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_SFT 1 + /* PORT ID */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff0) + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_SFT 4 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for link MTU change (16 bytes) */ + +struct hwrm_async_event_cmpl_link_mtu_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Link MTU changed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE UINT32_C(0x1) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* The new MTU of the link in bytes. */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for link speed change (16 bytes) */ + +struct hwrm_async_event_cmpl_link_speed_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Link speed changed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE UINT32_C(0x2) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* + * When this bit is '1', the link was forced to the force_link_speed + * value. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_FORCE UINT32_C(0x1) + /* The new link speed in 100 Mbps units. */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_MASK UINT32_C(0xfffe) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_SFT 1 + /* 100Mb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100MB (UINT32_C(0x1) << 1) + /* 1Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_1GB (UINT32_C(0xa) << 1) + /* 2Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2GB (UINT32_C(0x14) << 1) + /* 2.5Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2_5GB (UINT32_C(0x19) << 1) + /* 10Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10GB (UINT32_C(0x64) << 1) + /* 20Mb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_20GB (UINT32_C(0xc8) << 1) + /* 25Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (UINT32_C(0xfa) << 1) + /* 40Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (UINT32_C(0x190) << 1) + /* 50Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (UINT32_C(0x1f4) << 1) + /* 100Gb link speed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB (UINT32_C(0x3e8) << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_LAST HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB + /* PORT ID */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff0000) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_SFT 16 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for DCB Config change (16 bytes) */ + +struct hwrm_async_event_cmpl_dcb_config_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* DCB Configuration changed */ + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE UINT32_C(0x3) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* PORT ID */ + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for port connection not allowed (16 bytes) */ + +struct hwrm_async_event_cmpl_port_conn_not_allowed { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Port connection not allowed */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED UINT32_C(0x4) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* PORT ID */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0 + /* + * This value indicates the current port level enforcement policy for + * the optics module when there is an optical module mismatch and port + * is not connected. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK UINT32_C(0xff0000) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT 16 + /* No enforcement */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_NONE (UINT32_C(0x0) << 16) + /* Disable Transmit side Laser. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_DISABLETX (UINT32_C(0x1) << 16) + /* Raise a warning message. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_WARNINGMSG (UINT32_C(0x2) << 16) + /* Power down the module. */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN (UINT32_C(0x3) << 16) + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_LAST HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for link speed config not allowed (16 bytes) */ + +struct hwrm_async_event_cmpl_link_speed_cfg_not_allowed { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Link speed configuration was not allowed */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED UINT32_C(0x5) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* PORT ID */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for link speed configuration change (16 bytes) */ + +struct hwrm_async_event_cmpl_link_speed_cfg_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Link speed configuration change */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_ID_LINK_SPEED_CFG_CHANGE UINT32_C(0x6) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* PORT ID */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0 + /* + * If set to 1, it indicates that the supported link speeds + * configuration on the port has changed. If set to 0, then there is no + * change in supported link speeds configuration. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_SUPPORTED_LINK_SPEEDS_CHANGE UINT32_C(0x10000) + /* + * If set to 1, it indicates that the link speed configuration on the + * port has become illegal or invalid. If set to 0, then the link speed + * configuration on the port is legal or valid. + */ + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_ILLEGAL_LINK_SPEED_CFG UINT32_C(0x20000) +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for port PHY configuration change (16 bytes) */ + +struct hwrm_async_event_cmpl_port_phy_cfg_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Port PHY configuration change */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_ID_PORT_PHY_CFG_CHANGE UINT32_C(0x7) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* PORT ID */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0 + /* + * If set to 1, it indicates that the FEC configuration on the port has + * changed. If set to 0, then there is no change in FEC configuration. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_FEC_CFG_CHANGE UINT32_C(0x10000) + /* + * If set to 1, it indicates that the EEE configuration on the port has + * changed. If set to 0, then there is no change in EEE configuration on + * the port. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_EEE_CFG_CHANGE UINT32_C(0x20000) + /* + * If set to 1, it indicates that the pause configuration on the PHY has + * changed. If set to 0, then there is no change in the pause + * configuration on the PHY. + */ + #define HWRM_ASYNC_EVENT_CMPL_PORT_PHY_CFG_CHANGE_EVENT_DATA1_PAUSE_CFG_CHANGE UINT32_C(0x40000) +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for Function Driver Unload (16 bytes) */ + +struct hwrm_async_event_cmpl_func_drvr_unload { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Function driver unloaded */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD UINT32_C(0x10) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* Function ID */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for Function Driver load (16 bytes) */ + +struct hwrm_async_event_cmpl_func_drvr_load { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Function driver loaded */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD UINT32_C(0x11) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* Function ID */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record to indicate completion of FLR related processing (16 bytes) */ + +struct hwrm_async_event_cmpl_func_flr_proc_cmplt { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* Function FLR related processing has completed */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_ID_FUNC_FLR_PROC_CMPLT UINT32_C(0x12) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* Function ID */ + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_DATA1_FUNC_ID_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for PF Driver Unload (16 bytes) */ + +struct hwrm_async_event_cmpl_pf_drvr_unload { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* PF driver unloaded */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD UINT32_C(0x20) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* PF ID */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0 + /* Indicates the physical port this pf belongs to */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_MASK UINT32_C(0x70000) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_SFT 16 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for PF Driver load (16 bytes) */ + +struct hwrm_async_event_cmpl_pf_drvr_load { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* PF driver loaded */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD UINT32_C(0x21) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* PF ID */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0 + /* Indicates the physical port this pf belongs to */ + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_MASK UINT32_C(0x70000) + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_SFT 16 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for VF FLR (16 bytes) */ + +struct hwrm_async_event_cmpl_vf_flr { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* VF Function Level Reset (FLR) */ + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR UINT32_C(0x30) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* VF ID */ + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for VF MAC Addr change (16 bytes) */ + +struct hwrm_async_event_cmpl_vf_mac_addr_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* VF MAC Address Change */ + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE UINT32_C(0x31) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* VF ID */ + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_MASK UINT32_C(0xffff) + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0 +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for PF-VF communication status change (16 bytes) */ + +struct hwrm_async_event_cmpl_pf_vf_comm_status_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* PF-VF communication channel status change. */ + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_ID_PF_VF_COMM_STATUS_CHANGE UINT32_C(0x32) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* + * If this bit is set to 1, then it indicates that the PF-VF + * communication was lost and it is established. If this bit set to 0, + * then it indicates that the PF-VF communication was established and it + * is lost. + */ + #define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_DATA1_COMM_ESTABLISHED UINT32_C(0x1) +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for VF configuration change (16 bytes) */ + +struct hwrm_async_event_cmpl_vf_cfg_change { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* VF Configuration Change */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_ID_VF_CFG_CHANGE UINT32_C(0x33) + uint32_t event_data2; + /* Event specific data */ + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* + * Each flag provided in this field indicates a specific VF + * configuration change. At least one of these flags shall be set to 1 + * when an asynchronous event completion of this type is provided by the + * HWRM. + */ + /* + * If this bit is set to 1, then the value of MTU was changed on this + * VF. If set to 0, then this bit should be ignored. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MTU_CHANGE UINT32_C(0x1) + /* + * If this bit is set to 1, then the value of MRU was changed on this + * VF. If set to 0, then this bit should be ignored. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MRU_CHANGE UINT32_C(0x2) + /* + * If this bit is set to 1, then the value of default MAC address was + * changed on this VF. If set to 0, then this bit should be ignored. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_MAC_ADDR_CHANGE UINT32_C(0x4) + /* + * If this bit is set to 1, then the value of default VLAN was changed + * on this VF. If set to 0, then this bit should be ignored. + */ + #define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_VLAN_CHANGE UINT32_C(0x8) +} __attribute__((packed)); + +/* HWRM Asynchronous Event Completion Record for HWRM Error (16 bytes) */ + +struct hwrm_async_event_cmpl_hwrm_error { + uint16_t type; + /* unused1 is 10 b */ + /* + * This field indicates the exact type of the completion. By convention, + * the LSB identifies the length of the record in 16B units. Even values + * indicate 16B records. Odd values indicate 32B records. + */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_MASK UINT32_C(0x3f) + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_SFT 0 + /* HWRM Asynchronous Event Information */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_HWRM_ASYNC_EVENT UINT32_C(0x2e) + /* unused1 is 10 b */ + uint16_t event_id; + /* Identifiers of events. */ + /* HWRM Error */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR UINT32_C(0xff) + uint32_t event_data2; + /* Event specific data */ + /* Severity of HWRM Error */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_MASK UINT32_C(0xff) + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_SFT 0 + /* Warning */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING UINT32_C(0x0) + /* Non-fatal Error */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL UINT32_C(0x1) + /* Fatal Error */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL UINT32_C(0x2) + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_LAST HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL + uint8_t opaque_v; + /* opaque is 7 b */ + /* + * This value is written by the NIC such that it will be different for + * each pass through the completion queue. The even passes will write 1. + * The odd passes will write 0. + */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_V UINT32_C(0x1) + /* opaque is 7 b */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK UINT32_C(0xfe) + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_SFT 1 + uint8_t timestamp_lo; + /* 8-lsb timestamp from POR (100-msec resolution) */ + uint16_t timestamp_hi; + /* 16-lsb timestamp from POR (100-msec resolution) */ + uint32_t event_data1; + /* Event specific data */ + /* Time stamp for error event */ + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP UINT32_C(0x1) +} __attribute__((packed)); + +/* Door Bell Formats */ +/* + * Description: The backup version of the packet must be valid in the TX ring + * before the push doorbell is written to the chip. The first 32b and the BD + * portion of the push doorbell must be written in multiples of 32b units on the + * PCI interface. The data portion of the push doorbell may be written in + * multiples of 8b units on the PCI interface. A push update must contain + * exactly one push packet. The backup version of the packet must start with a + * long (32B) BD and the BDs must be less than or equal to 16x16B units long. + */ +/* + * Note: This door bell format is used by the driver when it wants to push a + * packet into the chip for super-fast transmission. This pushes a partial BD + * and the packet data into the chip. If the chip has room, it will transmit the + * packet. If the chip dosn't have room, it will read the BD and packet data + * from host memory as a normal packet. + */ +/* TX Door Bell Format (4 bytes) */ + +struct tx_doorbell { + uint32_t key_idx; + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '0' for TX door bell operations. + */ + /* + * BD Index of next BD that will be used to transmit data on the TX ring + * mapped to this door bell. NIC may read and process all BDs up to, but + * not including this index. + */ + #define TX_DOORBELL_IDX_MASK UINT32_C(0xffffff) + #define TX_DOORBELL_IDX_SFT 0 + /* reserved is 4 b */ + #define TX_DOORBELL_RESERVED_MASK UINT32_C(0xf000000) + #define TX_DOORBELL_RESERVED_SFT 24 + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '0' for TX door bell operations. + */ + #define TX_DOORBELL_KEY_MASK UINT32_C(0xf0000000) + #define TX_DOORBELL_KEY_SFT 28 + /* TX Operation */ + #define TX_DOORBELL_KEY_TX (UINT32_C(0x0) << 28) +} __attribute__((packed)); + +/* RX Door Bell Format (4 bytes) */ + +struct rx_doorbell { + uint32_t key_idx; + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '1' for RX door bell operations. + */ + /* + * BD Index of next BD that will be used for an empty receive buffer on + * the RX ring mapped to this door bell. NIC may read and process all + * BDs up to, but not including this index. + */ + #define RX_DOORBELL_IDX_MASK UINT32_C(0xffffff) + #define RX_DOORBELL_IDX_SFT 0 + /* reserved is 4 b */ + #define RX_DOORBELL_RESERVED_MASK UINT32_C(0xf000000) + #define RX_DOORBELL_RESERVED_SFT 24 + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '1' for RX door bell operations. + */ + #define RX_DOORBELL_KEY_MASK UINT32_C(0xf0000000) + #define RX_DOORBELL_KEY_SFT 28 + /* RX Operation */ + #define RX_DOORBELL_KEY_RX (UINT32_C(0x1) << 28) +} __attribute__((packed)); + +/* CMP Door Bell Format (4 bytes) */ + +struct cmpl_doorbell { + uint32_t key_mask_valid_idx; + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '2' for CMP door bell operations. + */ + /* + * BD Index of the most recently handed completion record on the + * completion ring mapped to this door bell. NIC may write this location + * again with a new completion. + */ + #define CMPL_DOORBELL_IDX_MASK UINT32_C(0xffffff) + #define CMPL_DOORBELL_IDX_SFT 0 + /* reserved is 2 b */ + #define CMPL_DOORBELL_RESERVED_MASK UINT32_C(0x3000000) + #define CMPL_DOORBELL_RESERVED_SFT 24 + /* + * This indicates if the BDIDX value is valid for this update when it is + * '1'. When it is '0', the BDIDX value should be ignored. + */ + #define CMPL_DOORBELL_IDX_VALID UINT32_C(0x4000000) + /* + * This bit indicates the new interrupt mask state for the interrupt + * associated with the BDIDX. A '1', means the interrupt is to be + * masked. A '0' indicates the interrupt is to be unmasked. + */ + #define CMPL_DOORBELL_MASK UINT32_C(0x8000000) + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '2' for CMP door bell operations. + */ + #define CMPL_DOORBELL_KEY_MASK UINT32_C(0xf0000000) + #define CMPL_DOORBELL_KEY_SFT 28 + /* Completion Operation */ + #define CMPL_DOORBELL_KEY_CMPL (UINT32_C(0x2) << 28) +} __attribute__((packed)); + +/* Status Door Bell Format (4 bytes) */ + +struct status_doorbell { + uint32_t key_idx; + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '3' for Status door bell operations. + */ + /* + * BD Index of the status record for which space is now available to the + * NIC. + */ + /* + * While there is no actual BD associated with the index, the similar + * scheme is being used to communicate to the NIC that space is + * available for status completions. + */ + #define STATUS_DOORBELL_IDX_MASK UINT32_C(0xffffff) + #define STATUS_DOORBELL_IDX_SFT 0 + /* reserved is 4 b */ + #define STATUS_DOORBELL_RESERVED_MASK UINT32_C(0xf000000) + #define STATUS_DOORBELL_RESERVED_SFT 24 + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is '3' for Status door bell operations. + */ + #define STATUS_DOORBELL_KEY_MASK UINT32_C(0xf0000000) + #define STATUS_DOORBELL_KEY_SFT 28 + /* Status Operation */ + #define STATUS_DOORBELL_KEY_STAT (UINT32_C(0x3) << 28) +} __attribute__((packed)); + +/* Push w/32B BD Door Bell Format (32 bytes) */ + +struct push32_doorbell { + uint32_t key_sz_idx; + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is 4 for push door bell operations. + */ + /* + * This is the BD Index of last BD of the push packet that will be used + * to transmit data on the TX ring mapped to this door bell. + */ + #define PUSH32_DOORBELL_IDX_MASK UINT32_C(0xffffff) + #define PUSH32_DOORBELL_IDX_SFT 0 + /* + * This is the number of 16B BDs spaces consumed in the TX Ring by the + * "backup" version of the packet being pushed. A value of 1 is invalid + * since backup must start with a long 32B BE. A value of 2 indicates + * just the first 32B BE. A value of 3 indicates 32B+16B BD. etc. A + * value of 0 indicates 16x16B BD spaces are consumed. + */ + #define PUSH32_DOORBELL_SZ_MASK UINT32_C(0xf000000) + #define PUSH32_DOORBELL_SZ_SFT 24 + /* + * This value indicates the type of door bell operation that is begin + * requested. This value is 4 for push door bell operations. + */ + #define PUSH32_DOORBELL_KEY_MASK UINT32_C(0xf0000000) + #define PUSH32_DOORBELL_KEY_SFT 28 + /* Push Operation */ + #define PUSH32_DOORBELL_KEY_PUSH (UINT32_C(0x4) << 28) + uint16_t flags_type; + /* + * All bits in this field must be valid on the first BD of a packet. + * Only the packet_end bit must be valid for the remaining BDs of a + * packet. + */ + /* This value identifies the type of buffer descriptor. */ + #define PUSH32_DOORBELL_TYPE_MASK UINT32_C(0x3f) + #define PUSH32_DOORBELL_TYPE_SFT 0 + /* + * Indicates that this BD is 32B long and is used for normal L2 + * packet transmission. + */ + #define PUSH32_DOORBELL_TYPE_TX_BD_LONG UINT32_C(0x10) + /* + * If set to 1, the packet ends with the data in the buffer pointed to + * by this descriptor. This flag must be valid on every BD. This bit + * must be set on all push doorbells. + */ + #define PUSH32_DOORBELL_FLAGS_PACKET_END UINT32_C(0x40) + /* + * If set to 1, the device will not generate a completion for this + * transmit packet unless there is an error in it's processing. If this + * bit is set to 0, then the packet will be completed normally. This bit + * must be valid only on the first BD of a packet. + */ + #define PUSH32_DOORBELL_FLAGS_NO_CMPL UINT32_C(0x80) + /* + * This value must match the sz field in the first 32b of the push + * operation except that if 16x16B BD locations are consumed in the ring + * by this packet, then this value must be 16 (not zero). + */ + #define PUSH32_DOORBELL_FLAGS_BD_CNT_MASK UINT32_C(0x1f00) + #define PUSH32_DOORBELL_FLAGS_BD_CNT_SFT 8 + /* + * This value is a hint for the length of the entire packet. It is used + * by the chip to optimize internal processing. The packet will be + * dropped if the hint is too short. This field is valid only on the + * first BD of a packet. + */ + #define PUSH32_DOORBELL_FLAGS_LHINT_MASK UINT32_C(0x6000) + #define PUSH32_DOORBELL_FLAGS_LHINT_SFT 13 + /* indicates packet length < 512B */ + #define PUSH32_DOORBELL_FLAGS_LHINT_LT512 (UINT32_C(0x0) << 13) + /* indicates 512 <= packet length < 1KB */ + #define PUSH32_DOORBELL_FLAGS_LHINT_LT1K (UINT32_C(0x1) << 13) + /* indicates 1KB <= packet length < 2KB */ + #define PUSH32_DOORBELL_FLAGS_LHINT_LT2K (UINT32_C(0x2) << 13) + /* indicates packet length >= 2KB */ + #define PUSH32_DOORBELL_FLAGS_LHINT_GTE2K (UINT32_C(0x3) << 13) + #define PUSH32_DOORBELL_FLAGS_LHINT_LAST PUSH32_DOORBELL_FLAGS_LHINT_GTE2K + /* + * If set to 1, the device immediately updates the Send Consumer Index + * after the buffer associated with this descriptor has been transferred + * via DMA to NIC memory from host memory. An interrupt may or may not + * be generated according to the state of the interrupt avoidance + * mechanisms. If this bit is set to 0, then the Consumer Index is only + * updated as soon as one of the host interrupt coalescing conditions + * has been met. This bit must be valid on the first BD of a packet. + */ + #define PUSH32_DOORBELL_FLAGS_COAL_NOW UINT32_C(0x8000) + /* + * All bits in this field must be valid on the first BD of a packet. + * Only the packet_end bit must be valid for the remaining BDs of a + * packet. + */ + #define PUSH32_DOORBELL_FLAGS_MASK UINT32_C(0xffc0) + #define PUSH32_DOORBELL_FLAGS_SFT 6 + uint16_t len; + /* + * This is the length of the host physical buffer this BD describes in + * bytes. This field must be valid on all BDs of a packet. + */ + uint32_t opaque; + /* + * The opaque data field is pass through to the completion and can be + * used for any data that the driver wants to associate with the + * transmit BD. This field must be valid on the first BD of a packet. + */ + uint16_t lflags; + /* + * All bits in this field must be valid on the first BD of a packet. + * Their value on other BDs of the packet will be ignored. + */ + /* + * If set to 1, the controller replaces the TCP/UPD checksum fields of + * normal TCP/UPD checksum, or the inner TCP/UDP checksum field of the + * encapsulated TCP/UDP packets with the hardware calculated TCP/UDP + * checksum for the packet associated with this descriptor. The flag is + * ignored if the LSO flag is set. This bit must be valid on the first + * BD of a packet. + */ + #define PUSH32_DOORBELL_LFLAGS_TCP_UDP_CHKSUM UINT32_C(0x1) + /* + * If set to 1, the controller replaces the IP checksum of the normal + * packets, or the inner IP checksum of the encapsulated packets with + * the hardware calculated IP checksum for the packet associated with + * this descriptor. This bit must be valid on the first BD of a packet. + */ + #define PUSH32_DOORBELL_LFLAGS_IP_CHKSUM UINT32_C(0x2) + /* + * If set to 1, the controller will not append an Ethernet CRC to the + * end of the frame. This bit must be valid on the first BD of a packet. + * Packet must be 64B or longer when this flag is set. It is not useful + * to use this bit with any form of TX offload such as CSO or LSO. The + * intent is that the packet from the host already has a valid Ethernet + * CRC on the packet. + */ + #define PUSH32_DOORBELL_LFLAGS_NOCRC UINT32_C(0x4) + /* + * If set to 1, the device will record the time at which the packet was + * actually transmitted at the TX MAC. This bit must be valid on the + * first BD of a packet. + */ + #define PUSH32_DOORBELL_LFLAGS_STAMP UINT32_C(0x8) + /* + * If set to 1, The controller replaces the tunnel IP checksum field + * with hardware calculated IP checksum for the IP header of the packet + * associated with this descriptor. For outer UDP checksum, global outer + * UDP checksum TE_NIC register needs to be enabled. If the global outer + * UDP checksum TE_NIC register bit is set, outer UDP checksum will be + * calculated for the following cases: 1. Packets with tcp_udp_chksum + * flag set to offload checksum for inner packet AND the inner packet is + * TCP/UDP. If the inner packet is ICMP for example (non-TCP/UDP), even + * if the tcp_udp_chksum is set, the outer UDP checksum will not be + * calculated. 2. Packets with lso flag set which implies inner TCP + * checksum calculation as part of LSO operation. + */ + #define PUSH32_DOORBELL_LFLAGS_T_IP_CHKSUM UINT32_C(0x10) + /* + * If set to 1, the device will treat this packet with LSO(Large Send + * Offload) processing for both normal or encapsulated packets, which is + * a form of TCP segmentation. When this bit is 1, the hdr_size and mss + * fields must be valid. The driver doesn't need to set t_ip_chksum, + * ip_chksum, and tcp_udp_chksum flags since the controller will replace + * the appropriate checksum fields for segmented packets. When this bit + * is 1, the hdr_size and mss fields must be valid. + */ + #define PUSH32_DOORBELL_LFLAGS_LSO UINT32_C(0x20) + /* + * If set to zero when LSO is '1', then the IPID will be treated as a + * 16b number and will be wrapped if it exceeds a value of 0xffff. If + * set to one when LSO is '1', then the IPID will be treated as a 15b + * number and will be wrapped if it exceeds a value 0f 0x7fff. + */ + #define PUSH32_DOORBELL_LFLAGS_IPID_FMT UINT32_C(0x40) + /* + * If set to zero when LSO is '1', then the IPID of the tunnel IP header + * will not be modified during LSO operations. If set to one when LSO is + * '1', then the IPID of the tunnel IP header will be incremented for + * each subsequent segment of an LSO operation. The flag is ignored if + * the LSO packet is a normal (non-tunneled) TCP packet. + */ + #define PUSH32_DOORBELL_LFLAGS_T_IPID UINT32_C(0x80) + /* + * If set to '1', then the RoCE ICRC will be appended to the packet. + * Packet must be a valid RoCE format packet. + */ + #define PUSH32_DOORBELL_LFLAGS_ROCE_CRC UINT32_C(0x100) + /* + * If set to '1', then the FCoE CRC will be appended to the packet. + * Packet must be a valid FCoE format packet. + */ + #define PUSH32_DOORBELL_LFLAGS_FCOE_CRC UINT32_C(0x200) + uint16_t hdr_size; + /* + * When LSO is '1', this field must contain the offset of the TCP + * payload from the beginning of the packet in as 16b words. In case of + * encapsulated/tunneling packet, this field contains the offset of the + * inner TCP payload from beginning of the packet as 16-bit words. This + * value must be valid on the first BD of a packet. + */ + #define PUSH32_DOORBELL_HDR_SIZE_MASK UINT32_C(0x1ff) + #define PUSH32_DOORBELL_HDR_SIZE_SFT 0 + uint32_t mss; + /* + * This is the MSS value that will be used to do the LSO processing. The + * value is the length in bytes of the TCP payload for each segment + * generated by the LSO operation. This value must be valid on the first + * BD of a packet. + */ + #define PUSH32_DOORBELL_MSS_MASK UINT32_C(0x7fff) + #define PUSH32_DOORBELL_MSS_SFT 0 + uint16_t unused_2; + uint16_t cfa_action; + /* + * This value selects a CFA action to perform on the packet. Set this + * value to zero if no CFA action is desired. This value must be valid + * on the first BD of a packet. + */ + uint32_t cfa_meta; + /* + * This value is action meta-data that defines CFA edit operations that + * are done in addition to any action editing. + */ + /* When key=1, This is the VLAN tag VID value. */ + #define PUSH32_DOORBELL_CFA_META_VLAN_VID_MASK UINT32_C(0xfff) + #define PUSH32_DOORBELL_CFA_META_VLAN_VID_SFT 0 + /* When key=1, This is the VLAN tag DE value. */ + #define PUSH32_DOORBELL_CFA_META_VLAN_DE UINT32_C(0x1000) + /* When key=1, This is the VLAN tag PRI value. */ + #define PUSH32_DOORBELL_CFA_META_VLAN_PRI_MASK UINT32_C(0xe000) + #define PUSH32_DOORBELL_CFA_META_VLAN_PRI_SFT 13 + /* When key=1, This is the VLAN tag TPID select value. */ + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_MASK UINT32_C(0x70000) + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_SFT 16 + /* 0x88a8 */ + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID88A8 (UINT32_C(0x0) << 16) + /* 0x8100 */ + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID8100 (UINT32_C(0x1) << 16) + /* 0x9100 */ + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID9100 (UINT32_C(0x2) << 16) + /* 0x9200 */ + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID9200 (UINT32_C(0x3) << 16) + /* 0x9300 */ + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPID9300 (UINT32_C(0x4) << 16) + /* Value programmed in CFA VLANTPID register. */ + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPIDCFG (UINT32_C(0x5) << 16) + #define PUSH32_DOORBELL_CFA_META_VLAN_TPID_LAST PUSH32_DOORBELL_CFA_META_VLAN_TPID_TPIDCFG + /* When key=1, This is the VLAN tag TPID select value. */ + #define PUSH32_DOORBELL_CFA_META_VLAN_RESERVED_MASK UINT32_C(0xff80000) + #define PUSH32_DOORBELL_CFA_META_VLAN_RESERVED_SFT 19 + /* + * This field identifies the type of edit to be performed on the packet. + * This value must be valid on the first BD of a packet. + */ + #define PUSH32_DOORBELL_CFA_META_KEY_MASK UINT32_C(0xf0000000) + #define PUSH32_DOORBELL_CFA_META_KEY_SFT 28 + /* No editing */ + #define PUSH32_DOORBELL_CFA_META_KEY_NONE (UINT32_C(0x0) << 28) + /* + * - meta[17:16] - TPID select value (0 = 0x8100). - meta[15:12] + * - PRI/DE value. - meta[11:0] - VID value. + */ + #define PUSH32_DOORBELL_CFA_META_KEY_VLAN_TAG (UINT32_C(0x1) << 28) + #define PUSH32_DOORBELL_CFA_META_KEY_LAST PUSH32_DOORBELL_CFA_META_KEY_VLAN_TAG + uint32_t data[25]; + /* + * This is the data for the push packet. If the packet data does not fit + * in the first pass, data writing can continue at offset 4 of the + * doorbell for up to 4 additional passes for a total data size of 512B + * maximum. + */ +} __attribute__((packed)); + +/* HW Resource Manager Specification 1.4.0 */ +#define HWRM_VERSION_MAJOR 1 +#define HWRM_VERSION_MINOR 4 +#define HWRM_VERSION_UPDATE 0 + +#define HWRM_VERSION_STR "1.4.0" +/* + * Following is the signature for HWRM message field that indicates not + * applicable (All F's). Need to cast it the size of the field if needed. + */ +#define HWRM_NA_SIGNATURE ((uint32_t)(-1)) +#define HWRM_MAX_REQ_LEN (128) /* hwrm_func_buf_rgtr */ +#define HWRM_MAX_RESP_LEN (176) /* hwrm_func_qstats */ +#define HW_HASH_INDEX_SIZE 0x80 /* 7 bit indirection table index. */ +#define HW_HASH_KEY_SIZE 40 +#define HWRM_RESP_VALID_KEY 1 /* valid key for HWRM response */ +/* + * Description: Port Rx Statistics Formats. The HWRM shall return any + * unsupported counter with a value of 0xFFFFFFFF for 32-bit counters and + * 0xFFFFFFFFFFFFFFFF for 64-bit counters. + */ +/* + * Note: The Hardware Resource Manager (HWRM) manages various hardware resources + * inside the chip. The HWRM is implemented in firmware, and runs on embedded + * processors inside the chip. This firmware service is vital part of the chip. + * The chip can not be used by a driver or HWRM client without the HWRM. + */ +/* Input (16 bytes) */ + +struct input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (8 bytes) */ + +struct output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ +} __attribute__((packed)); + +#define GET_HWRM_REQ_TYPE(x) \ + ((x) == 0x98 ? "HWRM_CFA_ENCAP_RECORD_FREE": \ + ((x) == 0x99 ? "HWRM_CFA_NTUPLE_FILTER_ALLOC": \ + ((x) == 0x90 ? "HWRM_CFA_L2_FILTER_ALLOC": \ + ((x) == 0x91 ? "HWRM_CFA_L2_FILTER_FREE": \ + ((x) == 0x92 ? "HWRM_CFA_L2_FILTER_CFG": \ + ((x) == 0x93 ? "HWRM_CFA_L2_SET_RX_MASK": \ + ((x) == 0x94 ? "RESERVED3": \ + ((x) == 0x95 ? "HWRM_CFA_TUNNEL_FILTER_ALLOC": \ + ((x) == 0x96 ? "HWRM_CFA_TUNNEL_FILTER_FREE": \ + ((x) == 0x97 ? "HWRM_CFA_ENCAP_RECORD_ALLOC": \ + ((x) == 0x10 ? "RESERVED1": \ + ((x) == 0x11 ? "HWRM_FUNC_RESET": \ + ((x) == 0x12 ? "HWRM_FUNC_GETFID": \ + ((x) == 0x13 ? "HWRM_FUNC_VF_ALLOC": \ + ((x) == 0x14 ? "HWRM_FUNC_VF_FREE": \ + ((x) == 0x15 ? "HWRM_FUNC_QCAPS": \ + ((x) == 0x16 ? "HWRM_FUNC_QCFG": \ + ((x) == 0x17 ? "HWRM_FUNC_CFG": \ + ((x) == 0x18 ? "HWRM_FUNC_QSTATS": \ + ((x) == 0x19 ? "HWRM_FUNC_CLR_STATS": \ + ((x) == 0xe0 ? "HWRM_TEMP_MONITOR_QUERY": \ + ((x) == 0xd3 ? "HWRM_FWD_ASYNC_EVENT_CMPL": \ + ((x) == 0xd2 ? "HWRM_FWD_RESP": \ + ((x) == 0x1a ? "HWRM_FUNC_DRV_UNRGTR": \ + ((x) == 0x1b ? "HWRM_FUNC_VF_RESC_FREE": \ + ((x) == 0x1c ? "HWRM_FUNC_VF_VNIC_IDS_QUERY": \ + ((x) == 0x1d ? "HWRM_FUNC_DRV_RGTR": \ + ((x) == 0x1e ? "HWRM_FUNC_DRV_QVER": \ + ((x) == 0x1f ? "HWRM_FUNC_BUF_RGTR": \ + ((x) == 0x9a ? "HWRM_CFA_NTUPLE_FILTER_FREE": \ + ((x) == 0x9b ? "HWRM_CFA_NTUPLE_FILTER_CFG": \ + ((x) == 0x9c ? "HWRM_CFA_EM_FLOW_ALLOC": \ + ((x) == 0x9d ? "HWRM_CFA_EM_FLOW_FREE": \ + ((x) == 0x9e ? "HWRM_CFA_EM_FLOW_CFG": \ + ((x) == 0xd1 ? "HWRM_REJECT_FWD_RESP": \ + ((x) == 0xd0 ? "HWRM_EXEC_FWD_RESP": \ + ((x) == 0xc8 ? "HWRM_FW_SET_TIME": \ + ((x) == 0xc9 ? "HWRM_FW_GET_TIME": \ + ((x) == 0xc0 ? "HWRM_FW_RESET": \ + ((x) == 0xc1 ? "HWRM_FW_QSTATUS": \ + ((x) == 0x70 ? "HWRM_VNIC_RSS_COS_LB_CTX_ALLOC": \ + ((x) == 0x71 ? "HWRM_VNIC_RSS_COS_LB_CTX_FREE": \ + ((x) == 0xb1 ? "HWRM_STAT_CTX_FREE": \ + ((x) == 0xb0 ? "HWRM_STAT_CTX_ALLOC": \ + ((x) == 0xb3 ? "HWRM_STAT_CTX_CLR_STATS": \ + ((x) == 0xb2 ? "HWRM_STAT_CTX_QUERY": \ + ((x) == 0xfff6 ? "HWRM_NVM_GET_DEV_INFO": \ + ((x) == 0x61 ? "HWRM_RING_GRP_FREE": \ + ((x) == 0x60 ? "HWRM_RING_GRP_ALLOC": \ + ((x) == 0xf1 ? "HWRM_WOL_FILTER_FREE": \ + ((x) == 0xf0 ? "HWRM_WOL_FILTER_ALLOC": \ + ((x) == 0xf3 ? "HWRM_WOL_REASON_QCFG": \ + ((x) == 0xf2 ? "HWRM_WOL_FILTER_QCFG": \ + ((x) == 0xa0 ? "HWRM_TUNNEL_DST_PORT_QUERY": \ + ((x) == 0xa1 ? "HWRM_TUNNEL_DST_PORT_ALLOC": \ + ((x) == 0xa2 ? "HWRM_TUNNEL_DST_PORT_FREE": \ + ((x) == 0xfffc ? "HWRM_NVM_RAW_DUMP": \ + ((x) == 0xfffb ? "HWRM_NVM_GET_DIR_INFO": \ + ((x) == 0xfffa ? "HWRM_NVM_GET_DIR_ENTRIES": \ + ((x) == 0xe ? "HWRM_FUNC_BUF_UNRGTR": \ + ((x) == 0xf ? "HWRM_FUNC_VF_CFG": \ + ((x) == 0xffff ? "HWRM_NVM_RAW_WRITE_BLK": \ + ((x) == 0xfffe ? "HWRM_NVM_WRITE": \ + ((x) == 0xfffd ? "HWRM_NVM_READ": \ + ((x) == 0x50 ? "HWRM_RING_ALLOC": \ + ((x) == 0x51 ? "HWRM_RING_FREE": \ + ((x) == 0x52 ? "HWRM_RING_CMPL_RING_QAGGINT_PARAMS": \ + ((x) == 0x53 ? "HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS": \ + ((x) == 0x4a ? "HWRM_VNIC_QCAPS": \ + ((x) == 0x49 ? "HWRM_VNIC_PLCMODES_QCFG": \ + ((x) == 0x48 ? "HWRM_VNIC_PLCMODES_CFG": \ + ((x) == 0x47 ? "HWRM_VNIC_RSS_QCFG": \ + ((x) == 0x46 ? "HWRM_VNIC_RSS_CFG": \ + ((x) == 0x45 ? "HWRM_VNIC_TPA_QCFG": \ + ((x) == 0x44 ? "HWRM_VNIC_TPA_CFG": \ + ((x) == 0x43 ? "HWRM_VNIC_QCFG": \ + ((x) == 0x42 ? "HWRM_VNIC_CFG": \ + ((x) == 0x41 ? "HWRM_VNIC_FREE": \ + ((x) == 0x40 ? "HWRM_VNIC_ALLOC": \ + ((x) == 0x0 ? "HWRM_VER_GET": \ + ((x) == 0xfff9 ? "HWRM_NVM_FIND_DIR_ENTRY": \ + ((x) == 0xfff8 ? "HWRM_NVM_MOD_DIR_ENTRY": \ + ((x) == 0xfff7 ? "HWRM_NVM_ERASE_DIR_ENTRY": \ + ((x) == 0x5e ? "HWRM_RING_RESET": \ + ((x) == 0xfff5 ? "HWRM_NVM_VERIFY_UPDATE": \ + ((x) == 0xfff4 ? "HWRM_NVM_MODIFY": \ + ((x) == 0xfff3 ? "HWRM_NVM_INSTALL_UPDATE": \ + ((x) == 0x2a ? "HWRM_PORT_PHY_QCAPS": \ + ((x) == 0x2c ? "HWRM_PORT_PHY_I2C_READ": \ + ((x) == 0x2b ? "HWRM_PORT_PHY_I2C_WRITE": \ + ((x) == 0x38 ? "HWRM_QUEUE_PRI2COS_CFG": \ + ((x) == 0x39 ? "HWRM_QUEUE_COS2BW_QCFG": \ + ((x) == 0x32 ? "HWRM_QUEUE_CFG": \ + ((x) == 0x33 ? "HWRM_QUEUE_BUFFERS_QCFG": \ + ((x) == 0x30 ? "HWRM_QUEUE_QPORTCFG": \ + ((x) == 0x31 ? "HWRM_QUEUE_QCFG": \ + ((x) == 0x36 ? "HWRM_QUEUE_PFCENABLE_CFG": \ + ((x) == 0x37 ? "HWRM_QUEUE_PRI2COS_QCFG": \ + ((x) == 0x34 ? "HWRM_QUEUE_BUFFERS_CFG": \ + ((x) == 0x35 ? "HWRM_QUEUE_PFCENABLE_QCFG": \ + ((x) == 0xff14 ? "HWRM_DBG_DUMP": \ + ((x) == 0xff12 ? "HWRM_DBG_WRITE_DIRECT": \ + ((x) == 0xff13 ? "HWRM_DBG_WRITE_INDIRECT": \ + ((x) == 0xff10 ? "HWRM_DBG_READ_DIRECT": \ + ((x) == 0xff11 ? "HWRM_DBG_READ_INDIRECT": \ + ((x) == 0x25 ? "HWRM_PORT_CLR_STATS": \ + ((x) == 0x24 ? "HWRM_PORT_LPBK_QSTATS": \ + ((x) == 0x27 ? "HWRM_PORT_PHY_QCFG": \ + ((x) == 0x26 ? "HWRM_PORT_LPBK_CLR_STATS": \ + ((x) == 0x21 ? "HWRM_PORT_MAC_CFG": \ + ((x) == 0x20 ? "HWRM_PORT_PHY_CFG": \ + ((x) == 0x23 ? "HWRM_PORT_QSTATS": \ + ((x) == 0x22 ? "HWRM_PORT_TS_QUERY": \ + ((x) == 0x29 ? "HWRM_PORT_BLINK_LED": \ + ((x) == 0x28 ? "HWRM_PORT_MAC_QCFG": \ + ((x) == 0x3a ? "HWRM_QUEUE_COS2BW_CFG": \ + "Unknown req_type")))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) + +/* Command numbering (8 bytes) */ + +struct cmd_nums { + uint16_t req_type; + /* + * This version of the specification defines the commands listed in the + * table below. The following are general implementation requirements + * for these commands: # All commands listed below that are marked + * neither reserved nor experimental shall be implemented by the HWRM. # + * A HWRM client compliant to this specification should not use commands + * outside of the list below. # A HWRM client compliant to this + * specification should not use command numbers marked reserved below. # + * A command marked experimental below may not be implemented by the + * HWRM. # A command marked experimental may change in the future + * version of the HWRM specification. # A command not listed below may + * be implemented by the HWRM. The behavior of commands that are not + * listed below is outside the scope of this specification. + */ + #define HWRM_VER_GET (UINT32_C(0x0)) + #define HWRM_FUNC_BUF_UNRGTR (UINT32_C(0xe)) + /* Experimental */ + #define HWRM_FUNC_VF_CFG (UINT32_C(0xf)) + /* Reserved for future use */ + #define RESERVED1 (UINT32_C(0x10)) + #define HWRM_FUNC_RESET (UINT32_C(0x11)) + #define HWRM_FUNC_GETFID (UINT32_C(0x12)) + #define HWRM_FUNC_VF_ALLOC (UINT32_C(0x13)) + #define HWRM_FUNC_VF_FREE (UINT32_C(0x14)) + #define HWRM_FUNC_QCAPS (UINT32_C(0x15)) + #define HWRM_FUNC_QCFG (UINT32_C(0x16)) + #define HWRM_FUNC_CFG (UINT32_C(0x17)) + #define HWRM_FUNC_QSTATS (UINT32_C(0x18)) + #define HWRM_FUNC_CLR_STATS (UINT32_C(0x19)) + #define HWRM_FUNC_DRV_UNRGTR (UINT32_C(0x1a)) + #define HWRM_FUNC_VF_RESC_FREE (UINT32_C(0x1b)) + #define HWRM_FUNC_VF_VNIC_IDS_QUERY (UINT32_C(0x1c)) + #define HWRM_FUNC_DRV_RGTR (UINT32_C(0x1d)) + #define HWRM_FUNC_DRV_QVER (UINT32_C(0x1e)) + #define HWRM_FUNC_BUF_RGTR (UINT32_C(0x1f)) + #define HWRM_PORT_PHY_CFG (UINT32_C(0x20)) + #define HWRM_PORT_MAC_CFG (UINT32_C(0x21)) + /* Experimental */ + #define HWRM_PORT_TS_QUERY (UINT32_C(0x22)) + #define HWRM_PORT_QSTATS (UINT32_C(0x23)) + #define HWRM_PORT_LPBK_QSTATS (UINT32_C(0x24)) + /* Experimental */ + #define HWRM_PORT_CLR_STATS (UINT32_C(0x25)) + /* Experimental */ + #define HWRM_PORT_LPBK_CLR_STATS (UINT32_C(0x26)) + #define HWRM_PORT_PHY_QCFG (UINT32_C(0x27)) + /* Experimental */ + #define HWRM_PORT_MAC_QCFG (UINT32_C(0x28)) + /* Experimental */ + #define HWRM_PORT_BLINK_LED (UINT32_C(0x29)) + /* Experimental */ + #define HWRM_PORT_PHY_QCAPS (UINT32_C(0x2a)) + /* Experimental */ + #define HWRM_PORT_PHY_I2C_WRITE (UINT32_C(0x2b)) + /* Experimental */ + #define HWRM_PORT_PHY_I2C_READ (UINT32_C(0x2c)) + #define HWRM_QUEUE_QPORTCFG (UINT32_C(0x30)) + #define HWRM_QUEUE_QCFG (UINT32_C(0x31)) + #define HWRM_QUEUE_CFG (UINT32_C(0x32)) + #define HWRM_QUEUE_BUFFERS_QCFG (UINT32_C(0x33)) + #define HWRM_QUEUE_BUFFERS_CFG (UINT32_C(0x34)) + /* Experimental */ + #define HWRM_QUEUE_PFCENABLE_QCFG (UINT32_C(0x35)) + /* Experimental */ + #define HWRM_QUEUE_PFCENABLE_CFG (UINT32_C(0x36)) + /* Experimental */ + #define HWRM_QUEUE_PRI2COS_QCFG (UINT32_C(0x37)) + /* Experimental */ + #define HWRM_QUEUE_PRI2COS_CFG (UINT32_C(0x38)) + /* Experimental */ + #define HWRM_QUEUE_COS2BW_QCFG (UINT32_C(0x39)) + /* Experimental */ + #define HWRM_QUEUE_COS2BW_CFG (UINT32_C(0x3a)) + #define HWRM_VNIC_ALLOC (UINT32_C(0x40)) + #define HWRM_VNIC_FREE (UINT32_C(0x41)) + #define HWRM_VNIC_CFG (UINT32_C(0x42)) + /* Experimental */ + #define HWRM_VNIC_QCFG (UINT32_C(0x43)) + #define HWRM_VNIC_TPA_CFG (UINT32_C(0x44)) + /* Experimental */ + #define HWRM_VNIC_TPA_QCFG (UINT32_C(0x45)) + #define HWRM_VNIC_RSS_CFG (UINT32_C(0x46)) + #define HWRM_VNIC_RSS_QCFG (UINT32_C(0x47)) + #define HWRM_VNIC_PLCMODES_CFG (UINT32_C(0x48)) + #define HWRM_VNIC_PLCMODES_QCFG (UINT32_C(0x49)) + /* Experimental */ + #define HWRM_VNIC_QCAPS (UINT32_C(0x4a)) + #define HWRM_RING_ALLOC (UINT32_C(0x50)) + #define HWRM_RING_FREE (UINT32_C(0x51)) + #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS (UINT32_C(0x52)) + #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS (UINT32_C(0x53)) + #define HWRM_RING_RESET (UINT32_C(0x5e)) + #define HWRM_RING_GRP_ALLOC (UINT32_C(0x60)) + #define HWRM_RING_GRP_FREE (UINT32_C(0x61)) + #define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC (UINT32_C(0x70)) + #define HWRM_VNIC_RSS_COS_LB_CTX_FREE (UINT32_C(0x71)) + #define HWRM_CFA_L2_FILTER_ALLOC (UINT32_C(0x90)) + #define HWRM_CFA_L2_FILTER_FREE (UINT32_C(0x91)) + #define HWRM_CFA_L2_FILTER_CFG (UINT32_C(0x92)) + #define HWRM_CFA_L2_SET_RX_MASK (UINT32_C(0x93)) + /* Reserved for future use */ + #define RESERVED3 (UINT32_C(0x94)) + #define HWRM_CFA_TUNNEL_FILTER_ALLOC (UINT32_C(0x95)) + #define HWRM_CFA_TUNNEL_FILTER_FREE (UINT32_C(0x96)) + /* Experimental */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC (UINT32_C(0x97)) + /* Experimental */ + #define HWRM_CFA_ENCAP_RECORD_FREE (UINT32_C(0x98)) + #define HWRM_CFA_NTUPLE_FILTER_ALLOC (UINT32_C(0x99)) + #define HWRM_CFA_NTUPLE_FILTER_FREE (UINT32_C(0x9a)) + #define HWRM_CFA_NTUPLE_FILTER_CFG (UINT32_C(0x9b)) + /* Experimental */ + #define HWRM_CFA_EM_FLOW_ALLOC (UINT32_C(0x9c)) + /* Experimental */ + #define HWRM_CFA_EM_FLOW_FREE (UINT32_C(0x9d)) + /* Experimental */ + #define HWRM_CFA_EM_FLOW_CFG (UINT32_C(0x9e)) + #define HWRM_TUNNEL_DST_PORT_QUERY (UINT32_C(0xa0)) + #define HWRM_TUNNEL_DST_PORT_ALLOC (UINT32_C(0xa1)) + #define HWRM_TUNNEL_DST_PORT_FREE (UINT32_C(0xa2)) + #define HWRM_STAT_CTX_ALLOC (UINT32_C(0xb0)) + #define HWRM_STAT_CTX_FREE (UINT32_C(0xb1)) + #define HWRM_STAT_CTX_QUERY (UINT32_C(0xb2)) + #define HWRM_STAT_CTX_CLR_STATS (UINT32_C(0xb3)) + #define HWRM_FW_RESET (UINT32_C(0xc0)) + #define HWRM_FW_QSTATUS (UINT32_C(0xc1)) + /* Experimental */ + #define HWRM_FW_SET_TIME (UINT32_C(0xc8)) + /* Experimental */ + #define HWRM_FW_GET_TIME (UINT32_C(0xc9)) + #define HWRM_EXEC_FWD_RESP (UINT32_C(0xd0)) + #define HWRM_REJECT_FWD_RESP (UINT32_C(0xd1)) + #define HWRM_FWD_RESP (UINT32_C(0xd2)) + #define HWRM_FWD_ASYNC_EVENT_CMPL (UINT32_C(0xd3)) + #define HWRM_TEMP_MONITOR_QUERY (UINT32_C(0xe0)) + /* Experimental */ + #define HWRM_WOL_FILTER_ALLOC (UINT32_C(0xf0)) + /* Experimental */ + #define HWRM_WOL_FILTER_FREE (UINT32_C(0xf1)) + /* Experimental */ + #define HWRM_WOL_FILTER_QCFG (UINT32_C(0xf2)) + /* Experimental */ + #define HWRM_WOL_REASON_QCFG (UINT32_C(0xf3)) + /* Experimental */ + #define HWRM_DBG_READ_DIRECT (UINT32_C(0xff10)) + /* Experimental */ + #define HWRM_DBG_READ_INDIRECT (UINT32_C(0xff11)) + /* Experimental */ + #define HWRM_DBG_WRITE_DIRECT (UINT32_C(0xff12)) + /* Experimental */ + #define HWRM_DBG_WRITE_INDIRECT (UINT32_C(0xff13)) + #define HWRM_DBG_DUMP (UINT32_C(0xff14)) + #define HWRM_NVM_INSTALL_UPDATE (UINT32_C(0xfff3)) + #define HWRM_NVM_MODIFY (UINT32_C(0xfff4)) + #define HWRM_NVM_VERIFY_UPDATE (UINT32_C(0xfff5)) + #define HWRM_NVM_GET_DEV_INFO (UINT32_C(0xfff6)) + #define HWRM_NVM_ERASE_DIR_ENTRY (UINT32_C(0xfff7)) + #define HWRM_NVM_MOD_DIR_ENTRY (UINT32_C(0xfff8)) + #define HWRM_NVM_FIND_DIR_ENTRY (UINT32_C(0xfff9)) + #define HWRM_NVM_GET_DIR_ENTRIES (UINT32_C(0xfffa)) + #define HWRM_NVM_GET_DIR_INFO (UINT32_C(0xfffb)) + #define HWRM_NVM_RAW_DUMP (UINT32_C(0xfffc)) + #define HWRM_NVM_READ (UINT32_C(0xfffd)) + #define HWRM_NVM_WRITE (UINT32_C(0xfffe)) + #define HWRM_NVM_RAW_WRITE_BLK (UINT32_C(0xffff)) + uint16_t unused_0[3]; +} __attribute__((packed)); + +#define GET_HWRM_ERROR_CODE(x) \ + ((x) == 0xf ? "HWRM_ERROR": \ + ((x) == 0xffff ? "CMD_NOT_SUPPORTED": \ + ((x) == 0xfffe ? "UNKNOWN_ERR": \ + ((x) == 0x4 ? "RESOURCE_ALLOC_ERROR": \ + ((x) == 0x5 ? "INVALID_FLAGS": \ + ((x) == 0x6 ? "INVALID_ENABLES": \ + ((x) == 0x0 ? "SUCCESS": \ + ((x) == 0x1 ? "FAIL": \ + ((x) == 0x2 ? "INVALID_PARAMS": \ + ((x) == 0x3 ? "RESOURCE_ACCESS_DENIED": \ + "Unknown error_code")))))))))) + +/* Return Codes (8 bytes) */ + +struct ret_codes { + uint16_t error_code; + /* These are numbers assigned to return/error codes. */ + /* Request was successfully executed by the HWRM. */ + #define HWRM_ERR_CODE_SUCCESS (UINT32_C(0x0)) + /* THe HWRM failed to execute the request. */ + #define HWRM_ERR_CODE_FAIL (UINT32_C(0x1)) + /* The request contains invalid argument(s) or input parameters. */ + #define HWRM_ERR_CODE_INVALID_PARAMS (UINT32_C(0x2)) + /* + * The requester is not allowed to access the requested + * resource. This error code shall be provided in a response to + * a request to query or modify an existing resource that is not + * accessible by the requester. + */ + #define HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED (UINT32_C(0x3)) + /* + * The HWRM is unable to allocate the requested resource. This + * code only applies to requests for HWRM resource allocations. + */ + #define HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR (UINT32_C(0x4)) + /* Invalid combination of flags is specified in the request. */ + #define HWRM_ERR_CODE_INVALID_FLAGS (UINT32_C(0x5)) + /* + * Invalid combination of enables fields is specified in the + * request. + */ + #define HWRM_ERR_CODE_INVALID_ENABLES (UINT32_C(0x6)) + /* Generic HWRM execution error that represents an internal error. */ + #define HWRM_ERR_CODE_HWRM_ERROR (UINT32_C(0xf)) + /* Unknown error */ + #define HWRM_ERR_CODE_UNKNOWN_ERR (UINT32_C(0xfffe)) + /* Unsupported or invalid command */ + #define HWRM_ERR_CODE_CMD_NOT_SUPPORTED (UINT32_C(0xffff)) + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_err_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t opaque_0; + /* debug info for this error response. */ + uint16_t opaque_1; + /* debug info for this error response. */ + uint8_t cmd_err; + /* + * In the case of an error response, command specific error code is + * returned in this field. + */ + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* Port Tx Statistics Formats (408 bytes) */ + +struct tx_port_stats { + uint64_t tx_64b_frames; + /* Total Number of 64 Bytes frames transmitted */ + uint64_t tx_65b_127b_frames; + /* Total Number of 65-127 Bytes frames transmitted */ + uint64_t tx_128b_255b_frames; + /* Total Number of 128-255 Bytes frames transmitted */ + uint64_t tx_256b_511b_frames; + /* Total Number of 256-511 Bytes frames transmitted */ + uint64_t tx_512b_1023b_frames; + /* Total Number of 512-1023 Bytes frames transmitted */ + uint64_t tx_1024b_1518_frames; + /* Total Number of 1024-1518 Bytes frames transmitted */ + uint64_t tx_good_vlan_frames; + /* + * Total Number of each good VLAN (exludes FCS errors) frame transmitted + * which is 1519 to 1522 bytes in length inclusive (excluding framing + * bits but including FCS bytes). + */ + uint64_t tx_1519b_2047_frames; + /* Total Number of 1519-2047 Bytes frames transmitted */ + uint64_t tx_2048b_4095b_frames; + /* Total Number of 2048-4095 Bytes frames transmitted */ + uint64_t tx_4096b_9216b_frames; + /* Total Number of 4096-9216 Bytes frames transmitted */ + uint64_t tx_9217b_16383b_frames; + /* Total Number of 9217-16383 Bytes frames transmitted */ + uint64_t tx_good_frames; + /* Total Number of good frames transmitted */ + uint64_t tx_total_frames; + /* Total Number of frames transmitted */ + uint64_t tx_ucast_frames; + /* Total number of unicast frames transmitted */ + uint64_t tx_mcast_frames; + /* Total number of multicast frames transmitted */ + uint64_t tx_bcast_frames; + /* Total number of broadcast frames transmitted */ + uint64_t tx_pause_frames; + /* Total number of PAUSE control frames transmitted */ + uint64_t tx_pfc_frames; + /* Total number of PFC/per-priority PAUSE control frames transmitted */ + uint64_t tx_jabber_frames; + /* Total number of jabber frames transmitted */ + uint64_t tx_fcs_err_frames; + /* Total number of frames transmitted with FCS error */ + uint64_t tx_control_frames; + /* Total number of control frames transmitted */ + uint64_t tx_oversz_frames; + /* Total number of over-sized frames transmitted */ + uint64_t tx_single_dfrl_frames; + /* Total number of frames with single deferral */ + uint64_t tx_multi_dfrl_frames; + /* Total number of frames with multiple deferrals */ + uint64_t tx_single_coll_frames; + /* Total number of frames with single collision */ + uint64_t tx_multi_coll_frames; + /* Total number of frames with multiple collisions */ + uint64_t tx_late_coll_frames; + /* Total number of frames with late collisions */ + uint64_t tx_excessive_coll_frames; + /* Total number of frames with excessive collisions */ + uint64_t tx_frag_frames; + /* Total number of fragmented frames transmitted */ + uint64_t tx_err; + /* Total number of transmit errors */ + uint64_t tx_tagged_frames; + /* Total number of single VLAN tagged frames transmitted */ + uint64_t tx_dbl_tagged_frames; + /* Total number of double VLAN tagged frames transmitted */ + uint64_t tx_runt_frames; + /* Total number of runt frames transmitted */ + uint64_t tx_fifo_underruns; + /* Total number of TX FIFO under runs */ + uint64_t tx_pfc_ena_frames_pri0; + /* Total number of PFC frames with PFC enabled bit for Pri 0 transmitted */ + uint64_t tx_pfc_ena_frames_pri1; + /* Total number of PFC frames with PFC enabled bit for Pri 1 transmitted */ + uint64_t tx_pfc_ena_frames_pri2; + /* Total number of PFC frames with PFC enabled bit for Pri 2 transmitted */ + uint64_t tx_pfc_ena_frames_pri3; + /* Total number of PFC frames with PFC enabled bit for Pri 3 transmitted */ + uint64_t tx_pfc_ena_frames_pri4; + /* Total number of PFC frames with PFC enabled bit for Pri 4 transmitted */ + uint64_t tx_pfc_ena_frames_pri5; + /* Total number of PFC frames with PFC enabled bit for Pri 5 transmitted */ + uint64_t tx_pfc_ena_frames_pri6; + /* Total number of PFC frames with PFC enabled bit for Pri 6 transmitted */ + uint64_t tx_pfc_ena_frames_pri7; + /* Total number of PFC frames with PFC enabled bit for Pri 7 transmitted */ + uint64_t tx_eee_lpi_events; + /* Total number of EEE LPI Events on TX */ + uint64_t tx_eee_lpi_duration; + /* EEE LPI Duration Counter on TX */ + uint64_t tx_llfc_logical_msgs; + /* Total number of Link Level Flow Control (LLFC) messages transmitted */ + uint64_t tx_hcfc_msgs; + /* Total number of HCFC messages transmitted */ + uint64_t tx_total_collisions; + /* Total number of TX collisions */ + uint64_t tx_bytes; + /* Total number of transmitted bytes */ + uint64_t tx_xthol_frames; + /* Total number of end-to-end HOL frames */ + uint64_t tx_stat_discard; + /* Total Tx Drops per Port reported by STATS block */ + uint64_t tx_stat_error; + /* Total Tx Error Drops per Port reported by STATS block */ +} __attribute__((packed)); + +/* Port Rx Statistics Formats (528 bytes) */ + +struct rx_port_stats { + uint64_t rx_64b_frames; + /* Total Number of 64 Bytes frames received */ + uint64_t rx_65b_127b_frames; + /* Total Number of 65-127 Bytes frames received */ + uint64_t rx_128b_255b_frames; + /* Total Number of 128-255 Bytes frames received */ + uint64_t rx_256b_511b_frames; + /* Total Number of 256-511 Bytes frames received */ + uint64_t rx_512b_1023b_frames; + /* Total Number of 512-1023 Bytes frames received */ + uint64_t rx_1024b_1518_frames; + /* Total Number of 1024-1518 Bytes frames received */ + uint64_t rx_good_vlan_frames; + /* + * Total Number of each good VLAN (exludes FCS errors) frame received + * which is 1519 to 1522 bytes in length inclusive (excluding framing + * bits but including FCS bytes). + */ + uint64_t rx_1519b_2047b_frames; + /* Total Number of 1519-2047 Bytes frames received */ + uint64_t rx_2048b_4095b_frames; + /* Total Number of 2048-4095 Bytes frames received */ + uint64_t rx_4096b_9216b_frames; + /* Total Number of 4096-9216 Bytes frames received */ + uint64_t rx_9217b_16383b_frames; + /* Total Number of 9217-16383 Bytes frames received */ + uint64_t rx_total_frames; + /* Total number of frames received */ + uint64_t rx_ucast_frames; + /* Total number of unicast frames received */ + uint64_t rx_mcast_frames; + /* Total number of multicast frames received */ + uint64_t rx_bcast_frames; + /* Total number of broadcast frames received */ + uint64_t rx_fcs_err_frames; + /* Total number of received frames with FCS error */ + uint64_t rx_ctrl_frames; + /* Total number of control frames received */ + uint64_t rx_pause_frames; + /* Total number of PAUSE frames received */ + uint64_t rx_pfc_frames; + /* Total number of PFC frames received */ + uint64_t rx_unsupported_opcode_frames; + /* Total number of frames received with an unsupported opcode */ + uint64_t rx_unsupported_da_pausepfc_frames; + /* + * Total number of frames received with an unsupported DA for pause and + * PFC + */ + uint64_t rx_wrong_sa_frames; + /* Total number of frames received with an unsupported SA */ + uint64_t rx_align_err_frames; + /* Total number of received packets with alignment error */ + uint64_t rx_oor_len_frames; + /* Total number of received frames with out-of-range length */ + uint64_t rx_code_err_frames; + /* Total number of received frames with error termination */ + uint64_t rx_false_carrier_frames; + /* + * Total number of received frames with a false carrier is detected + * during idle, as defined by RX_ER samples active and RXD is 0xE. The + * event is reported along with the statistics generated on the next + * received frame. Only one false carrier condition can be detected and + * logged between frames. Carrier event, valid for 10M/100M speed modes + * only. + */ + uint64_t rx_ovrsz_frames; + /* Total number of over-sized frames received */ + uint64_t rx_jbr_frames; + /* Total number of jabber packets received */ + uint64_t rx_mtu_err_frames; + /* Total number of received frames with MTU error */ + uint64_t rx_match_crc_frames; + /* Total number of received frames with CRC match */ + uint64_t rx_promiscuous_frames; + /* Total number of frames received promiscuously */ + uint64_t rx_tagged_frames; + /* Total number of received frames with one or two VLAN tags */ + uint64_t rx_double_tagged_frames; + /* Total number of received frames with two VLAN tags */ + uint64_t rx_trunc_frames; + /* Total number of truncated frames received */ + uint64_t rx_good_frames; + /* Total number of good frames (without errors) received */ + uint64_t rx_pfc_xon2xoff_frames_pri0; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 0 + */ + uint64_t rx_pfc_xon2xoff_frames_pri1; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 1 + */ + uint64_t rx_pfc_xon2xoff_frames_pri2; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 2 + */ + uint64_t rx_pfc_xon2xoff_frames_pri3; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 3 + */ + uint64_t rx_pfc_xon2xoff_frames_pri4; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 4 + */ + uint64_t rx_pfc_xon2xoff_frames_pri5; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 5 + */ + uint64_t rx_pfc_xon2xoff_frames_pri6; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 6 + */ + uint64_t rx_pfc_xon2xoff_frames_pri7; + /* + * Total number of received PFC frames with transition from XON to XOFF + * on Pri 7 + */ + uint64_t rx_pfc_ena_frames_pri0; + /* Total number of received PFC frames with PFC enabled bit for Pri 0 */ + uint64_t rx_pfc_ena_frames_pri1; + /* Total number of received PFC frames with PFC enabled bit for Pri 1 */ + uint64_t rx_pfc_ena_frames_pri2; + /* Total number of received PFC frames with PFC enabled bit for Pri 2 */ + uint64_t rx_pfc_ena_frames_pri3; + /* Total number of received PFC frames with PFC enabled bit for Pri 3 */ + uint64_t rx_pfc_ena_frames_pri4; + /* Total number of received PFC frames with PFC enabled bit for Pri 4 */ + uint64_t rx_pfc_ena_frames_pri5; + /* Total number of received PFC frames with PFC enabled bit for Pri 5 */ + uint64_t rx_pfc_ena_frames_pri6; + /* Total number of received PFC frames with PFC enabled bit for Pri 6 */ + uint64_t rx_pfc_ena_frames_pri7; + /* Total number of received PFC frames with PFC enabled bit for Pri 7 */ + uint64_t rx_sch_crc_err_frames; + /* Total Number of frames received with SCH CRC error */ + uint64_t rx_undrsz_frames; + /* Total Number of under-sized frames received */ + uint64_t rx_frag_frames; + /* Total Number of fragmented frames received */ + uint64_t rx_eee_lpi_events; + /* Total number of RX EEE LPI Events */ + uint64_t rx_eee_lpi_duration; + /* EEE LPI Duration Counter on RX */ + uint64_t rx_llfc_physical_msgs; + /* + * Total number of physical type Link Level Flow Control (LLFC) messages + * received + */ + uint64_t rx_llfc_logical_msgs; + /* + * Total number of logical type Link Level Flow Control (LLFC) messages + * received + */ + uint64_t rx_llfc_msgs_with_crc_err; + /* + * Total number of logical type Link Level Flow Control (LLFC) messages + * received with CRC error + */ + uint64_t rx_hcfc_msgs; + /* Total number of HCFC messages received */ + uint64_t rx_hcfc_msgs_with_crc_err; + /* Total number of HCFC messages received with CRC error */ + uint64_t rx_bytes; + /* Total number of received bytes */ + uint64_t rx_runt_bytes; + /* Total number of bytes received in runt frames */ + uint64_t rx_runt_frames; + /* Total number of runt frames received */ + uint64_t rx_stat_discard; + /* Total Rx Discards per Port reported by STATS block */ + uint64_t rx_stat_err; + /* Total Rx Error Drops per Port reported by STATS block */ +} __attribute__((packed)); + +/* hwrm_ver_get */ +/* + * Description: This function is called by a driver to determine the HWRM + * interface version supported by the HWRM firmware, the version of HWRM + * firmware implementation, the name of HWRM firmware, the versions of other + * embedded firmwares, and the names of other embedded firmwares, etc. Any + * interface or firmware version with major = 0, minor = 0, and update = 0 shall + * be considered an invalid version. + */ +/* Input (24 bytes) */ + +struct hwrm_ver_get_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t hwrm_intf_maj; + /* + * This field represents the major version of HWRM interface + * specification supported by the driver HWRM implementation. The + * interface major version is intended to change only when non backward + * compatible changes are made to the HWRM interface specification. + */ + uint8_t hwrm_intf_min; + /* + * This field represents the minor version of HWRM interface + * specification supported by the driver HWRM implementation. A change + * in interface minor version is used to reflect significant backward + * compatible modification to HWRM interface specification. This can be + * due to addition or removal of functionality. HWRM interface + * specifications with the same major version but different minor + * versions are compatible. + */ + uint8_t hwrm_intf_upd; + /* + * This field represents the update version of HWRM interface + * specification supported by the driver HWRM implementation. The + * interface update version is used to reflect minor changes or bug + * fixes to a released HWRM interface specification. + */ + uint8_t unused_0[5]; +} __attribute__((packed)); + +/* Output (128 bytes) */ + +struct hwrm_ver_get_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t hwrm_intf_maj; + /* + * This field represents the major version of HWRM interface + * specification supported by the HWRM implementation. The interface + * major version is intended to change only when non backward compatible + * changes are made to the HWRM interface specification. A HWRM + * implementation that is compliant with this specification shall + * provide value of 1 in this field. + */ + uint8_t hwrm_intf_min; + /* + * This field represents the minor version of HWRM interface + * specification supported by the HWRM implementation. A change in + * interface minor version is used to reflect significant backward + * compatible modification to HWRM interface specification. This can be + * due to addition or removal of functionality. HWRM interface + * specifications with the same major version but different minor + * versions are compatible. A HWRM implementation that is compliant with + * this specification shall provide value of 2 in this field. + */ + uint8_t hwrm_intf_upd; + /* + * This field represents the update version of HWRM interface + * specification supported by the HWRM implementation. The interface + * update version is used to reflect minor changes or bug fixes to a + * released HWRM interface specification. A HWRM implementation that is + * compliant with this specification shall provide value of 2 in this + * field. + */ + uint8_t hwrm_intf_rsvd; + uint8_t hwrm_fw_maj; + /* + * This field represents the major version of HWRM firmware. A change in + * firmware major version represents a major firmware release. + */ + uint8_t hwrm_fw_min; + /* + * This field represents the minor version of HWRM firmware. A change in + * firmware minor version represents significant firmware functionality + * changes. + */ + uint8_t hwrm_fw_bld; + /* + * This field represents the build version of HWRM firmware. A change in + * firmware build version represents bug fixes to a released firmware. + */ + uint8_t hwrm_fw_rsvd; + /* + * This field is a reserved field. This field can be used to represent + * firmware branches or customer specific releases tied to a specific + * (major,minor,update) version of the HWRM firmware. + */ + uint8_t mgmt_fw_maj; + /* + * This field represents the major version of mgmt firmware. A change in + * major version represents a major release. + */ + uint8_t mgmt_fw_min; + /* + * This field represents the minor version of mgmt firmware. A change in + * minor version represents significant functionality changes. + */ + uint8_t mgmt_fw_bld; + /* + * This field represents the build version of mgmt firmware. A change in + * update version represents bug fixes. + */ + uint8_t mgmt_fw_rsvd; + /* + * This field is a reserved field. This field can be used to represent + * firmware branches or customer specific releases tied to a specific + * (major,minor,update) version + */ + uint8_t netctrl_fw_maj; + /* + * This field represents the major version of network control firmware. + * A change in major version represents a major release. + */ + uint8_t netctrl_fw_min; + /* + * This field represents the minor version of network control firmware. + * A change in minor version represents significant functionality + * changes. + */ + uint8_t netctrl_fw_bld; + /* + * This field represents the build version of network control firmware. + * A change in update version represents bug fixes. + */ + uint8_t netctrl_fw_rsvd; + /* + * This field is a reserved field. This field can be used to represent + * firmware branches or customer specific releases tied to a specific + * (major,minor,update) version + */ + uint32_t reserved1; + /* + * This field is reserved for future use. The responder should set it to + * 0. The requester should ignore this field. + */ + uint8_t roce_fw_maj; + /* + * This field represents the major version of RoCE firmware. A change in + * major version represents a major release. + */ + uint8_t roce_fw_min; + /* + * This field represents the minor version of RoCE firmware. A change in + * minor version represents significant functionality changes. + */ + uint8_t roce_fw_bld; + /* + * This field represents the build version of RoCE firmware. A change in + * update version represents bug fixes. + */ + uint8_t roce_fw_rsvd; + /* + * This field is a reserved field. This field can be used to represent + * firmware branches or customer specific releases tied to a specific + * (major,minor,update) version + */ + char hwrm_fw_name[16]; + /* + * This field represents the name of HWRM FW (ASCII chars with NULL at + * the end). + */ + char mgmt_fw_name[16]; + /* + * This field represents the name of mgmt FW (ASCII chars with NULL at + * the end). + */ + char netctrl_fw_name[16]; + /* + * This field represents the name of network control firmware (ASCII + * chars with NULL at the end). + */ + uint32_t reserved2[4]; + /* + * This field is reserved for future use. The responder should set it to + * 0. The requester should ignore this field. + */ + char roce_fw_name[16]; + /* + * This field represents the name of RoCE FW (ASCII chars with NULL at + * the end). + */ + uint16_t chip_num; + /* This field returns the chip number. */ + uint8_t chip_rev; + /* This field returns the revision of chip. */ + uint8_t chip_metal; + /* This field returns the chip metal number. */ + uint8_t chip_bond_id; + /* This field returns the bond id of the chip. */ + uint8_t chip_platform_type; + /* + * This value indicates the type of platform used for chip + * implementation. + */ + /* ASIC */ + #define HWRM_VER_GET_OUTPUT_CHIP_PLATFORM_TYPE_ASIC UINT32_C(0x0) + /* FPGA platform of the chip. */ + #define HWRM_VER_GET_OUTPUT_CHIP_PLATFORM_TYPE_FPGA UINT32_C(0x1) + /* Palladium platform of the chip. */ + #define HWRM_VER_GET_OUTPUT_CHIP_PLATFORM_TYPE_PALLADIUM UINT32_C(0x2) + uint16_t max_req_win_len; + /* + * This field returns the maximum value of request window that is + * supported by the HWRM. The request window is mapped into device + * address space using MMIO. + */ + uint16_t max_resp_len; + /* This field returns the maximum value of response buffer in bytes. */ + uint16_t def_req_timeout; + /* This field returns the default request timeout value in milliseconds. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_reset */ +/* + * Description: This command resets a hardware function (PCIe function) and + * frees any resources used by the function. This command shall be initiated by + * the driver after an FLR has occurred to prepare the function for re-use. This + * command may also be initiated by a driver prior to doing it's own + * configuration. This command puts the function into the reset state. In the + * reset state, global and port related features of the chip are not available. + */ +/* + * Note: This command will reset a function that has already been disabled or + * idled. The command returns all the resources owned by the function so a new + * driver may allocate and configure resources normally. + */ +/* Input (24 bytes) */ + +struct hwrm_func_reset_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the vf_id_valid field to be configured. */ + #define HWRM_FUNC_RESET_INPUT_ENABLES_VF_ID_VALID UINT32_C(0x1) + uint16_t vf_id; + /* + * The ID of the VF that this PF is trying to reset. Only the parent PF + * shall be allowed to reset a child VF. A parent PF driver shall use + * this field only when a specific child VF is requested to be reset. + */ + uint8_t func_reset_level; + /* This value indicates the level of a function reset. */ + /* + * Reset the caller function and its children VFs (if any). If + * no children functions exist, then reset the caller function + * only. + */ + #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETALL UINT32_C(0x0) + /* Reset the caller function only */ + #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETME UINT32_C(0x1) + /* + * Reset all children VFs of the caller function driver if the + * caller is a PF driver. It is an error to specify this level + * by a VF driver. It is an error to specify this level by a PF + * driver with no children VFs. + */ + #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETCHILDREN UINT32_C(0x2) + /* + * Reset a specific VF of the caller function driver if the + * caller is the parent PF driver. It is an error to specify + * this level by a VF driver. It is an error to specify this + * level by a PF driver that is not the parent of the VF that is + * being requested to reset. + */ + #define HWRM_FUNC_RESET_INPUT_FUNC_RESET_LEVEL_RESETVF UINT32_C(0x3) + uint8_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_reset_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_getfid */ +/* + * Description: This command returns the FID value for the function. If a valid + * pci_id is provided, then this function returns fid for that PCI function. + * Otherwise, it returns FID of the requesting function. This value is needed to + * configure Rings and MSI-X vectors so their DMA operations appear correctly on + * the PCI bus. For PF-HWRM commands, there is no need for FID. Similarly there + * is no need for FID for VF-HWRM commands. In the PF-VF communication, only PF + * needs to know FIDs. + */ +/* Input (24 bytes) */ + +struct hwrm_func_getfid_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the pci_id field to be configured. */ + #define HWRM_FUNC_GETFID_INPUT_ENABLES_PCI_ID UINT32_C(0x1) + uint16_t pci_id; + /* + * This value is the PCI ID of the queried function. If ARI is enabled, + * then it is Bus Number (8b):Function Number(8b). Otherwise, it is Bus + * Number (8b):Device Number (4b):Function Number(4b). + */ + uint16_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_getfid_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t fid; + /* + * FID value. This value is used to identify operations on the PCI bus + * as belonging to a particular PCI function. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_vf_alloc */ +/* + * Description: This command is used to allocate requested number of virtual + * functions on a physical function. It will return the FID value of the first + * virtual function. The FIDs of the remaining virtual functions can be derived + * by sequentially incrementing the FID value of the first VF. This command + * supports the following models for VF allocation: # Allocation of one or more + * VFs from a PF without specifying the first VF ID # Allocation of multiple VFs + * from a PF starting with a specific VF # Allocation of a specific VF from a PF + * If this command is called on a virtual function or a physical function that + * is not enabled for SR-IOV, the HWRM shall return an error. The VF IDs + * returned by this function remain valid after the VF is disabled or reset. + */ +/* Input (24 bytes) */ + +struct hwrm_func_vf_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the first_vf_id field to be configured. */ + #define HWRM_FUNC_VF_ALLOC_INPUT_ENABLES_FIRST_VF_ID UINT32_C(0x1) + uint16_t first_vf_id; + /* + * This value is used to identify a Virtual Function (VF). The scope of + * VF ID is local within a PF. + */ + uint16_t num_vfs; + /* The number of virtual functions requested. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_vf_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t first_vf_id; + /* The ID of the first VF allocated. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_vf_free */ +/* + * Description: This command will free allocated virtual functions on a physical + * function. If this command is called on a virtual function or a physical + * function that is not enabled for SR-IOV, the HWRM shall return an error. + * After the successful completion of this command, the VF IDs of the VFs that + * are freed on the PF are invalid. + */ +/* Input (24 bytes) */ + +struct hwrm_func_vf_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the first_vf_id field to be configured. */ + #define HWRM_FUNC_VF_FREE_INPUT_ENABLES_FIRST_VF_ID UINT32_C(0x1) + uint16_t first_vf_id; + /* + * This value is used to identify a Virtual Function (VF). The scope of + * VF ID is local within a PF. + */ + uint16_t num_vfs; + /* + * The number of virtual functions requested. 0xFFFF - Cleanup all + * children of this PF. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_vf_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_vf_cfg */ +/* + * Description: This command allows configuration of a VF by its driver. If this + * function is called by a PF driver, then the HWRM shall fail this command. If + * guest VLAN and/or MAC address are provided in this command, then the HWRM + * shall set up appropriate MAC/VLAN filters for the VF that is being + * configured. A VF driver should set VF MTU/MRU using this command prior to + * allocating RX VNICs or TX rings for the corresponding VF. + */ +/* Input (32 bytes) */ + +struct hwrm_func_vf_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the mtu field to be configured. */ + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_MTU UINT32_C(0x1) + /* This bit must be '1' for the guest_vlan field to be configured. */ + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_GUEST_VLAN UINT32_C(0x2) + /* This bit must be '1' for the async_event_cr field to be configured. */ + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR UINT32_C(0x4) + /* This bit must be '1' for the dflt_mac_addr field to be configured. */ + #define HWRM_FUNC_VF_CFG_INPUT_ENABLES_DFLT_MAC_ADDR UINT32_C(0x8) + uint16_t mtu; + /* + * The maximum transmission unit requested on the function. The HWRM + * should make sure that the mtu of the function does not exceed the mtu + * of the physical port that this function is associated with. In + * addition to requesting mtu per function, it is possible to configure + * mtu per transmit ring. By default, the mtu of each transmit ring + * associated with a function is equal to the mtu of the function. The + * HWRM should make sure that the mtu of each transmit ring that is + * assigned to a function has a valid mtu. + */ + uint16_t guest_vlan; + /* + * The guest VLAN for the function being configured. This field's format + * is same as 802.1Q Tag's Tag Control Information (TCI) format that + * includes both Priority Code Point (PCP) and VLAN Identifier (VID). + */ + uint16_t async_event_cr; + /* + * ID of the target completion ring for receiving asynchronous event + * completions. If this field is not valid, then the HWRM shall use the + * default completion ring of the function that is being configured as + * the target completion ring for providing any asynchronous event + * completions for that function. If this field is valid, then the HWRM + * shall use the completion ring identified by this ID as the target + * completion ring for providing any asynchronous event completions for + * the function that is being configured. + */ + uint8_t dflt_mac_addr[6]; + /* + * This value is the current MAC address requested by the VF driver to + * be configured on this VF. A value of 00-00-00-00-00-00 indicates no + * MAC address configuration is requested by the VF driver. The parent + * PF driver may reject or overwrite this MAC address. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_vf_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_qcaps */ +/* + * Description: This command returns capabilities of a function. The input FID + * value is used to indicate what function is being queried. This allows a + * physical function driver to query virtual functions that are children of the + * physical function. The output FID value is needed to configure Rings and + * MSI-X vectors so their DMA operations appear correctly on the PCI bus. + */ +/* Input (24 bytes) */ + +struct hwrm_func_qcaps_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t fid; + /* + * Function ID of the function that is being queried. 0xFF... (All Fs) + * if the query is for the requesting function. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (80 bytes) */ + +struct hwrm_func_qcaps_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t fid; + /* + * FID value. This value is used to identify operations on the PCI bus + * as belonging to a particular PCI function. + */ + uint16_t port_id; + /* + * Port ID of port that this function is associated with. Valid only for + * the PF. 0xFF... (All Fs) if this function is not associated with any + * port. 0xFF... (All Fs) if this function is called from a VF. + */ + uint32_t flags; + /* If 1, then Push mode is supported on this function. */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PUSH_MODE_SUPPORTED UINT32_C(0x1) + /* If 1, then the global MSI-X auto-masking is enabled for the device. */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_GLOBAL_MSIX_AUTOMASKING UINT32_C(0x2) + /* + * If 1, then the Precision Time Protocol (PTP) processing is supported + * on this function. The HWRM should enable PTP on only a single + * Physical Function (PF) per port. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PTP_SUPPORTED UINT32_C(0x4) + /* + * If 1, then RDMA over Converged Ethernet (RoCE) v1 is supported on + * this function. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V1_SUPPORTED UINT32_C(0x8) + /* + * If 1, then RDMA over Converged Ethernet (RoCE) v2 is supported on + * this function. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ROCE_V2_SUPPORTED UINT32_C(0x10) + /* + * If 1, then control and configuration of WoL magic packet is supported + * on this function. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED UINT32_C(0x20) + /* + * If 1, then control and configuration of bitmap pattern packet is + * supported on this function. + */ + #define HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_BMP_SUPPORTED UINT32_C(0x40) + uint8_t mac_address[6]; + /* + * This value is current MAC address configured for this function. A + * value of 00-00-00-00-00-00 indicates no MAC address is currently + * configured. + */ + uint16_t max_rsscos_ctx; + /* + * The maximum number of RSS/COS contexts that can be allocated to the + * function. + */ + uint16_t max_cmpl_rings; + /* + * The maximum number of completion rings that can be allocated to the + * function. + */ + uint16_t max_tx_rings; + /* + * The maximum number of transmit rings that can be allocated to the + * function. + */ + uint16_t max_rx_rings; + /* + * The maximum number of receive rings that can be allocated to the + * function. + */ + uint16_t max_l2_ctxs; + /* + * The maximum number of L2 contexts that can be allocated to the + * function. + */ + uint16_t max_vnics; + /* The maximum number of VNICs that can be allocated to the function. */ + uint16_t first_vf_id; + /* + * The identifier for the first VF enabled on a PF. This is valid only + * on the PF with SR-IOV enabled. 0xFF... (All Fs) if this command is + * called on a PF with SR-IOV disabled or on a VF. + */ + uint16_t max_vfs; + /* + * The maximum number of VFs that can be allocated to the function. This + * is valid only on the PF with SR-IOV enabled. 0xFF... (All Fs) if this + * command is called on a PF with SR-IOV disabled or on a VF. + */ + uint16_t max_stat_ctx; + /* + * The maximum number of statistic contexts that can be allocated to the + * function. + */ + uint32_t max_encap_records; + /* + * The maximum number of Encapsulation records that can be offloaded by + * this function. + */ + uint32_t max_decap_records; + /* + * The maximum number of decapsulation records that can be offloaded by + * this function. + */ + uint32_t max_tx_em_flows; + /* + * The maximum number of Exact Match (EM) flows that can be offloaded by + * this function on the TX side. + */ + uint32_t max_tx_wm_flows; + /* + * The maximum number of Wildcard Match (WM) flows that can be offloaded + * by this function on the TX side. + */ + uint32_t max_rx_em_flows; + /* + * The maximum number of Exact Match (EM) flows that can be offloaded by + * this function on the RX side. + */ + uint32_t max_rx_wm_flows; + /* + * The maximum number of Wildcard Match (WM) flows that can be offloaded + * by this function on the RX side. + */ + uint32_t max_mcast_filters; + /* + * The maximum number of multicast filters that can be supported by this + * function on the RX side. + */ + uint32_t max_flow_id; + /* + * The maximum value of flow_id that can be supported in completion + * records. + */ + uint32_t max_hw_ring_grps; + /* + * The maximum number of HW ring groups that can be supported on this + * function. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_qcfg */ +/* + * Description: This command returns the current configuration of a function. + * The input FID value is used to indicate what function is being queried. This + * allows a physical function driver to query virtual functions that are + * children of the physical function. The output FID value is needed to + * configure Rings and MSI-X vectors so their DMA operations appear correctly on + * the PCI bus. + */ +/* Input (24 bytes) */ + +struct hwrm_func_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t fid; + /* + * Function ID of the function that is being queried. 0xFF... (All Fs) + * if the query is for the requesting function. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (72 bytes) */ + +struct hwrm_func_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t fid; + /* + * FID value. This value is used to identify operations on the PCI bus + * as belonging to a particular PCI function. + */ + uint16_t port_id; + /* + * Port ID of port that this function is associated with. 0xFF... (All + * Fs) if this function is not associated with any port. + */ + uint16_t vlan; + /* + * This value is the current VLAN setting for this function. The value + * of 0 for this field indicates no priority tagging or VLAN is used. + * This field's format is same as 802.1Q Tag's Tag Control Information + * (TCI) format that includes both Priority Code Point (PCP) and VLAN + * Identifier (VID). + */ + uint16_t flags; + /* + * If 1, then magic packet based Out-Of-Box WoL is enabled on the port + * associated with this function. + */ + #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_OOB_WOL_MAGICPKT_ENABLED UINT32_C(0x1) + /* + * If 1, then bitmap pattern based Out-Of-Box WoL packet is enabled on + * the port associated with this function. + */ + #define HWRM_FUNC_QCFG_OUTPUT_FLAGS_OOB_WOL_BMP_ENABLED UINT32_C(0x2) + uint8_t mac_address[6]; + /* + * This value is current MAC address configured for this function. A + * value of 00-00-00-00-00-00 indicates no MAC address is currently + * configured. + */ + uint16_t pci_id; + /* + * This value is current PCI ID of this function. If ARI is enabled, + * then it is Bus Number (8b):Function Number(8b). Otherwise, it is Bus + * Number (8b):Device Number (4b):Function Number(4b). + */ + uint16_t alloc_rsscos_ctx; + /* The number of RSS/COS contexts currently allocated to the function. */ + uint16_t alloc_cmpl_rings; + /* + * The number of completion rings currently allocated to the function. + * This does not include the rings allocated to any children functions + * if any. + */ + uint16_t alloc_tx_rings; + /* + * The number of transmit rings currently allocated to the function. + * This does not include the rings allocated to any children functions + * if any. + */ + uint16_t alloc_rx_rings; + /* + * The number of receive rings currently allocated to the function. This + * does not include the rings allocated to any children functions if + * any. + */ + uint16_t alloc_l2_ctx; + /* The allocated number of L2 contexts to the function. */ + uint16_t alloc_vnics; + /* The allocated number of vnics to the function. */ + uint16_t mtu; + /* + * The maximum transmission unit of the function. For rings allocated on + * this function, this default value is used if ring MTU is not + * specified. + */ + uint16_t mru; + /* + * The maximum receive unit of the function. For vnics allocated on this + * function, this default value is used if vnic MRU is not specified. + */ + uint16_t stat_ctx_id; + /* The statistics context assigned to a function. */ + uint8_t port_partition_type; + /* + * The HWRM shall return Unknown value for this field when this command + * is used to query VF's configuration. + */ + /* Single physical function */ + #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_SPF UINT32_C(0x0) + /* Multiple physical functions */ + #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_MPFS UINT32_C(0x1) + /* Network Partitioning 1.0 */ + #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_0 UINT32_C(0x2) + /* Network Partitioning 1.5 */ + #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_5 UINT32_C(0x3) + /* Network Partitioning 2.0 */ + #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR2_0 UINT32_C(0x4) + /* Unknown */ + #define HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_UNKNOWN UINT32_C(0xff) + uint8_t unused_0; + uint16_t dflt_vnic_id; + /* The default VNIC ID assigned to a function that is being queried. */ + uint8_t unused_1; + uint8_t unused_2; + uint32_t min_bw; + /* + * Minimum BW allocated for this function in Mbps. The HWRM will + * translate this value into byte counter and time interval used for the + * scheduler inside the device. A value of 0 indicates the minimum + * bandwidth is not configured. + */ + uint32_t max_bw; + /* + * Maximum BW allocated for this function in Mbps. The HWRM will + * translate this value into byte counter and time interval used for the + * scheduler inside the device. A value of 0 indicates that the maximum + * bandwidth is not configured. + */ + uint8_t evb_mode; + /* + * This value indicates the Edge virtual bridge mode for the domain that + * this function belongs to. + */ + /* No Edge Virtual Bridging (EVB) */ + #define HWRM_FUNC_QCFG_OUTPUT_EVB_MODE_NO_EVB UINT32_C(0x0) + /* Virtual Ethernet Bridge (VEB) */ + #define HWRM_FUNC_QCFG_OUTPUT_EVB_MODE_VEB UINT32_C(0x1) + /* Virtual Ethernet Port Aggregator (VEPA) */ + #define HWRM_FUNC_QCFG_OUTPUT_EVB_MODE_VEPA UINT32_C(0x2) + uint8_t unused_3; + uint16_t unused_4; + uint32_t alloc_mcast_filters; + /* + * The number of allocated multicast filters for this function on the RX + * side. + */ + uint32_t alloc_hw_ring_grps; + /* The number of allocated HW ring groups for this function. */ + uint8_t unused_5; + uint8_t unused_6; + uint8_t unused_7; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_cfg */ +/* + * Description: This command allows configuration of a PF by the corresponding + * PF driver. This command also allows configuration of a child VF by its parent + * PF driver. The input FID value is used to indicate what function is being + * configured. This allows a PF driver to configure the PF owned by itself or a + * virtual function that is a child of the PF. This command allows to reserve + * resources for a VF by its parent PF. To reverse the process, the command + * should be called with all enables flags cleared for resources. This will free + * allocated resources for the VF and return them to the resource pool. If this + * command is requested by a VF driver to configure or reserve resources, then + * the HWRM shall fail this command. If default MAC address and/or VLAN are + * provided in this command, then the HWRM shall set up appropriate MAC/VLAN + * filters for the function that is being configured. If source properties + * checks are enabled and default MAC address and/or IP address are provided in + * this command, then the HWRM shall set appropriate source property checks + * based on provided MAC and/or IP addresses. The parent PF driver should not + * set MTU/MRU for a VF using this command. This is to allow MTU/MRU setting by + * the VF driver. If the MTU or MRU for a VF is set by the PF driver, then the + * HWRM should ignore it. A function's MTU/MRU should be set prior to allocating + * RX VNICs or TX rings. + */ +/* Input (88 bytes) */ + +struct hwrm_func_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t fid; + /* + * Function ID of the function that is being configured. If set to + * 0xFF... (All Fs), then the the configuration is for the requesting + * function. + */ + uint8_t unused_0; + uint8_t unused_1; + uint32_t flags; + /* + * When this bit is '1', the function is requested to be put in the + * promiscuous mode. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_PROM_MODE UINT32_C(0x1) + /* + * When this bit is '1', the function is enabled with source MAC address + * check. This is an anti-spoofing check. If this flag is set, then the + * function shall be configured to allow transmission of frames with the + * source MAC address that is configured for this function. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_SRC_MAC_ADDR_CHECK UINT32_C(0x2) + /* + * When this bit is '1', the function is enabled with source IP address + * check. This is an anti-spoofing check. If this flag is set, then the + * function shall be configured to allow transmission of frames with the + * source IP address that is configured for this function. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_SRC_IP_ADDR_CHECK UINT32_C(0x4) + /* + * When this bit is set to '1', the function shall be configured with + * VLAN priority match. If the VLAN PRI of a packet originated from this + * function does not match, then the packet shall be discarded. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_VLAN_PRI_MATCH UINT32_C(0x8) + /* + * When this bit is set to '1', the function shall be configured to + * check for VLAN priority match. If the VLAN PRI of a packet originated + * from this function does not match, then the default VLAN PRI shall be + * used. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_DFLT_PRI_NOMATCH UINT32_C(0x10) + /* + * When this bit is set to '1', the function shall be configured to not + * allow the transmission of pause frames. PAUSE frames use 48-bit + * destination multicast MAC address 01-80-C2-00-00-01. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_PAUSE UINT32_C(0x20) + /* + * When this bit is set to '1', the function shall be configured to not + * allow the transmission of Spanning Tree Protocol (STP) frames. STP + * frames use Ethertype 0x0802 and 48-bit destination multicast MAC + * address 01-80-C2-00-00-00 and 01-80-C2-00-00-08 for 802.1D and + * 802.1ad respectively. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_STP UINT32_C(0x40) + /* + * When this bit is set to '1', the function shall be configured to not + * allow the transmission of Link Layer Discovery Protocol (LLDP) + * frames. LLDP frames use Ethertype 0x88CC and 48-bit destination + * multicast MAC address 01-80-C2-00-00-00 or 01-80-C2-00-00-03 or + * 01-80-C2-00-00-0E. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_LLDP UINT32_C(0x80) + /* + * When this bit is set to '1', the function shall be configured to not + * allow the transmission of Precision Time Protocol (PTP) v2 frames. + * PTP frames use Ethertype 0x88F7 and 48-bit destination multicast MAC + * address 01-80-C2-00-00-0E or 01-1B-19-00-00-00. + */ + #define HWRM_FUNC_CFG_INPUT_FLAGS_DISABLE_PTPV2 UINT32_C(0x100) + uint32_t enables; + /* This bit must be '1' for the mtu field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_MTU UINT32_C(0x1) + /* This bit must be '1' for the mru field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_MRU UINT32_C(0x2) + /* This bit must be '1' for the num_rsscos_ctxs field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS UINT32_C(0x4) + /* This bit must be '1' for the num_cmpl_rings field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS UINT32_C(0x8) + /* This bit must be '1' for the num_tx_rings field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS UINT32_C(0x10) + /* This bit must be '1' for the num_rx_rings field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS UINT32_C(0x20) + /* This bit must be '1' for the num_l2_ctxs field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_L2_CTXS UINT32_C(0x40) + /* This bit must be '1' for the num_vnics field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS UINT32_C(0x80) + /* This bit must be '1' for the num_stat_ctxs field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS UINT32_C(0x100) + /* This bit must be '1' for the dflt_mac_addr field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_DFLT_MAC_ADDR UINT32_C(0x200) + /* This bit must be '1' for the dflt_vlan field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_DFLT_VLAN UINT32_C(0x400) + /* This bit must be '1' for the dflt_ip_addr field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_DFLT_IP_ADDR UINT32_C(0x800) + /* This bit must be '1' for the min_bw field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_MIN_BW UINT32_C(0x1000) + /* This bit must be '1' for the max_bw field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_MAX_BW UINT32_C(0x2000) + /* This bit must be '1' for the async_event_cr field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR UINT32_C(0x4000) + /* + * This bit must be '1' for the vlan_antispoof_mode field to be + * configured. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_VLAN_ANTISPOOF_MODE UINT32_C(0x8000) + /* + * This bit must be '1' for the allowed_vlan_pris field to be + * configured. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_ALLOWED_VLAN_PRIS UINT32_C(0x10000) + /* This bit must be '1' for the evb_mode field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_EVB_MODE UINT32_C(0x20000) + /* + * This bit must be '1' for the num_mcast_filters field to be + * configured. + */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MCAST_FILTERS UINT32_C(0x40000) + /* This bit must be '1' for the num_hw_ring_grps field to be configured. */ + #define HWRM_FUNC_CFG_INPUT_ENABLES_NUM_HW_RING_GRPS UINT32_C(0x80000) + uint16_t mtu; + /* + * The maximum transmission unit of the function. The HWRM should make + * sure that the mtu of the function does not exceed the mtu of the + * physical port that this function is associated with. In addition to + * configuring mtu per function, it is possible to configure mtu per + * transmit ring. By default, the mtu of each transmit ring associated + * with a function is equal to the mtu of the function. The HWRM should + * make sure that the mtu of each transmit ring that is assigned to a + * function has a valid mtu. + */ + uint16_t mru; + /* + * The maximum receive unit of the function. The HWRM should make sure + * that the mru of the function does not exceed the mru of the physical + * port that this function is associated with. In addition to + * configuring mru per function, it is possible to configure mru per + * vnic. By default, the mru of each vnic associated with a function is + * equal to the mru of the function. The HWRM should make sure that the + * mru of each vnic that is assigned to a function has a valid mru. + */ + uint16_t num_rsscos_ctxs; + /* The number of RSS/COS contexts requested for the function. */ + uint16_t num_cmpl_rings; + /* + * The number of completion rings requested for the function. This does + * not include the rings allocated to any children functions if any. + */ + uint16_t num_tx_rings; + /* + * The number of transmit rings requested for the function. This does + * not include the rings allocated to any children functions if any. + */ + uint16_t num_rx_rings; + /* + * The number of receive rings requested for the function. This does not + * include the rings allocated to any children functions if any. + */ + uint16_t num_l2_ctxs; + /* The requested number of L2 contexts for the function. */ + uint16_t num_vnics; + /* The requested number of vnics for the function. */ + uint16_t num_stat_ctxs; + /* The requested number of statistic contexts for the function. */ + uint16_t num_hw_ring_grps; + /* + * The number of HW ring groups that should be reserved for this + * function. + */ + uint8_t dflt_mac_addr[6]; + /* The default MAC address for the function being configured. */ + uint16_t dflt_vlan; + /* + * The default VLAN for the function being configured. This field's + * format is same as 802.1Q Tag's Tag Control Information (TCI) format + * that includes both Priority Code Point (PCP) and VLAN Identifier + * (VID). + */ + uint32_t dflt_ip_addr[4]; /* big endian */ + /* + * The default IP address for the function being configured. This + * address is only used in enabling source property check. + */ + uint32_t min_bw; + /* + * Minimum BW allocated for this function in Mbps. The HWRM will + * translate this value into byte counter and time interval used for the + * scheduler inside the device. + */ + uint32_t max_bw; + /* + * Maximum BW allocated for this function in Mbps. The HWRM will + * translate this value into byte counter and time interval used for the + * scheduler inside the device. + */ + uint16_t async_event_cr; + /* + * ID of the target completion ring for receiving asynchronous event + * completions. If this field is not valid, then the HWRM shall use the + * default completion ring of the function that is being configured as + * the target completion ring for providing any asynchronous event + * completions for that function. If this field is valid, then the HWRM + * shall use the completion ring identified by this ID as the target + * completion ring for providing any asynchronous event completions for + * the function that is being configured. + */ + uint8_t vlan_antispoof_mode; + /* VLAN Anti-spoofing mode. */ + /* No VLAN anti-spoofing checks are enabled */ + #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_NOCHECK UINT32_C(0x0) + /* Validate VLAN against the configured VLAN(s) */ + #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_VALIDATE_VLAN UINT32_C(0x1) + /* Insert VLAN if it does not exist, otherwise discard */ + #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_INSERT_IF_VLANDNE UINT32_C(0x2) + /* Insert VLAN if it does not exist, override VLAN if it exists */ + #define HWRM_FUNC_CFG_INPUT_VLAN_ANTISPOOF_MODE_INSERT_OR_OVERRIDE_VLAN UINT32_C(0x3) + uint8_t allowed_vlan_pris; + /* + * This bit field defines VLAN PRIs that are allowed on this function. + * If nth bit is set, then VLAN PRI n is allowed on this function. + */ + uint8_t evb_mode; + /* + * The HWRM shall allow a PF driver to change EVB mode for the partition + * it belongs to. The HWRM shall not allow a VF driver to change the EVB + * mode. The HWRM shall take into account the switching of EVB mode from + * one to another and reconfigure hardware resources as appropriately. + * The switching from VEB to VEPA mode requires the disabling of the + * loopback traffic. Additionally, source knock outs are handled + * differently in VEB and VEPA modes. + */ + /* No Edge Virtual Bridging (EVB) */ + #define HWRM_FUNC_CFG_INPUT_EVB_MODE_NO_EVB UINT32_C(0x0) + /* Virtual Ethernet Bridge (VEB) */ + #define HWRM_FUNC_CFG_INPUT_EVB_MODE_VEB UINT32_C(0x1) + /* Virtual Ethernet Port Aggregator (VEPA) */ + #define HWRM_FUNC_CFG_INPUT_EVB_MODE_VEPA UINT32_C(0x2) + uint8_t unused_2; + uint16_t num_mcast_filters; + /* + * The number of multicast filters that should be reserved for this + * function on the RX side. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_qstats */ +/* + * Description: This command returns statistics of a function. The input FID + * value is used to indicate what function is being queried. This allows a + * physical function driver to query virtual functions that are children of the + * physical function. The HWRM shall return any unsupported counter with a value + * of 0xFFFFFFFF for 32-bit counters and 0xFFFFFFFFFFFFFFFF for 64-bit counters. + */ +/* Input (24 bytes) */ + +struct hwrm_func_qstats_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t fid; + /* + * Function ID of the function that is being queried. 0xFF... (All Fs) + * if the query is for the requesting function. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (176 bytes) */ + +struct hwrm_func_qstats_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t tx_ucast_pkts; + /* Number of transmitted unicast packets on the function. */ + uint64_t tx_mcast_pkts; + /* Number of transmitted multicast packets on the function. */ + uint64_t tx_bcast_pkts; + /* Number of transmitted broadcast packets on the function. */ + uint64_t tx_err_pkts; + /* + * Number of transmitted packets that were dropped due to internal NIC + * resource problems. For transmit, this can only happen if TMP is + * configured to allow dropping in HOL blocking conditions, which is not + * a normal configuration. + */ + uint64_t tx_drop_pkts; + /* + * Number of dropped packets on transmit path on the function. These are + * packets that have been marked for drop by the TE CFA block or are + * packets that exceeded the transmit MTU limit for the function. + */ + uint64_t tx_ucast_bytes; + /* Number of transmitted bytes for unicast traffic on the function. */ + uint64_t tx_mcast_bytes; + /* Number of transmitted bytes for multicast traffic on the function. */ + uint64_t tx_bcast_bytes; + /* Number of transmitted bytes for broadcast traffic on the function. */ + uint64_t rx_ucast_pkts; + /* Number of received unicast packets on the function. */ + uint64_t rx_mcast_pkts; + /* Number of received multicast packets on the function. */ + uint64_t rx_bcast_pkts; + /* Number of received broadcast packets on the function. */ + uint64_t rx_err_pkts; + /* + * Number of received packets that were dropped on the function due to + * resource limitations. This can happen for 3 reasons. # The BD used + * for the packet has a bad format. # There were no BDs available in the + * ring for the packet. # There were no BDs available on-chip for the + * packet. + */ + uint64_t rx_drop_pkts; + /* + * Number of dropped packets on received path on the function. These are + * packets that have been marked for drop by the RE CFA. + */ + uint64_t rx_ucast_bytes; + /* Number of received bytes for unicast traffic on the function. */ + uint64_t rx_mcast_bytes; + /* Number of received bytes for multicast traffic on the function. */ + uint64_t rx_bcast_bytes; + /* Number of received bytes for broadcast traffic on the function. */ + uint64_t rx_agg_pkts; + /* Number of aggregated unicast packets on the function. */ + uint64_t rx_agg_bytes; + /* Number of aggregated unicast bytes on the function. */ + uint64_t rx_agg_events; + /* Number of aggregation events on the function. */ + uint64_t rx_agg_aborts; + /* Number of aborted aggregations on the function. */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_clr_stats */ +/* + * Description: This command clears statistics of a function. The input FID + * value is used to indicate what function's statistics is being cleared. This + * allows a physical function driver to clear statistics of virtual functions + * that are children of the physical function. + */ +/* Input (24 bytes) */ + +struct hwrm_func_clr_stats_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t fid; + /* + * Function ID of the function. 0xFF... (All Fs) if the query is for the + * requesting function. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_clr_stats_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_vf_resc_free */ +/* Description: This command frees resources of a vf. */ +/* Input (24 bytes) */ + +struct hwrm_func_vf_resc_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t vf_id; + /* + * This value is used to identify a Virtual Function (VF). The scope of + * VF ID is local within a PF. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_vf_resc_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_vf_vnic_ids_query */ +/* Description: This command is used to query vf vnic ids. */ +/* Input (32 bytes) */ + +struct hwrm_func_vf_vnic_ids_query_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t vf_id; + /* + * This value is used to identify a Virtual Function (VF). The scope of + * VF ID is local within a PF. + */ + uint8_t unused_0; + uint8_t unused_1; + uint32_t max_vnic_id_cnt; + /* Max number of vnic ids in vnic id table */ + uint64_t vnic_id_tbl_addr; + /* This is the address for VF VNIC ID table */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_vf_vnic_ids_query_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t vnic_id_cnt; + /* Actual number of vnic ids Each VNIC ID is written as a 32-bit number. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_drv_rgtr */ +/* + * Description: This command is used by the function driver to register its + * information with the HWRM. A function driver shall implement this command. A + * function driver shall use this command during the driver initialization right + * after the HWRM version discovery and default ring resources allocation. + */ +/* Input (80 bytes) */ + +struct hwrm_func_drv_rgtr_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is '1', the function driver is requesting all requests + * from its children VF drivers to be forwarded to itself. This flag can + * only be set by the PF driver. If a VF driver sets this flag, it + * should be ignored by the HWRM. + */ + #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_ALL_MODE UINT32_C(0x1) + /* + * When this bit is '1', the function is requesting none of the requests + * from its children VF drivers to be forwarded to itself. This flag can + * only be set by the PF driver. If a VF driver sets this flag, it + * should be ignored by the HWRM. + */ + #define HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_NONE_MODE UINT32_C(0x2) + uint32_t enables; + /* This bit must be '1' for the os_type field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE UINT32_C(0x1) + /* This bit must be '1' for the ver field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER UINT32_C(0x2) + /* This bit must be '1' for the timestamp field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_TIMESTAMP UINT32_C(0x4) + /* This bit must be '1' for the vf_req_fwd field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VF_REQ_FWD UINT32_C(0x8) + /* This bit must be '1' for the async_event_fwd field to be configured. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD UINT32_C(0x10) + uint16_t os_type; + /* This value indicates the type of OS. */ + /* Unknown */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_UNKNOWN UINT32_C(0x0) + /* Other OS not listed below. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_OTHER UINT32_C(0x1) + /* MSDOS OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_MSDOS UINT32_C(0xe) + /* Windows OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WINDOWS UINT32_C(0x12) + /* Solaris OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_SOLARIS UINT32_C(0x1d) + /* Linux OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_LINUX UINT32_C(0x24) + /* FreeBSD OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD UINT32_C(0x2a) + /* VMware ESXi OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_ESXI UINT32_C(0x68) + /* Microsoft Windows 8 64-bit OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WIN864 UINT32_C(0x73) + /* Microsoft Windows Server 2012 R2 OS. */ + #define HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_WIN2012R2 UINT32_C(0x74) + uint8_t ver_maj; + /* This is the major version of the driver. */ + uint8_t ver_min; + /* This is the minor version of the driver. */ + uint8_t ver_upd; + /* This is the update version of the driver. */ + uint8_t unused_0; + uint16_t unused_1; + uint32_t timestamp; + /* + * This is a 32-bit timestamp provided by the driver for keep alive. The + * timestamp is in multiples of 1ms. + */ + uint32_t unused_2; + uint32_t vf_req_fwd[8]; + /* + * This is a 256-bit bit mask provided by the PF driver for letting the + * HWRM know what commands issued by the VF driver to the HWRM should be + * forwarded to the PF driver. Nth bit refers to the Nth req_type. + * Setting Nth bit to 1 indicates that requests from the VF driver with + * req_type equal to N shall be forwarded to the parent PF driver. This + * field is not valid for the VF driver. + */ + uint32_t async_event_fwd[8]; + /* + * This is a 256-bit bit mask provided by the function driver (PF or VF + * driver) to indicate the list of asynchronous event completions to be + * forwarded. Nth bit refers to the Nth event_id. Setting Nth bit to 1 + * by the function driver shall result in the HWRM forwarding + * asynchronous event completion with event_id equal to N. If all bits + * are set to 0 (value of 0), then the HWRM shall not forward any + * asynchronous event completion to this function driver. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_drv_rgtr_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_drv_unrgtr */ +/* + * Description: This command is used by the function driver to un register with + * the HWRM. A function driver shall implement this command. A function driver + * shall use this command during the driver unloading. + */ +/* Input (24 bytes) */ + +struct hwrm_func_drv_unrgtr_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is '1', the function driver is notifying the HWRM to + * prepare for the shutdown. + */ + #define HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN UINT32_C(0x1) + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_drv_unrgtr_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_buf_rgtr */ +/* + * Description: This command is used by the PF driver to register buffers used + * in the PF-VF communication with the HWRM. The PF driver uses this command to + * register buffers for each PF-VF channel. A parent PF may issue this command + * per child VF. If VF ID is not valid, then this command is used to register + * buffers for all children VFs of the PF. + */ +/* Input (128 bytes) */ + +struct hwrm_func_buf_rgtr_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the vf_id field to be configured. */ + #define HWRM_FUNC_BUF_RGTR_INPUT_ENABLES_VF_ID UINT32_C(0x1) + /* This bit must be '1' for the err_buf_addr field to be configured. */ + #define HWRM_FUNC_BUF_RGTR_INPUT_ENABLES_ERR_BUF_ADDR UINT32_C(0x2) + uint16_t vf_id; + /* + * This value is used to identify a Virtual Function (VF). The scope of + * VF ID is local within a PF. + */ + uint16_t req_buf_num_pages; + /* This field represents the number of pages used for request buffer(s). */ + uint16_t req_buf_page_size; + /* This field represents the page size used for request buffer(s). */ + /* 16 bytes */ + #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_16B UINT32_C(0x4) + /* 4 Kbytes */ + #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_4K UINT32_C(0xc) + /* 8 Kbytes */ + #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_8K UINT32_C(0xd) + /* 64 Kbytes */ + #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_64K UINT32_C(0x10) + /* 2 Mbytes */ + #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_2M UINT32_C(0x15) + /* 4 Mbytes */ + #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_4M UINT32_C(0x16) + /* 1 Gbytes */ + #define HWRM_FUNC_BUF_RGTR_INPUT_REQ_BUF_PAGE_SIZE_1G UINT32_C(0x1e) + uint16_t req_buf_len; + /* The length of the request buffer per VF in bytes. */ + uint16_t resp_buf_len; + /* The length of the response buffer in bytes. */ + uint8_t unused_0; + uint8_t unused_1; + uint64_t req_buf_page_addr0; + /* This field represents the page address of page #0. */ + uint64_t req_buf_page_addr1; + /* This field represents the page address of page #1. */ + uint64_t req_buf_page_addr2; + /* This field represents the page address of page #2. */ + uint64_t req_buf_page_addr3; + /* This field represents the page address of page #3. */ + uint64_t req_buf_page_addr4; + /* This field represents the page address of page #4. */ + uint64_t req_buf_page_addr5; + /* This field represents the page address of page #5. */ + uint64_t req_buf_page_addr6; + /* This field represents the page address of page #6. */ + uint64_t req_buf_page_addr7; + /* This field represents the page address of page #7. */ + uint64_t req_buf_page_addr8; + /* This field represents the page address of page #8. */ + uint64_t req_buf_page_addr9; + /* This field represents the page address of page #9. */ + uint64_t error_buf_addr; + /* + * This field is used to receive the error reporting from the chipset. + * Only applicable for PFs. + */ + uint64_t resp_buf_addr; + /* This field is used to receive the response forwarded by the HWRM. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_buf_rgtr_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_buf_unrgtr */ +/* + * Description: This command is used by the PF driver to unregister buffers used + * in the PF-VF communication with the HWRM. The PF driver uses this command to + * unregister buffers for PF-VF communication. A parent PF may issue this + * command to unregister buffers for communication between the PF and a specific + * VF. If the VF ID is not valid, then this command is used to unregister + * buffers used for communications with all children VFs of the PF. + */ +/* Input (24 bytes) */ + +struct hwrm_func_buf_unrgtr_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the vf_id field to be configured. */ + #define HWRM_FUNC_BUF_UNRGTR_INPUT_ENABLES_VF_ID UINT32_C(0x1) + uint16_t vf_id; + /* + * This value is used to identify a Virtual Function (VF). The scope of + * VF ID is local within a PF. + */ + uint16_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_buf_unrgtr_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_func_drv_qver */ +/* + * Description: This command is used to query the version of the driver. Any + * driver version with major = 0, minor = 0, and update = 0 shall be considered + * an invalid or unknown version. + */ +/* Input (24 bytes) */ + +struct hwrm_func_drv_qver_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t reserved; + /* Reserved for future use */ + uint16_t fid; + /* + * Function ID of the function that is being queried. 0xFF... (All Fs) + * if the query is for the requesting function. + */ + uint16_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_func_drv_qver_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t os_type; + /* This value indicates the type of OS. */ + /* Unknown */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_UNKNOWN UINT32_C(0x0) + /* Other OS not listed below. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_OTHER UINT32_C(0x1) + /* MSDOS OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_MSDOS UINT32_C(0xe) + /* Windows OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_WINDOWS UINT32_C(0x12) + /* Solaris OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_SOLARIS UINT32_C(0x1d) + /* Linux OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_LINUX UINT32_C(0x24) + /* FreeBSD OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_FREEBSD UINT32_C(0x2a) + /* VMware ESXi OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_ESXI UINT32_C(0x68) + /* Microsoft Windows 8 64-bit OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_WIN864 UINT32_C(0x73) + /* Microsoft Windows Server 2012 R2 OS. */ + #define HWRM_FUNC_DRV_QVER_OUTPUT_OS_TYPE_WIN2012R2 UINT32_C(0x74) + uint8_t ver_maj; + /* This is the major version of the driver. */ + uint8_t ver_min; + /* This is the minor version of the driver. */ + uint8_t ver_upd; + /* This is the update version of the driver. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_phy_cfg */ +/* + * Description: This command configures the PHY device for the port. It allows + * setting of the most generic settings for the PHY. The HWRM shall complete + * this command as soon as PHY settings are configured. They may not be applied + * when the command response is provided. A VF driver shall not be allowed to + * configure PHY using this command. In a network partition mode, a PF driver + * shall not be allowed to configure PHY using this command. + */ +/* Input (56 bytes) */ + +struct hwrm_port_phy_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is set to '1', the PHY for the port shall be reset. # + * If this bit is set to 1, then the HWRM shall reset the PHY after + * applying PHY configuration changes specified in this command. # In + * order to guarantee that PHY configuration changes specified in this + * command take effect, the HWRM client should set this flag to 1. # If + * this bit is not set to 1, then the HWRM may reset the PHY depending + * on the current PHY configuration and settings specified in this + * command. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY UINT32_C(0x1) + /* + * When this bit is set to '1', the link shall be forced to be taken + * down. # When this bit is set to '1", all other command input settings + * related to the link speed shall be ignored. Once the link state is + * forced down, it can be explicitly cleared from that state by setting + * this flag to '0'. # If this flag is set to '0', then the link shall + * be cleared from forced down state if the link is in forced down + * state. There may be conditions (e.g. out-of-band or sideband + * configuration changes for the link) outside the scope of the HWRM + * implementation that may clear forced down link state. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE_LINK_DOWN UINT32_C(0x2) + /* + * When this bit is set to '1', the link shall be forced to the + * force_link_speed value. When this bit is set to '1', the HWRM client + * should not enable any of the auto negotiation related fields + * represented by auto_XXX fields in this command. When this bit is set + * to '1' and the HWRM client has enabled a auto_XXX field in this + * command, then the HWRM shall ignore the enabled auto_XXX field. When + * this bit is set to zero, the link shall be allowed to autoneg. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE UINT32_C(0x4) + /* + * When this bit is set to '1', the auto-negotiation process shall be + * restarted on the link. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG UINT32_C(0x8) + /* + * When this bit is set to '1', Energy Efficient Ethernet (EEE) is + * requested to be enabled on this link. If EEE is not supported on this + * port, then this flag shall be ignored by the HWRM. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE UINT32_C(0x10) + /* + * When this bit is set to '1', Energy Efficient Ethernet (EEE) is + * requested to be disabled on this link. If EEE is not supported on + * this port, then this flag shall be ignored by the HWRM. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE UINT32_C(0x20) + /* + * When this bit is set to '1' and EEE is enabled on this link, then TX + * LPI is requested to be enabled on the link. If EEE is not supported + * on this port, then this flag shall be ignored by the HWRM. If EEE is + * disabled on this port, then this flag shall be ignored by the HWRM. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI_ENABLE UINT32_C(0x40) + /* + * When this bit is set to '1' and EEE is enabled on this link, then TX + * LPI is requested to be disabled on the link. If EEE is not supported + * on this port, then this flag shall be ignored by the HWRM. If EEE is + * disabled on this port, then this flag shall be ignored by the HWRM. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI_DISABLE UINT32_C(0x80) + /* + * When set to 1, then the HWRM shall enable FEC autonegotitation on + * this port if supported. When set to 0, then this flag shall be + * ignored. If FEC autonegotiation is not supported, then the HWRM shall + * ignore this flag. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_AUTONEG_ENABLE UINT32_C(0x100) + /* + * When set to 1, then the HWRM shall disable FEC autonegotiation on + * this port if supported. When set to 0, then this flag shall be + * ignored. If FEC autonegotiation is not supported, then the HWRM shall + * ignore this flag. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_AUTONEG_DISABLE UINT32_C(0x200) + /* + * When set to 1, then the HWRM shall enable FEC CLAUSE 74 (Fire Code) + * on this port if supported. When set to 0, then this flag shall be + * ignored. If FEC CLAUSE 74 is not supported, then the HWRM shall + * ignore this flag. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE74_ENABLE UINT32_C(0x400) + /* + * When set to 1, then the HWRM shall disable FEC CLAUSE 74 (Fire Code) + * on this port if supported. When set to 0, then this flag shall be + * ignored. If FEC CLAUSE 74 is not supported, then the HWRM shall + * ignore this flag. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE74_DISABLE UINT32_C(0x800) + /* + * When set to 1, then the HWRM shall enable FEC CLAUSE 91 (Reed + * Solomon) on this port if supported. When set to 0, then this flag + * shall be ignored. If FEC CLAUSE 91 is not supported, then the HWRM + * shall ignore this flag. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE91_ENABLE UINT32_C(0x1000) + /* + * When set to 1, then the HWRM shall disable FEC CLAUSE 91 (Reed + * Solomon) on this port if supported. When set to 0, then this flag + * shall be ignored. If FEC CLAUSE 91 is not supported, then the HWRM + * shall ignore this flag. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FLAGS_FEC_CLAUSE91_DISABLE UINT32_C(0x2000) + uint32_t enables; + /* This bit must be '1' for the auto_mode field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE UINT32_C(0x1) + /* This bit must be '1' for the auto_duplex field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_DUPLEX UINT32_C(0x2) + /* This bit must be '1' for the auto_pause field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE UINT32_C(0x4) + /* This bit must be '1' for the auto_link_speed field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED UINT32_C(0x8) + /* + * This bit must be '1' for the auto_link_speed_mask field to be + * configured. + */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_LINK_SPEED_MASK UINT32_C(0x10) + /* This bit must be '1' for the wirespeed field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_WIRESPEED UINT32_C(0x20) + /* This bit must be '1' for the lpbk field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_LPBK UINT32_C(0x40) + /* This bit must be '1' for the preemphasis field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_PREEMPHASIS UINT32_C(0x80) + /* This bit must be '1' for the force_pause field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE UINT32_C(0x100) + /* + * This bit must be '1' for the eee_link_speed_mask field to be + * configured. + */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_EEE_LINK_SPEED_MASK UINT32_C(0x200) + /* This bit must be '1' for the tx_lpi_timer field to be configured. */ + #define HWRM_PORT_PHY_CFG_INPUT_ENABLES_TX_LPI_TIMER UINT32_C(0x400) + uint16_t port_id; + /* Port ID of port that is to be configured. */ + uint16_t force_link_speed; + /* + * This is the speed that will be used if the force bit is '1'. If + * unsupported speed is selected, an error will be generated. + */ + /* 100Mb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB UINT32_C(0x1) + /* 1Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB UINT32_C(0xa) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2GB UINT32_C(0x14) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB UINT32_C(0x19) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB UINT32_C(0x64) + /* 20Mb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB UINT32_C(0xc8) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB UINT32_C(0xfa) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB UINT32_C(0x190) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB UINT32_C(0x1f4) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB UINT32_C(0x3e8) + /* 10Mb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10MB UINT32_C(0xffff) + uint8_t auto_mode; + /* + * This value is used to identify what autoneg mode is used when the + * link speed is not being forced. + */ + /* Disable autoneg or autoneg disabled. No speeds are selected. */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_NONE UINT32_C(0x0) + /* Select all possible speeds for autoneg mode. */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1) + /* + * Select only the auto_link_speed speed for autoneg mode. This + * mode has been DEPRECATED. An HWRM client should not use this + * mode. + */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ONE_SPEED UINT32_C(0x2) + /* + * Select the auto_link_speed or any speed below that speed for + * autoneg. This mode has been DEPRECATED. An HWRM client should + * not use this mode. + */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3) + /* + * Select the speeds based on the corresponding link speed mask + * value that is provided. + */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK UINT32_C(0x4) + uint8_t auto_duplex; + /* + * This is the duplex setting that will be used if the autoneg_mode is + * "one_speed" or "one_or_below". + */ + /* Half Duplex will be requested. */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_HALF UINT32_C(0x0) + /* Full duplex will be requested. */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_FULL UINT32_C(0x1) + /* Both Half and Full dupex will be requested. */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_DUPLEX_BOTH UINT32_C(0x2) + uint8_t auto_pause; + /* + * This value is used to configure the pause that will be used for + * autonegotiation. Add text on the usage of auto_pause and force_pause. + */ + /* + * When this bit is '1', Generation of tx pause messages has been + * requested. Disabled otherwise. + */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX UINT32_C(0x1) + /* + * When this bit is '1', Reception of rx pause messages has been + * requested. Disabled otherwise. + */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX UINT32_C(0x2) + /* + * When set to 1, the advertisement of pause is enabled. # When the + * auto_mode is not set to none and this flag is set to 1, then the + * auto_pause bits on this port are being advertised and autoneg pause + * results are being interpreted. # When the auto_mode is not set to + * none and this flag is set to 0, the pause is forced as indicated in + * force_pause, and also advertised as auto_pause bits, but the autoneg + * results are not interpreted since the pause configuration is being + * forced. # When the auto_mode is set to none and this flag is set to + * 1, auto_pause bits should be ignored and should be set to 0. + */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE UINT32_C(0x4) + uint8_t unused_0; + uint16_t auto_link_speed; + /* + * This is the speed that will be used if the autoneg_mode is + * "one_speed" or "one_or_below". If an unsupported speed is selected, + * an error will be generated. + */ + /* 100Mb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_100MB UINT32_C(0x1) + /* 1Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_1GB UINT32_C(0xa) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_2GB UINT32_C(0x14) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_2_5GB UINT32_C(0x19) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_10GB UINT32_C(0x64) + /* 20Mb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_20GB UINT32_C(0xc8) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_25GB UINT32_C(0xfa) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_40GB UINT32_C(0x190) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_50GB UINT32_C(0x1f4) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_100GB UINT32_C(0x3e8) + /* 10Mb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_10MB UINT32_C(0xffff) + uint16_t auto_link_speed_mask; + /* + * This is a mask of link speeds that will be used if autoneg_mode is + * "mask". If unsupported speed is enabled an error will be generated. + */ + /* 100Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100MBHD UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100MB UINT32_C(0x2) + /* 1Gb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GBHD UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_1GB UINT32_C(0x8) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_2GB UINT32_C(0x10) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_2_5GB UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10GB UINT32_C(0x40) + /* 20Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_20GB UINT32_C(0x80) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_25GB UINT32_C(0x100) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_40GB UINT32_C(0x200) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_50GB UINT32_C(0x400) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_100GB UINT32_C(0x800) + /* 10Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10MBHD UINT32_C(0x1000) + /* 10Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_AUTO_LINK_SPEED_MASK_10MB UINT32_C(0x2000) + uint8_t wirespeed; + /* This value controls the wirespeed feature. */ + /* Wirespeed feature is disabled. */ + #define HWRM_PORT_PHY_CFG_INPUT_WIRESPEED_OFF UINT32_C(0x0) + /* Wirespeed feature is enabled. */ + #define HWRM_PORT_PHY_CFG_INPUT_WIRESPEED_ON UINT32_C(0x1) + uint8_t lpbk; + /* This value controls the loopback setting for the PHY. */ + /* No loopback is selected. Normal operation. */ + #define HWRM_PORT_PHY_CFG_INPUT_LPBK_NONE UINT32_C(0x0) + /* + * The HW will be configured with local loopback such that host + * data is sent back to the host without modification. + */ + #define HWRM_PORT_PHY_CFG_INPUT_LPBK_LOCAL UINT32_C(0x1) + /* + * The HW will be configured with remote loopback such that port + * logic will send packets back out the transmitter that are + * received. + */ + #define HWRM_PORT_PHY_CFG_INPUT_LPBK_REMOTE UINT32_C(0x2) + uint8_t force_pause; + /* + * This value is used to configure the pause that will be used for force + * mode. + */ + /* + * When this bit is '1', Generation of tx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX UINT32_C(0x1) + /* + * When this bit is '1', Reception of rx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX UINT32_C(0x2) + uint8_t unused_1; + uint32_t preemphasis; + /* + * This value controls the pre-emphasis to be used for the link. Driver + * should not set this value (use enable.preemphasis = 0) unless driver + * is sure of setting. Normally HWRM FW will determine proper pre- + * emphasis. + */ + uint16_t eee_link_speed_mask; + /* + * Setting for link speed mask that is used to advertise speeds during + * autonegotiation when EEE is enabled. This field is valid only when + * EEE is enabled. The speeds specified in this field shall be a subset + * of speeds specified in auto_link_speed_mask. If EEE is enabled,then + * at least one speed shall be provided in this mask. + */ + /* Reserved */ + #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD1 UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_100MB UINT32_C(0x2) + /* Reserved */ + #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD2 UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_1GB UINT32_C(0x8) + /* Reserved */ + #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD3 UINT32_C(0x10) + /* Reserved */ + #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_RSVD4 UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_CFG_INPUT_EEE_LINK_SPEED_MASK_10GB UINT32_C(0x40) + uint8_t unused_2; + uint8_t unused_3; + uint32_t tx_lpi_timer; + uint32_t unused_4; + /* + * Reuested setting of TX LPI timer in microseconds. This field is valid + * only when EEE is enabled and TX LPI is enabled. + */ + #define HWRM_PORT_PHY_CFG_INPUT_TX_LPI_TIMER_MASK UINT32_C(0xffffff) + #define HWRM_PORT_PHY_CFG_INPUT_TX_LPI_TIMER_SFT 0 +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_port_phy_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_phy_qcfg */ +/* Description: This command queries the PHY configuration for the port. */ +/* Input (24 bytes) */ + +struct hwrm_port_phy_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* Port ID of port that is to be queried. */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (96 bytes) */ + +struct hwrm_port_phy_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t link; + /* This value indicates the current link status. */ + /* There is no link or cable detected. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_NO_LINK UINT32_C(0x0) + /* There is no link, but a cable has been detected. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SIGNAL UINT32_C(0x1) + /* There is a link. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK UINT32_C(0x2) + uint8_t unused_0; + uint16_t link_speed; + /* This value indicates the current link speed of the connection. */ + /* 100Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB UINT32_C(0x1) + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB UINT32_C(0xa) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB UINT32_C(0x14) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB UINT32_C(0x19) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB UINT32_C(0x64) + /* 20Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB UINT32_C(0xc8) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB UINT32_C(0xfa) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB UINT32_C(0x190) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB UINT32_C(0x1f4) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB UINT32_C(0x3e8) + /* 10Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB UINT32_C(0xffff) + uint8_t duplex; + /* This value is indicates the duplex of the current connection. */ + /* Half Duplex connection. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_HALF UINT32_C(0x0) + /* Full duplex connection. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL UINT32_C(0x1) + uint8_t pause; + /* + * This value is used to indicate the current pause configuration. When + * autoneg is enabled, this value represents the autoneg results of + * pause configuration. + */ + /* + * When this bit is '1', Generation of tx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX UINT32_C(0x1) + /* + * When this bit is '1', Reception of rx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX UINT32_C(0x2) + uint16_t support_speeds; + /* + * The supported speeds for the port. This is a bit mask. For each speed + * that is supported, the corrresponding bit will be set to '1'. + */ + /* 100Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MBHD UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MB UINT32_C(0x2) + /* 1Gb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GBHD UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB UINT32_C(0x8) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2GB UINT32_C(0x10) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB UINT32_C(0x40) + /* 20Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB UINT32_C(0x80) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB UINT32_C(0x100) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB UINT32_C(0x200) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB UINT32_C(0x400) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB UINT32_C(0x800) + /* 10Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MBHD UINT32_C(0x1000) + /* 10Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MB UINT32_C(0x2000) + uint16_t force_link_speed; + /* + * Current setting of forced link speed. When the link speed is not + * being forced, this value shall be set to 0. + */ + /* 100Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_100MB UINT32_C(0x1) + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_1GB UINT32_C(0xa) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_2GB UINT32_C(0x14) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_2_5GB UINT32_C(0x19) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_10GB UINT32_C(0x64) + /* 20Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_20GB UINT32_C(0xc8) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_25GB UINT32_C(0xfa) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_40GB UINT32_C(0x190) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_50GB UINT32_C(0x1f4) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_100GB UINT32_C(0x3e8) + /* 10Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_10MB UINT32_C(0xffff) + uint8_t auto_mode; + /* Current setting of auto negotiation mode. */ + /* Disable autoneg or autoneg disabled. No speeds are selected. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE UINT32_C(0x0) + /* Select all possible speeds for autoneg mode. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1) + /* + * Select only the auto_link_speed speed for autoneg mode. This + * mode has been DEPRECATED. An HWRM client should not use this + * mode. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ONE_SPEED UINT32_C(0x2) + /* + * Select the auto_link_speed or any speed below that speed for + * autoneg. This mode has been DEPRECATED. An HWRM client should + * not use this mode. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3) + /* + * Select the speeds based on the corresponding link speed mask + * value that is provided. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_SPEED_MASK UINT32_C(0x4) + uint8_t auto_pause; + /* + * Current setting of pause autonegotiation. Move autoneg_pause flag + * here. + */ + /* + * When this bit is '1', Generation of tx pause messages has been + * requested. Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_TX UINT32_C(0x1) + /* + * When this bit is '1', Reception of rx pause messages has been + * requested. Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_RX UINT32_C(0x2) + /* + * When set to 1, the advertisement of pause is enabled. # When the + * auto_mode is not set to none and this flag is set to 1, then the + * auto_pause bits on this port are being advertised and autoneg pause + * results are being interpreted. # When the auto_mode is not set to + * none and this flag is set to 0, the pause is forced as indicated in + * force_pause, and also advertised as auto_pause bits, but the autoneg + * results are not interpreted since the pause configuration is being + * forced. # When the auto_mode is set to none and this flag is set to + * 1, auto_pause bits should be ignored and should be set to 0. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_AUTONEG_PAUSE UINT32_C(0x4) + uint16_t auto_link_speed; + /* + * Current setting for auto_link_speed. This field is only valid when + * auto_mode is set to "one_speed" or "one_or_below". + */ + /* 100Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_100MB UINT32_C(0x1) + /* 1Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_1GB UINT32_C(0xa) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_2GB UINT32_C(0x14) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_2_5GB UINT32_C(0x19) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_10GB UINT32_C(0x64) + /* 20Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_20GB UINT32_C(0xc8) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_25GB UINT32_C(0xfa) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_40GB UINT32_C(0x190) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_50GB UINT32_C(0x1f4) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_100GB UINT32_C(0x3e8) + /* 10Mb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_10MB UINT32_C(0xffff) + uint16_t auto_link_speed_mask; + /* + * Current setting for auto_link_speed_mask that is used to advertise + * speeds during autonegotiation. This field is only valid when + * auto_mode is set to "mask". The speeds specified in this field shall + * be a subset of supported speeds on this port. + */ + /* 100Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_100MBHD UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_100MB UINT32_C(0x2) + /* 1Gb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_1GBHD UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_1GB UINT32_C(0x8) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_2GB UINT32_C(0x10) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_2_5GB UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_10GB UINT32_C(0x40) + /* 20Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_20GB UINT32_C(0x80) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_25GB UINT32_C(0x100) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_40GB UINT32_C(0x200) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_50GB UINT32_C(0x400) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_100GB UINT32_C(0x800) + /* 10Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_10MBHD UINT32_C(0x1000) + /* 10Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_LINK_SPEED_MASK_10MB UINT32_C(0x2000) + uint8_t wirespeed; + /* Current setting for wirespeed. */ + /* Wirespeed feature is disabled. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_WIRESPEED_OFF UINT32_C(0x0) + /* Wirespeed feature is enabled. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_WIRESPEED_ON UINT32_C(0x1) + uint8_t lpbk; + /* Current setting for loopback. */ + /* No loopback is selected. Normal operation. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_NONE UINT32_C(0x0) + /* + * The HW will be configured with local loopback such that host + * data is sent back to the host without modification. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_LOCAL UINT32_C(0x1) + /* + * The HW will be configured with remote loopback such that port + * logic will send packets back out the transmitter that are + * received. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LPBK_REMOTE UINT32_C(0x2) + uint8_t force_pause; + /* + * Current setting of forced pause. When the pause configuration is not + * being forced, then this value shall be set to 0. + */ + /* + * When this bit is '1', Generation of tx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_PAUSE_TX UINT32_C(0x1) + /* + * When this bit is '1', Reception of rx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_PAUSE_RX UINT32_C(0x2) + uint8_t module_status; + /* + * This value indicates the current status of the optics module on this + * port. + */ + /* Module is inserted and accepted */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NONE UINT32_C(0x0) + /* Module is rejected and transmit side Laser is disabled. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_DISABLETX UINT32_C(0x1) + /* Module mismatch warning. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_WARNINGMSG UINT32_C(0x2) + /* Module is rejected and powered down. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_PWRDOWN UINT32_C(0x3) + /* Module is not inserted. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NOTINSERTED UINT32_C(0x4) + /* Module status is not applicable. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MODULE_STATUS_NOTAPPLICABLE UINT32_C(0xff) + uint32_t preemphasis; + /* Current setting for preemphasis. */ + uint8_t phy_maj; + /* This field represents the major version of the PHY. */ + uint8_t phy_min; + /* This field represents the minor version of the PHY. */ + uint8_t phy_bld; + /* This field represents the build version of the PHY. */ + uint8_t phy_type; + /* This value represents a PHY type. */ + /* Unknown */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN UINT32_C(0x0) + /* BASE-CR */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR UINT32_C(0x1) + /* BASE-KR4 (Deprecated) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4 UINT32_C(0x2) + /* BASE-LR */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR UINT32_C(0x3) + /* BASE-SR */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR UINT32_C(0x4) + /* BASE-KR2 (Deprecated) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2 UINT32_C(0x5) + /* BASE-KX */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX UINT32_C(0x6) + /* BASE-KR */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR UINT32_C(0x7) + /* BASE-T */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET UINT32_C(0x8) + /* EEE capable BASE-T */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE UINT32_C(0x9) + /* SGMII connected external PHY */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY UINT32_C(0xa) + uint8_t media_type; + /* This value represents a media type. */ + /* Unknown */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_UNKNOWN UINT32_C(0x0) + /* Twisted Pair */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP UINT32_C(0x1) + /* Direct Attached Copper */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_DAC UINT32_C(0x2) + /* Fiber */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_FIBRE UINT32_C(0x3) + uint8_t xcvr_pkg_type; + /* This value represents a transceiver type. */ + /* PHY and MAC are in the same package */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_PKG_TYPE_XCVR_INTERNAL UINT32_C(0x1) + /* PHY and MAC are in different packages */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_PKG_TYPE_XCVR_EXTERNAL UINT32_C(0x2) + uint8_t eee_config_phy_addr; + /* + * This field represents flags related to EEE configuration. These EEE + * configuration flags are valid only when the auto_mode is not set to + * none (in other words autonegotiation is enabled). + */ + /* This field represents PHY address. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_MASK UINT32_C(0x1f) + #define HWRM_PORT_PHY_QCFG_OUTPUT_PHY_ADDR_SFT 0 + /* + * When set to 1, Energy Efficient Ethernet (EEE) mode is enabled. + * Speeds for autoneg with EEE mode enabled are based on + * eee_link_speed_mask. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_EEE_ENABLED UINT32_C(0x20) + /* + * This flag is valid only when eee_enabled is set to 1. # If + * eee_enabled is set to 0, then EEE mode is disabled and this flag + * shall be ignored. # If eee_enabled is set to 1 and this flag is set + * to 1, then Energy Efficient Ethernet (EEE) mode is enabled and in + * use. # If eee_enabled is set to 1 and this flag is set to 0, then + * Energy Efficient Ethernet (EEE) mode is enabled but is currently not + * in use. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_EEE_ACTIVE UINT32_C(0x40) + /* + * This flag is valid only when eee_enabled is set to 1. # If + * eee_enabled is set to 0, then EEE mode is disabled and this flag + * shall be ignored. # If eee_enabled is set to 1 and this flag is set + * to 1, then Energy Efficient Ethernet (EEE) mode is enabled and TX LPI + * is enabled. # If eee_enabled is set to 1 and this flag is set to 0, + * then Energy Efficient Ethernet (EEE) mode is enabled but TX LPI is + * disabled. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_EEE_TX_LPI UINT32_C(0x80) + /* + * This field represents flags related to EEE configuration. These EEE + * configuration flags are valid only when the auto_mode is not set to + * none (in other words autonegotiation is enabled). + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_MASK UINT32_C(0xe0) + #define HWRM_PORT_PHY_QCFG_OUTPUT_EEE_CONFIG_SFT 5 + uint8_t parallel_detect; + /* Reserved field, set to 0 */ + /* + * When set to 1, the parallel detection is used to determine the speed + * of the link partner. Parallel detection is used when a + * autonegotiation capable device is connected to a link parter that is + * not capable of autonegotiation. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_PARALLEL_DETECT UINT32_C(0x1) + /* Reserved field, set to 0 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_RESERVED_MASK UINT32_C(0xfe) + #define HWRM_PORT_PHY_QCFG_OUTPUT_RESERVED_SFT 1 + uint16_t link_partner_adv_speeds; + /* + * The advertised speeds for the port by the link partner. Each + * advertised speed will be set to '1'. + */ + /* 100Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_100MBHD UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_100MB UINT32_C(0x2) + /* 1Gb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_1GBHD UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_1GB UINT32_C(0x8) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_2GB UINT32_C(0x10) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_2_5GB UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_10GB UINT32_C(0x40) + /* 20Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_20GB UINT32_C(0x80) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_25GB UINT32_C(0x100) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_40GB UINT32_C(0x200) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_50GB UINT32_C(0x400) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_100GB UINT32_C(0x800) + /* 10Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_10MBHD UINT32_C(0x1000) + /* 10Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_SPEEDS_10MB UINT32_C(0x2000) + uint8_t link_partner_adv_auto_mode; + /* + * The advertised autoneg for the port by the link partner. This field + * is deprecated and should be set to 0. + */ + /* Disable autoneg or autoneg disabled. No speeds are selected. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_NONE UINT32_C(0x0) + /* Select all possible speeds for autoneg mode. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ALL_SPEEDS UINT32_C(0x1) + /* + * Select only the auto_link_speed speed for autoneg mode. This + * mode has been DEPRECATED. An HWRM client should not use this + * mode. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ONE_SPEED UINT32_C(0x2) + /* + * Select the auto_link_speed or any speed below that speed for + * autoneg. This mode has been DEPRECATED. An HWRM client should + * not use this mode. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_ONE_OR_BELOW UINT32_C(0x3) + /* + * Select the speeds based on the corresponding link speed mask + * value that is provided. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_AUTO_MODE_SPEED_MASK UINT32_C(0x4) + uint8_t link_partner_adv_pause; + /* The advertised pause settings on the port by the link partner. */ + /* + * When this bit is '1', Generation of tx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_PAUSE_TX UINT32_C(0x1) + /* + * When this bit is '1', Reception of rx pause messages is supported. + * Disabled otherwise. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_PAUSE_RX UINT32_C(0x2) + uint16_t adv_eee_link_speed_mask; + /* + * Current setting for link speed mask that is used to advertise speeds + * during autonegotiation when EEE is enabled. This field is valid only + * when eee_enabled flags is set to 1. The speeds specified in this + * field shall be a subset of speeds specified in auto_link_speed_mask. + */ + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD1 UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_100MB UINT32_C(0x2) + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD2 UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_1GB UINT32_C(0x8) + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD3 UINT32_C(0x10) + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_RSVD4 UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_ADV_EEE_LINK_SPEED_MASK_10GB UINT32_C(0x40) + uint16_t link_partner_adv_eee_link_speed_mask; + /* + * Current setting for link speed mask that is advertised by the link + * partner when EEE is enabled. This field is valid only when + * eee_enabled flags is set to 1. + */ + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD1 UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_100MB UINT32_C(0x2) + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD2 UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_1GB UINT32_C(0x8) + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD3 UINT32_C(0x10) + /* Reserved */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_RSVD4 UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_LINK_PARTNER_ADV_EEE_LINK_SPEED_MASK_10GB UINT32_C(0x40) + uint32_t xcvr_identifier_type_tx_lpi_timer; + /* This value represents transceiver identifier type. */ + /* + * Current setting of TX LPI timer in microseconds. This field is valid + * only when_eee_enabled flag is set to 1 and tx_lpi_enabled is set to + * 1. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_TX_LPI_TIMER_MASK UINT32_C(0xffffff) + #define HWRM_PORT_PHY_QCFG_OUTPUT_TX_LPI_TIMER_SFT 0 + /* This value represents transceiver identifier type. */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_MASK UINT32_C(0xff000000) + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_SFT 24 + /* Unknown */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_UNKNOWN (UINT32_C(0x0) << 24) + /* SFP/SFP+/SFP28 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_SFP (UINT32_C(0x3) << 24) + /* QSFP */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP (UINT32_C(0xc) << 24) + /* QSFP+ */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFPPLUS (UINT32_C(0xd) << 24) + /* QSFP28 */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_XCVR_IDENTIFIER_TYPE_QSFP28 (UINT32_C(0x11) << 24) + uint16_t fec_cfg; + /* + * This value represents the current configuration of Forward Error + * Correction (FEC) on the port. + */ + /* + * When set to 1, then FEC is not supported on this port. If this flag + * is set to 1, then all other FEC configuration flags shall be ignored. + * When set to 0, then FEC is supported as indicated by other + * configuration flags. If no cable is attached and the HWRM does not + * yet know the FEC capability, then the HWRM shall set this flag to 1 + * when reporting FEC capability. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_NONE_SUPPORTED UINT32_C(0x1) + /* + * When set to 1, then FEC autonegotiation is supported on this port. + * When set to 0, then FEC autonegotiation is not supported on this + * port. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_AUTONEG_SUPPORTED UINT32_C(0x2) + /* + * When set to 1, then FEC autonegotiation is enabled on this port. When + * set to 0, then FEC autonegotiation is disabled if supported. This + * flag should be ignored if FEC autonegotiation is not supported on + * this port. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_AUTONEG_ENABLED UINT32_C(0x4) + /* + * When set to 1, then FEC CLAUSE 74 (Fire Code) is supported on this + * port. When set to 0, then FEC CLAUSE 74 (Fire Code) is not supported + * on this port. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE74_SUPPORTED UINT32_C(0x8) + /* + * When set to 1, then FEC CLAUSE 74 (Fire Code) is enabled on this + * port. When set to 0, then FEC CLAUSE 74 (Fire Code) is disabled if + * supported. This flag should be ignored if FEC CLAUSE 74 is not + * supported on this port. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE74_ENABLED UINT32_C(0x10) + /* + * When set to 1, then FEC CLAUSE 91 (Reed Solomon) is supported on this + * port. When set to 0, then FEC CLAUSE 91 (Reed Solomon) is not + * supported on this port. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE91_SUPPORTED UINT32_C(0x20) + /* + * When set to 1, then FEC CLAUSE 91 (Reed Solomon) is enabled on this + * port. When set to 0, then FEC CLAUSE 91 (Reed Solomon) is disabled if + * supported. This flag should be ignored if FEC CLAUSE 91 is not + * supported on this port. + */ + #define HWRM_PORT_PHY_QCFG_OUTPUT_FEC_CFG_FEC_CLAUSE91_ENABLED UINT32_C(0x40) + uint8_t unused_1; + uint8_t unused_2; + char phy_vendor_name[16]; + /* + * Up to 16 bytes of null padded ASCII string representing PHY vendor. + * If the string is set to null, then the vendor name is not available. + */ + char phy_vendor_partnumber[16]; + /* + * Up to 16 bytes of null padded ASCII string that identifies vendor + * specific part number of the PHY. If the string is set to null, then + * the vendor specific part number is not available. + */ + uint32_t unused_3; + uint8_t unused_4; + uint8_t unused_5; + uint8_t unused_6; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_mac_cfg */ +/* Description: This command configures the MAC block for the port. */ +/* Input (40 bytes) */ + +struct hwrm_port_mac_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is '1', this command will configure the MAC to match + * the current link state of the PHY. If the link is not established on + * the PHY, then this bit has no effect. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_MATCH_LINK UINT32_C(0x1) + /* + * When this bit is '1', the CoS assignment logic is enabled. When this + * logic is enabled, then inner VLAN PRI to CoS mapping is enabled. If + * this bit is '0', then the default CoS is used. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_COS_ASSIGNMENT_ENABLE UINT32_C(0x2) + /* + * When this bit is '1', tunnel or outer VLAN PRI field to CoS mapping + * is enabled. If this bit is '0', then outer VLAN PRI bits are not used + * in determining CoS. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_TUNNEL_PRI2COS_ENABLE UINT32_C(0x4) + /* + * When this bit is '1', the IP DSCP to CoS mapping is enabled. If this + * bit is '0', then IP DSCP bits are not used in determining CoS. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_IP_DSCP2COS_ENABLE UINT32_C(0x8) + /* + * When this bit is '1', the HWRM is requested to enable timestamp + * capture capability on the receive side of this port. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_RX_TS_CAPTURE_ENABLE UINT32_C(0x10) + /* + * When this bit is '1', the HWRM is requested to disable timestamp + * capture capability on the receive side of this port. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_RX_TS_CAPTURE_DISABLE UINT32_C(0x20) + /* + * When this bit is '1', the HWRM is requested to enable timestamp + * capture capability on the transmit side of this port. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_TX_TS_CAPTURE_ENABLE UINT32_C(0x40) + /* + * When this bit is '1', the HWRM is requested to disable timestamp + * capture capability on the transmit side of this port. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_PTP_TX_TS_CAPTURE_DISABLE UINT32_C(0x80) + /* + * When this bit is '1', the Out-Of-Box WoL is requested to be enabled + * on this port. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_OOB_WOL_ENABLE UINT32_C(0x100) + /* + * When this bit is '1', the the Out-Of-Box WoL is requested to be + * disabled on this port. + */ + #define HWRM_PORT_MAC_CFG_INPUT_FLAGS_OOB_WOL_DISABLE UINT32_C(0x200) + uint32_t enables; + /* This bit must be '1' for the ipg field to be configured. */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_IPG UINT32_C(0x1) + /* This bit must be '1' for the lpbk field to be configured. */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_LPBK UINT32_C(0x2) + /* + * This bit must be '1' for the ivlan_pri2cos_map_pri field to be + * configured. + */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_IVLAN_PRI2COS_MAP_PRI UINT32_C(0x4) + /* This bit must be '1' for the lcos_map_pri field to be configured. */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_LCOS_MAP_PRI UINT32_C(0x8) + /* + * This bit must be '1' for the tunnel_pri2cos_map_pri field to be + * configured. + */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_TUNNEL_PRI2COS_MAP_PRI UINT32_C(0x10) + /* This bit must be '1' for the dscp2cos_map_pri field to be configured. */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_DSCP2COS_MAP_PRI UINT32_C(0x20) + /* + * This bit must be '1' for the rx_ts_capture_ptp_msg_type field to be + * configured. + */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE UINT32_C(0x40) + /* + * This bit must be '1' for the tx_ts_capture_ptp_msg_type field to be + * configured. + */ + #define HWRM_PORT_MAC_CFG_INPUT_ENABLES_TX_TS_CAPTURE_PTP_MSG_TYPE UINT32_C(0x80) + uint16_t port_id; + /* Port ID of port that is to be configured. */ + uint8_t ipg; + /* + * This value is used to configure the minimum IPG that will be sent + * between packets by this port. + */ + uint8_t lpbk; + /* This value controls the loopback setting for the MAC. */ + /* No loopback is selected. Normal operation. */ + #define HWRM_PORT_MAC_CFG_INPUT_LPBK_NONE UINT32_C(0x0) + /* + * The HW will be configured with local loopback such that host + * data is sent back to the host without modification. + */ + #define HWRM_PORT_MAC_CFG_INPUT_LPBK_LOCAL UINT32_C(0x1) + /* + * The HW will be configured with remote loopback such that port + * logic will send packets back out the transmitter that are + * received. + */ + #define HWRM_PORT_MAC_CFG_INPUT_LPBK_REMOTE UINT32_C(0x2) + uint8_t ivlan_pri2cos_map_pri; + /* + * This value controls the priority of mapping. Valid values: 1-4 Higher + * the number, higher the priority + */ + uint8_t lcos_map_pri; + /* + * This value controls the priority of mapping. Valid values: 1-4 Higher + * the number, higher the priority + */ + uint8_t tunnel_pri2cos_map_pri; + /* + * This value controls the priority of mapping. Valid values: 1-4 Higher + * the number, higher the priority + */ + uint8_t dscp2pri_map_pri; + /* + * This value controls the priority of mapping. Valid values: 1-4 Higher + * the number, higher the priority + */ + uint16_t rx_ts_capture_ptp_msg_type; + /* + * This is a 16-bit bit mask that is used to request a specific + * configuration of time stamp capture of PTP messages on the receive + * side of this port. This field shall be ignored if the + * ptp_rx_ts_capture_enable flag is not set in this command. Otherwise, + * if bit 'i' is set, then the HWRM is being requested to configure the + * receive side of the port to capture the time stamp of every received + * PTP message with messageType field value set to i. + */ + uint16_t tx_ts_capture_ptp_msg_type; + /* + * This is a 16-bit bit mask that is used to request a specific + * configuration of time stamp capture of PTP messages on the transmit + * side of this port. This field shall be ignored if the + * ptp_tx_ts_capture_enable flag is not set in this command. Otherwise, + * if bit 'i' is set, then the HWRM is being requested to configure the + * transmit sied of the port to capture the time stamp of every + * transmitted PTP message with messageType field value set to i. + */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_port_mac_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t mru; + /* + * This is the configured maximum length of Ethernet packet payload that + * is allowed to be received on the port. This value does not include + * the number of bytes used by Ethernet header and trailer (CRC). + */ + uint16_t mtu; + /* + * This is the configured maximum length of Ethernet packet payload that + * is allowed to be transmitted on the port. This value does not include + * the number of bytes used by Ethernet header and trailer (CRC). + */ + uint8_t ipg; + /* Current configuration of the IPG value. */ + uint8_t lpbk; + /* Current value of the loopback value. */ + /* No loopback is selected. Normal operation. */ + #define HWRM_PORT_MAC_CFG_OUTPUT_LPBK_NONE UINT32_C(0x0) + /* + * The HW will be configured with local loopback such that host + * data is sent back to the host without modification. + */ + #define HWRM_PORT_MAC_CFG_OUTPUT_LPBK_LOCAL UINT32_C(0x1) + /* + * The HW will be configured with remote loopback such that port + * logic will send packets back out the transmitter that are + * received. + */ + #define HWRM_PORT_MAC_CFG_OUTPUT_LPBK_REMOTE UINT32_C(0x2) + uint8_t unused_0; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_mac_qcfg */ +/* Description: This command queries the MAC block for the port. */ +/* Input (24 bytes) */ + +struct hwrm_port_mac_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* Port ID of port that is to be configured. */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_port_mac_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t mru; + /* + * This is the configured maximum length of Ethernet packet payload that + * is allowed to be received on the port. This value does not include + * the number of bytes used by the Ethernet header and trailer (CRC). + */ + uint16_t mtu; + /* + * This is the configured maximum length of Ethernet packet payload that + * is allowed to be transmitted on the port. This value does not include + * the number of bytes used by the Ethernet header and trailer (CRC). + */ + uint8_t ipg; + /* The minimum IPG that will be sent between packets by this port. */ + uint8_t lpbk; + /* The loopback setting for the MAC. */ + /* No loopback is selected. Normal operation. */ + #define HWRM_PORT_MAC_QCFG_OUTPUT_LPBK_NONE UINT32_C(0x0) + /* + * The HW will be configured with local loopback such that host + * data is sent back to the host without modification. + */ + #define HWRM_PORT_MAC_QCFG_OUTPUT_LPBK_LOCAL UINT32_C(0x1) + /* + * The HW will be configured with remote loopback such that port + * logic will send packets back out the transmitter that are + * received. + */ + #define HWRM_PORT_MAC_QCFG_OUTPUT_LPBK_REMOTE UINT32_C(0x2) + uint8_t ivlan_pri2cos_map_pri; + /* + * Priority of pri to CoS mapping. Valid values: 1-4 Higher the number, + * higher the priority Value 0 indicates that this mapping is not used. + */ + uint8_t lcos_map_pri; + /* + * Priority of local CoS to PRI mapping. Valid values: 1-4 Higher the + * number, higher the priority Value 0 indicates that this mapping is + * not used. + */ + uint8_t tunnel_pri2cos_map_pri; + /* + * Priority of tunnel PRI to CoS mapping. Valid values: 1-4 Higher the + * number, higher the priority Value 0 indicates that this mapping is + * not used. + */ + uint8_t dscp2pri_map_pri; + /* + * Priority of DSCP to PRI mapping. Valid values: 1-4 Higher the number, + * higher the priority Value 0 indicates that this mapping is not used. + */ + uint16_t rx_ts_capture_ptp_msg_type; + /* + * This is a 16-bit bit mask that represents the current configuration + * of time stamp capture of PTP messages on the receive side of this + * port. If bit 'i' is set, then the receive side of the port is + * configured to capture the time stamp of every received PTP message + * with messageType field value set to i. If all bits are set to 0 (i.e. + * field value set 0), then the receive side of the port is not + * configured to capture timestamp for PTP messages. If all bits are set + * to 1, then the receive side of the port is configured to capture + * timestamp for all PTP messages. + */ + uint16_t tx_ts_capture_ptp_msg_type; + /* + * This is a 16-bit bit mask that represents the current configuration + * of time stamp capture of PTP messages on the transmit side of this + * port. If bit 'i' is set, then the transmit side of the port is + * configured to capture the time stamp of every received PTP message + * with messageType field value set to i. If all bits are set to 0 (i.e. + * field value set 0), then the transmit side of the port is not + * configured to capture timestamp for PTP messages. If all bits are set + * to 1, then the transmit side of the port is configured to capture + * timestamp for all PTP messages. + */ + uint8_t unused_0; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_qstats */ +/* Description: This function returns per port Ethernet statistics. */ +/* Input (40 bytes) */ + +struct hwrm_port_qstats_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* Port ID of port that is being queried. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2[3]; + uint8_t unused_3; + uint64_t tx_stat_host_addr; + /* This is the host address where Tx port statistics will be stored */ + uint64_t rx_stat_host_addr; + /* This is the host address where Rx port statistics will be stored */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_port_qstats_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t tx_stat_size; + /* The size of TX port statistics block in bytes. */ + uint16_t rx_stat_size; + /* The size of RX port statistics block in bytes. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_lpbk_qstats */ +/* Description: This function returns loopback statistics. */ +/* Input (16 bytes) */ + +struct hwrm_port_lpbk_qstats_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (96 bytes) */ + +struct hwrm_port_lpbk_qstats_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t lpbk_ucast_frames; + /* Number of transmitted unicast frames */ + uint64_t lpbk_mcast_frames; + /* Number of transmitted multicast frames */ + uint64_t lpbk_bcast_frames; + /* Number of transmitted broadcast frames */ + uint64_t lpbk_ucast_bytes; + /* Number of transmitted bytes for unicast traffic */ + uint64_t lpbk_mcast_bytes; + /* Number of transmitted bytes for multicast traffic */ + uint64_t lpbk_bcast_bytes; + /* Number of transmitted bytes for broadcast traffic */ + uint64_t tx_stat_discard; + /* Total Tx Drops for loopback traffic reported by STATS block */ + uint64_t tx_stat_error; + /* Total Tx Error Drops for loopback traffic reported by STATS block */ + uint64_t rx_stat_discard; + /* Total Rx Drops for loopback traffic reported by STATS block */ + uint64_t rx_stat_error; + /* Total Rx Error Drops for loopback traffic reported by STATS block */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_clr_stats */ +/* + * Description: This function clears per port statistics. The HWRM shall not + * allow a VF driver to clear port statistics. The HWRM shall not allow a PF + * driver to clear port statistics in a partitioning mode. The HWRM may allow a + * PF driver to clear port statistics in the non-partitioning mode. + */ +/* Input (24 bytes) */ + +struct hwrm_port_clr_stats_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* Port ID of port that is being queried. */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_port_clr_stats_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_lpbk_clr_stats */ +/* + * Description: This function clears loopback statistics. The HWRM shall not + * allow a VF driver to clear loopback statistics. The HWRM shall not allow a PF + * driver to clear loopback statistics in a partitioning mode. The HWRM may + * allow a PF driver to clear loopback statistics in the non-partitioning mode. + */ +/* Input (16 bytes) */ + +struct hwrm_port_lpbk_clr_stats_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_port_lpbk_clr_stats_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_blink_led */ +/* + * Description: This function blinks the port LED for the specified number of + * times. + */ +/* Input (24 bytes) */ + +struct hwrm_port_blink_led_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t num_blinks; + /* Number of blinks. */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_port_blink_led_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_ts_query */ +/* + * Description: This function is used to read timestamp information captured for + * PTP messages on this port. + */ +/* Input (24 bytes) */ + +struct hwrm_port_ts_query_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_TX UINT32_C(0x0) + /* rx path */ + #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX UINT32_C(0x1) + #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_LAST HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX + uint16_t port_id; + /* Port ID of port that is being queried. */ + uint16_t unused_0; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_port_ts_query_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t ptp_msg_ts; + /* Timestamp value of PTP message captured. */ + uint16_t ptp_msg_seqid; + /* Sequence ID of the PTP message captured. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_port_phy_qcaps */ +/* + * Description: This function is used to query the current capabilities of PHY + * on this link. + */ +/* Input (24 bytes) */ + +struct hwrm_port_phy_qcaps_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* Port ID of port that is being queried. */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_port_phy_qcaps_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t eee_supported; + /* + * Reserved field. The HWRM shall set this field to 0. An HWRM client + * shall ignore this field. + */ + /* + * If set to 1, then this field indicates that the link is capable of + * supporting EEE. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_EEE_SUPPORTED UINT32_C(0x1) + /* + * Reserved field. The HWRM shall set this field to 0. An HWRM client + * shall ignore this field. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD1_MASK UINT32_C(0xfe) + #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD1_SFT 1 + uint8_t unused_0; + uint16_t supported_speeds_force_mode; + /* + * This is a bit mask to indicate what speeds are supported as forced + * speeds on this link. For each speed that can be forced on this link, + * the corresponding mask bit shall be set to '1'. + */ + /* 100Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_100MBHD UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_100MB UINT32_C(0x2) + /* 1Gb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_1GBHD UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_1GB UINT32_C(0x8) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_2GB UINT32_C(0x10) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_2_5GB UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_10GB UINT32_C(0x40) + /* 20Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_20GB UINT32_C(0x80) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_25GB UINT32_C(0x100) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_40GB UINT32_C(0x200) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_50GB UINT32_C(0x400) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_100GB UINT32_C(0x800) + /* 10Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_10MBHD UINT32_C(0x1000) + /* 10Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_FORCE_MODE_10MB UINT32_C(0x2000) + uint16_t supported_speeds_auto_mode; + /* + * This is a bit mask to indicate what speeds are supported for + * autonegotiation on this link. For each speed that can be + * autonegotiated on this link, the corresponding mask bit shall be set + * to '1'. + */ + /* 100Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_100MBHD UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_100MB UINT32_C(0x2) + /* 1Gb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_1GBHD UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_1GB UINT32_C(0x8) + /* 2Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_2GB UINT32_C(0x10) + /* 2.5Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_2_5GB UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_10GB UINT32_C(0x40) + /* 20Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_20GB UINT32_C(0x80) + /* 25Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_25GB UINT32_C(0x100) + /* 40Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_40GB UINT32_C(0x200) + /* 50Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_50GB UINT32_C(0x400) + /* 100Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_100GB UINT32_C(0x800) + /* 10Mb link speed (Half-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_10MBHD UINT32_C(0x1000) + /* 10Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_AUTO_MODE_10MB UINT32_C(0x2000) + uint16_t supported_speeds_eee_mode; + /* + * This is a bit mask to indicate what speeds are supported for EEE on + * this link. For each speed that can be autonegotiated when EEE is + * enabled on this link, the corresponding mask bit shall be set to '1'. + * This field is only valid when the eee_suppotred is set to '1'. + */ + /* Reserved */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD1 UINT32_C(0x1) + /* 100Mb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_100MB UINT32_C(0x2) + /* Reserved */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD2 UINT32_C(0x4) + /* 1Gb link speed (Full-duplex) */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_1GB UINT32_C(0x8) + /* Reserved */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD3 UINT32_C(0x10) + /* Reserved */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_RSVD4 UINT32_C(0x20) + /* 10Gb link speed */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_SUPPORTED_SPEEDS_EEE_MODE_10GB UINT32_C(0x40) + uint32_t tx_lpi_timer_low; + /* + * Reserved field. The HWRM shall set this field to 0. An HWRM client + * shall ignore this field. + */ + /* + * The lowest value of TX LPI timer that can be set on this link when + * EEE is enabled. This value is in microseconds. This field is valid + * only when_eee_supported is set to '1'. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_LOW_MASK UINT32_C(0xffffff) + #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_LOW_SFT 0 + /* + * Reserved field. The HWRM shall set this field to 0. An HWRM client + * shall ignore this field. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD2_MASK UINT32_C(0xff000000) + #define HWRM_PORT_PHY_QCAPS_OUTPUT_RSVD2_SFT 24 + uint32_t valid_tx_lpi_timer_high; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ + /* + * The highest value of TX LPI timer that can be set on this link when + * EEE is enabled. This value is in microseconds. This field is valid + * only when_eee_supported is set to '1'. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_HIGH_MASK UINT32_C(0xffffff) + #define HWRM_PORT_PHY_QCAPS_OUTPUT_TX_LPI_TIMER_HIGH_SFT 0 + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ + #define HWRM_PORT_PHY_QCAPS_OUTPUT_VALID_MASK UINT32_C(0xff000000) + #define HWRM_PORT_PHY_QCAPS_OUTPUT_VALID_SFT 24 +} __attribute__((packed)); + +/* hwrm_queue_qportcfg */ +/* + * Description: This function is called by a driver to query queue configuration + * of a port. # The HWRM shall at least advertise one queue with lossy service + * profile. # The driver shall use this command to query queue ids before + * configuring or using any queues. # If a service profile is not set for a + * queue, then the driver shall not use that queue without configuring a service + * profile for it. # If the driver is not allowed to configure service profiles, + * then the driver shall only use queues for which service profiles are pre- + * configured. + */ +/* Input (24 bytes) */ + +struct hwrm_queue_qportcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0) + /* rx path */ + #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1) + #define HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_QPORTCFG_INPUT_FLAGS_PATH_RX + uint16_t port_id; + /* + * Port ID of port for which the queue configuration is being queried. + * This field is only required when sent by IPC. + */ + uint16_t unused_0; +} __attribute__((packed)); + +/* Output (32 bytes) */ + +struct hwrm_queue_qportcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t max_configurable_queues; + /* The maximum number of queues that can be configured. */ + uint8_t max_configurable_lossless_queues; + /* The maximum number of lossless queues that can be configured. */ + uint8_t queue_cfg_allowed; + /* + * 0 - Not allowed. Non-zero - Allowed. If this value is non-zero, then + * the HWRM shall allow the host SW driver to configure queues using + * hwrm_queue_cfg. + */ + uint8_t queue_buffers_cfg_allowed; + /* + * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then + * the HWRM shall allow the host SW driver to configure queue buffers + * using hwrm_queue_buffers_cfg. + */ + uint8_t queue_pfcenable_cfg_allowed; + /* + * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then + * the HWRM shall allow the host SW driver to configure PFC using + * hwrm_queue_pfcenable_cfg. + */ + uint8_t queue_pri2cos_cfg_allowed; + /* + * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then + * the HWRM shall allow the host SW driver to configure Priority to CoS + * mapping using hwrm_queue_pri2cos_cfg. + */ + uint8_t queue_cos2bw_cfg_allowed; + /* + * 0 - Not allowed. Non-zero - Allowed If this value is non-zero, then + * the HWRM shall allow the host SW driver to configure CoS Bandwidth + * configuration using hwrm_queue_cos2bw_cfg. + */ + uint8_t queue_id0; + /* ID of CoS Queue 0. FF - Invalid id */ + uint8_t queue_id0_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t queue_id1; + /* ID of CoS Queue 1. FF - Invalid id */ + uint8_t queue_id1_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID1_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t queue_id2; + /* ID of CoS Queue 2. FF - Invalid id */ + uint8_t queue_id2_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID2_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID2_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID2_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t queue_id3; + /* ID of CoS Queue 3. FF - Invalid id */ + uint8_t queue_id3_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID3_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID3_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID3_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t queue_id4; + /* ID of CoS Queue 4. FF - Invalid id */ + uint8_t queue_id4_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID4_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID4_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID4_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t queue_id5; + /* ID of CoS Queue 5. FF - Invalid id */ + uint8_t queue_id5_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID5_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID5_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID5_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t queue_id6; + /* ID of CoS Queue 6. FF - Invalid id */ + uint8_t queue_id6_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID6_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID6_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID6_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t queue_id7; + /* ID of CoS Queue 7. FF - Invalid id */ + uint8_t queue_id7_service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID7_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID7_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID7_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_qcfg */ +/* + * Description: This function is called by a driver to query a queue + * configuration. + */ +/* Input (24 bytes) */ + +struct hwrm_queue_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0) + /* rx path */ + #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1) + #define HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_QCFG_INPUT_FLAGS_PATH_RX + uint32_t queue_id; + /* Queue ID of the queue. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_queue_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t queue_len; + /* This value is a the estimate packet length used in the TX arbiter. */ + uint8_t service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_QCFG_OUTPUT_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_QCFG_OUTPUT_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_QCFG_OUTPUT_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t unused_0; + uint8_t unused_1; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_cfg */ +/* Description: This function is called by a driver to configure a queue. */ +/* Input (40 bytes) */ + +struct hwrm_queue_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0) + /* rx path */ + #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1) + #define HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_CFG_INPUT_FLAGS_PATH_RX + uint32_t enables; + /* This bit must be '1' for the dflt_len field to be configured. */ + #define HWRM_QUEUE_CFG_INPUT_ENABLES_DFLT_LEN UINT32_C(0x1) + /* This bit must be '1' for the service_profile field to be configured. */ + #define HWRM_QUEUE_CFG_INPUT_ENABLES_SERVICE_PROFILE UINT32_C(0x2) + uint32_t queue_id; + /* Queue ID of queue that is to be configured by this function. */ + uint32_t dflt_len; + /* + * This value is a the estimate packet length used in the TX arbiter. + * Set to 0xFF... (All Fs) to not adjust this value. + */ + uint8_t service_profile; + /* This value is applicable to CoS queues only. */ + /* Lossy (best-effort) */ + #define HWRM_QUEUE_CFG_INPUT_SERVICE_PROFILE_LOSSY UINT32_C(0x0) + /* Lossless */ + #define HWRM_QUEUE_CFG_INPUT_SERVICE_PROFILE_LOSSLESS UINT32_C(0x1) + /* Set to 0xFF... (All Fs) if there is no service profile specified */ + #define HWRM_QUEUE_CFG_INPUT_SERVICE_PROFILE_UNKNOWN UINT32_C(0xff) + uint8_t unused_0[7]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_queue_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_buffers_qcfg */ +/* + * Description: This function is called by a driver to query configuration of + * the buffers assigned to a queue. + */ +/* Input (24 bytes) */ + +struct hwrm_queue_buffers_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0) + /* rx path */ + #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1) + #define HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_BUFFERS_QCFG_INPUT_FLAGS_PATH_RX + uint32_t queue_id; + /* Queue ID of queue that is to be configured by this function. */ +} __attribute__((packed)); + +/* Output (40 bytes) */ + +struct hwrm_queue_buffers_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t reserved; + /* Number of bytes allocated as reserved space for this queue. */ + uint32_t shared; + /* + * Number of bytes of shared buffer space for this queue. The changing + * of shared buffer size for one CoS may create an adverse effect on + * other CoSs sharing the same buffer. It is recommended that the driver + * does not modify the shared mbuf size without understanding the + * consequence of it. + */ + uint32_t xoff; + /* + * XOFF threshold of the queue. This is a high threshold value used to + * trigger XOFF. + */ + uint32_t xon; + /* + * XON threshold of the queue. This is the low threshold value used to + * trigger XON. + */ + uint32_t full; + /* + * FULL threshold of the queue. At this threshold, buffers allocated for + * this queue are full. Once this condition is asserted, packets on that + * queue are dropped. + */ + uint32_t notfull; + /* + * NOTFULL threshold of the queue. This threshold is used for the de- + * assertion of buffers full condition. + */ + uint32_t max; + /* + * The maximum number of bytes that will be allowed to be consumed by + * the queue. This value is the sum of both the number of bytes reserved + * for this queue and the maximum number of bytes of shared buffers + * allowed to be consumed by this queue. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_buffers_cfg */ +/* + * Description: This function is called by a driver to configure the buffering + * for a queue. + */ +/* Input (56 bytes) */ + +struct hwrm_queue_buffers_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_TX UINT32_C(0x0) + /* rx path */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_RX UINT32_C(0x1) + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_BUFFERS_CFG_INPUT_FLAGS_PATH_RX + uint32_t enables; + /* This bit must be '1' for the reserved field to be configured. */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_RESERVED UINT32_C(0x1) + /* This bit must be '1' for the shared field to be configured. */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_SHARED UINT32_C(0x2) + /* This bit must be '1' for the xoff field to be configured. */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_XOFF UINT32_C(0x4) + /* This bit must be '1' for the xon field to be configured. */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_XON UINT32_C(0x8) + /* This bit must be '1' for the full field to be configured. */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_FULL UINT32_C(0x10) + /* This bit must be '1' for the notfull field to be configured. */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_NOTFULL UINT32_C(0x20) + /* This bit must be '1' for the max field to be configured. */ + #define HWRM_QUEUE_BUFFERS_CFG_INPUT_ENABLES_MAX UINT32_C(0x40) + uint32_t queue_id; + /* Queue ID of queue that is to be configured by this function. */ + uint32_t reserved; + /* Number of bytes to be allocated as reserved space for this queue. */ + uint32_t shared; + /* + * Number of bytes of shared buffer space for this queue. The changing + * of shared buffer size for one CoS may create an adverse effect on + * other CoSs sharing the same buffer. It is recommended that the driver + * does not modify the shared mbuf size without understanding the + * consequence of it. + */ + uint32_t xoff; + /* + * XOFF threshold of the queue. This is a high threshold value used to + * trigger XOFF. + */ + uint32_t xon; + /* + * XON threshold of the queue. This is the low threshold value used to + * trigger XON. + */ + uint32_t full; + /* + * FULL threshold of the queue. At this threshold, buffers allocated for + * this queue are full. Once this condition is asserted, packets on that + * queue are dropped. + */ + uint32_t notfull; + /* + * NOTFULL threshold of the queue. This threshold is used for the de- + * assertion of buffers full condition. + */ + uint32_t max; + /* + * The maximum number of bytes that will be allowed to be consumed by + * the queue. This value is the sum of both the number of bytes reserved + * for this queue and the maximum number of bytes of shared buffers + * allowed to be consumed by this queue. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_queue_buffers_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_pfcenable_qcfg */ +/* + * Description: This function is called by a driver to query PFC configuration + * for different priorities on that port. This mapping can be different on + * different ports. + */ +/* Input (24 bytes) */ + +struct hwrm_queue_pfcenable_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* + * Port ID of port for which the table is being configured. The HWRM + * needs to check whether this function is allowed to configure pri2cos + * mapping on this port. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_queue_pfcenable_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t flags; + /* If set to 1, then PFC is enabled on PRI 0. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI0_PFC_ENABLED UINT32_C(0x1) + /* If set to 1, then PFC is enabled on PRI 1. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI1_PFC_ENABLED UINT32_C(0x2) + /* If set to 1, then PFC is enabled on PRI 2. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI2_PFC_ENABLED UINT32_C(0x4) + /* If set to 1, then PFC is enabled on PRI 3. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI3_PFC_ENABLED UINT32_C(0x8) + /* If set to 1, then PFC is enabled on PRI 4. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI4_PFC_ENABLED UINT32_C(0x10) + /* If set to 1, then PFC is enabled on PRI 5. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI5_PFC_ENABLED UINT32_C(0x20) + /* If set to 1, then PFC is enabled on PRI 6. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI6_PFC_ENABLED UINT32_C(0x40) + /* If set to 1, then PFC is enabled on PRI 7. */ + #define HWRM_QUEUE_PFCENABLE_QCFG_OUTPUT_FLAGS_PRI7_PFC_ENABLED UINT32_C(0x80) + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_pfcenable_cfg */ +/* + * Description: This function is called by a driver to configure the PFC enabled + * for different priorities on that port. This mapping can be different on + * different ports. + */ +/* Input (24 bytes) */ + +struct hwrm_queue_pfcenable_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* If set to 1, then PFC is requested to be enabled on PRI 0. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI0_PFC_ENABLED UINT32_C(0x1) + /* If set to 1, then PFC is requested to be enabled on PRI 1. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI1_PFC_ENABLED UINT32_C(0x2) + /* If set to 1, then PFC is requested to be enabled on PRI 2. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI2_PFC_ENABLED UINT32_C(0x4) + /* If set to 1, then PFC is requested to be enabled on PRI 3. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI3_PFC_ENABLED UINT32_C(0x8) + /* If set to 1, then PFC is requested to be enabled on PRI 4. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI4_PFC_ENABLED UINT32_C(0x10) + /* If set to 1, then PFC is requested to be enabled on PRI 5. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI5_PFC_ENABLED UINT32_C(0x20) + /* If set to 1, then PFC is requested to be enabled on PRI 6. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI6_PFC_ENABLED UINT32_C(0x40) + /* If set to 1, then PFC is requested to be enabled on PRI 7. */ + #define HWRM_QUEUE_PFCENABLE_CFG_INPUT_FLAGS_PRI7_PFC_ENABLED UINT32_C(0x80) + uint16_t port_id; + /* + * Port ID of port for which the table is being configured. The HWRM + * needs to check whether this function is allowed to configure pri2cos + * mapping on this port. + */ + uint16_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_queue_pfcenable_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_pri2cos_qcfg */ +/* + * Description: This function is called by a driver to query configuration of + * the priority to CoS queue mapping on the transmit side and receive side. This + * mapping can be different in each direction (TX or RX). This mapping can be + * different on different ports. Each CoS queue represents a Traffic Class (TC) + * on that port. + */ +/* Input (24 bytes) */ + +struct hwrm_queue_pri2cos_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0) + /* rx path */ + #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0) + #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_PATH_RX + /* + * When this bit is set to '1', the mapping is requested for inner VLAN + * PRI. + */ + #define HWRM_QUEUE_PRI2COS_QCFG_INPUT_FLAGS_IVLAN UINT32_C(0x2) + uint8_t port_id; + /* + * Port ID of port for which the table is being configured. The HWRM + * needs to check whether this function is allowed to configure pri2cos + * mapping on this port. + */ + uint8_t unused_0[3]; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_queue_pri2cos_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t pri0_cos_queue_id; + /* + * CoS Queue assigned to priority 0. This value can only be changed + * before traffic has started. + */ + uint8_t pri1_cos_queue_id; + /* + * CoS Queue assigned to priority 1. This value can only be changed + * before traffic has started. + */ + uint8_t pri2_cos_queue_id; + /* + * CoS Queue assigned to priority 2 This value can only be changed + * before traffic has started. + */ + uint8_t pri3_cos_queue_id; + /* + * CoS Queue assigned to priority 3. This value can only be changed + * before traffic has started. + */ + uint8_t pri4_cos_queue_id; + /* + * CoS Queue assigned to priority 4. This value can only be changed + * before traffic has started. + */ + uint8_t pri5_cos_queue_id; + /* + * CoS Queue assigned to priority 5. This value can only be changed + * before traffic has started. + */ + uint8_t pri6_cos_queue_id; + /* + * CoS Queue assigned to priority 6. This value can only be changed + * before traffic has started. + */ + uint8_t pri7_cos_queue_id; + /* + * CoS Queue assigned to priority 7. This value can only be changed + * before traffic has started. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_pri2cos_cfg */ +/* + * Description: This function is called by a driver to configure the priority to + * CoS queue mapping on the transmit side and receive side. This mapping can be + * different in each direction (TX or RX). This mapping can be different on + * different ports. Each CoS queue represents a Traffic Class (TC) on that port. + * This command configures the VLAN PRI-to-TC mapping for a specific port in + * specific direction. + */ +/* Input (40 bytes) */ + +struct hwrm_queue_pri2cos_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0) + /* rx path */ + #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0) + #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_LAST HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_PATH_RX + /* When this bit is '1', the mapping is for inner VLAN PRI. */ + #define HWRM_QUEUE_PRI2COS_CFG_INPUT_FLAGS_IVLAN UINT32_C(0x2) + uint32_t enables; + uint8_t port_id; + /* + * Port ID of port for which the table is being configured. The HWRM + * needs to check whether this function is allowed to configure pri2cos + * mapping on this port. + */ + uint8_t pri0_cos_queue_id; + /* + * CoS Queue assigned to priority 0. This value can only be changed + * before traffic has started. + */ + uint8_t pri1_cos_queue_id; + /* + * CoS Queue assigned to priority 1. This value can only be changed + * before traffic has started. + */ + uint8_t pri2_cos_queue_id; + /* + * CoS Queue assigned to priority 2 This value can only be changed + * before traffic has started. + */ + uint8_t pri3_cos_queue_id; + /* + * CoS Queue assigned to priority 3. This value can only be changed + * before traffic has started. + */ + uint8_t pri4_cos_queue_id; + /* + * CoS Queue assigned to priority 4. This value can only be changed + * before traffic has started. + */ + uint8_t pri5_cos_queue_id; + /* + * CoS Queue assigned to priority 5. This value can only be changed + * before traffic has started. + */ + uint8_t pri6_cos_queue_id; + /* + * CoS Queue assigned to priority 6. This value can only be changed + * before traffic has started. + */ + uint8_t pri7_cos_queue_id; + /* + * CoS Queue assigned to priority 7. This value can only be changed + * before traffic has started. + */ + uint8_t unused_0[7]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_queue_pri2cos_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_cos2bw_qcfg */ +/* + * Description: This function is called by a driver to query the BW to CoS queue + * mapping on the transmit side of a specific port. This mapping can be + * different on different ports. Each CoS queue represents a Traffic Class (TC) + * on that port. Each traffic class can be assigned a valid combination of the + * following: - Minimum bandwidth - Maximum bandwidth - Transmission selection + * algorithm (TSA) - Priority Level (only applies to strict priority COS) - + * Bandwidth weight # A CoS can be SP or non-SP: A SP CoS always gets the strict + * priority. Is an COS min BW is set to 0x0 then it is considered to be non-SP; + * this is a valid configuration. Note: SP provides lower latency in addition to + * reserved bandwidth # For both SP CoS and non-SP CoS, min BW can be specified + * to reserve specific amount of the port BW. # The min BW specified for a CoS + * shall not exceed max port bandwidth. # The total of min BWs specified for all + * CoS shall not exceed max port bandwidth. # For any non-SP CoS, the minimum + * bandwidth guarantees are subject to round-robin scheduling. This allows BW + * reservation with anti-starvation; one CoS will not block another CoS using + * RR. Note: The bandwidth guarantees for any non-SP CoS are met after servicing + * all SP CoS. # An SP CoS can potentially starve other lower priority SP CoS + * and non-SP CoS queues. This can occur to the extent the SP min exceeds the + * available port BW. # For any CoS, max BW can be specified to limit the BW + * consumed by the CoS. # The max BW specified for a CoS shall not exceed the + * max port bandwidth. # The WFQ provides a mechanism for sharing available + * bandwidth beyond the reserved minimums configured for each CoS. The WFQ + * scheduler is used to provide the percentages of remaining bandwidth after: * + * first servicing the reserved bandwidth for all SP CoS, * followed by the + * reserved bandwidth for all non-SP CoS * All CoS may participate in the WFQ # + * If a CoS does not have a configured max BW it may use all available bandwidth + * up to the max port bandwidth Minimum Bandwidth (min BW): # This is the + * guaranteed bandwidth for the COS. # A value of 0x0 is valid and it means that + * this COS is not guaranteed any bandwidth. A value of 0xFF.. (all Fs) means + * min BW is not specified. When the min BW is not specified, the HWRM can set + * it to any value it considers appropriate. Note: For a non-SP COS, the HWRM + * should set min BW to 0 when the min BW is not specified. For an SP COS, the + * HWRM should set min BW to some small value when the min BW is not specified. + * Maximum Bandwidth: # This is the bandwidth limit of the COS. # Values 0x0 and + * 0xFF.. (all Fs) are considered unspecified and the HWRM will set the maximum + * bandwidth to maximum port bandwidth. Priority Level: # It applies only to SP. + * # This parameter is ignored for non-SP. # 0-7 are valid values (higher value + * means higher priority) # A priority level can be assigned to at most one SP. + * # Invalid priority levels assignment for SPs shall result in failure. + * Additional notes: # The HWRM may have to use min and (max - min) to set + * appropriate counters of hardware rate limiters. # The bandwidth percentage as + * specified in the DCB TC BW assignment should be used by the driver to specify + * maximum bandwidth and bandwidth weight for a COS. For example, the driver + * should set max BW to 20 Gbps and weight to 50 for two COSs when these two + * COSs are assigned 50% share of 40 Gbps max port bandwidth. + */ +/* Input (24 bytes) */ + +struct hwrm_queue_cos2bw_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* + * Port ID of port for which the table is being configured. The HWRM + * needs to check whether this function is allowed to configure TC BW + * assignment on this port. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (112 bytes) */ + +struct hwrm_queue_cos2bw_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t queue_id0; + /* ID of CoS Queue 0. */ + uint8_t unused_0; + uint16_t unused_1; + uint32_t queue_id0_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id0_max_bw; + /* + * Maximum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id0_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id0_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id0_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id1; + /* ID of CoS Queue 1. */ + uint32_t queue_id1_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id1_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id1_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id1_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id1_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id2; + /* ID of CoS Queue 2. */ + uint32_t queue_id2_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id2_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id2_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id2_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id2_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id3; + /* ID of CoS Queue 3. */ + uint32_t queue_id3_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id3_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id3_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id3_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id3_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id4; + /* ID of CoS Queue 4. */ + uint32_t queue_id4_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id4_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id4_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id4_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id4_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id5; + /* ID of CoS Queue 5. */ + uint32_t queue_id5_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id5_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id5_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id5_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id5_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id6; + /* ID of CoS Queue 6. */ + uint32_t queue_id6_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id6_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id6_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id6_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id6_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id7; + /* ID of CoS Queue 7. */ + uint32_t queue_id7_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id7_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id7_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_QCFG_OUTPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id7_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id7_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t unused_5; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_queue_cos2bw_cfg */ +/* + * Description: This function is called by a driver to configure the BW to CoS + * queue mapping on the transmit side of a specific port. This mapping can be + * different on different ports. Each CoS queue represents a Traffic Class (TC) + * on that port. Each traffic class can be assigned a valid combination of the + * following: - Minimum bandwidth - Maximum bandwidth - Transmission selection + * algorithm (TSA) - Priority Level (only applies to strict priority COS) - + * Bandwidth weight # A CoS can be SP or non-SP: A SP CoS always gets the strict + * priority. Is an COS min BW is set to 0x0 then it is considered to be non-SP; + * this is a valid configuration. Note: SP provides lower latency in addition to + * reserved bandwidth # For both SP CoS and non-SP CoS, min BW can be specified + * to reserve specific amount of the port BW. # The min BW specified for a CoS + * shall not exceed max port bandwidth. # The total of min BWs specified for all + * CoS shall not exceed max port bandwidth. # For any non-SP CoS, the minimum + * bandwidth guarantees are subject to round-robin scheduling. This allows BW + * reservation with anti-starvation; one CoS will not block another CoS using + * RR. Note: The bandwidth guarantees for any non-SP CoS are met after servicing + * all SP CoS. # An SP CoS can potentially starve other lower priority SP CoS + * and non-SP CoS queues. This can occur to the extent the SP min exceeds the + * available port BW. # For any CoS, max BW can be specified to limit the BW + * consumed by the CoS. # The max BW specified for a CoS shall not exceed the + * max port bandwidth. # The WFQ provides a mechanism for sharing available + * bandwidth beyond the reserved minimums configured for each CoS. The WFQ + * scheduler is used to provide the percentages of remaining bandwidth after: - + * first servicing the reserved bandwidth for all SP CoS, - followed by the + * reserved bandwidth for all non-SP CoS - All CoS may participate in the WFQ # + * If a CoS does not have a configured max BW it may use all available bandwidth + * up to the max port bandwidth Minimum Bandwidth (min BW): # This is the + * guaranteed bandwidth for the COS. # A value of 0x0 is valid and it means that + * this COS is not guaranteed any bandwidth. A value of 0xFF.. (all Fs) means + * min BW is not specified. When the min BW is not specified, the HWRM can set + * it to any value it considers appropriate. Note: For a non-SP COS, the HWRM + * should set min BW to 0 when the min BW is not specified. For an SP COS, the + * HWRM should set min BW to some small value when the min BW is not specified. + * Maximum Bandwidth: # This is the bandwidth limit of the COS. # Values 0x0 and + * 0xFF.. (all Fs) are considered unspecified and the HWRM will set the maximum + * bandwidth to maximum port bandwidth. Priority Level: # It applies only to SP. + * # This parameter is ignored for non-SP. # 0-7 are valid values (higher value + * means higher priority) # A priority level can be assigned to at most one SP. + * # Invalid priority levels assignment for SPs shall result in failure. + * Additional notes: # The HWRM may have to use min and (max - min) to set + * appropriate counters of hardware rate limiters. # The bandwidth percentage as + * specified in the DCB TC BW assignment should be used by the driver to specify + * maximum bandwidth and bandwidth weight for a COS. For example, the driver + * should set max BW to 20 Gbps and weight to 50 for two COSs when these two + * COSs are assigned 50% share of 40 Gbps max port bandwidth. + */ +/* Input (128 bytes) */ + +struct hwrm_queue_cos2bw_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + uint32_t enables; + /* + * This bit must be '1' for the cos_queue_id0_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID0_VALID UINT32_C(0x1) + /* + * This bit must be '1' for the cos_queue_id1_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID1_VALID UINT32_C(0x2) + /* + * This bit must be '1' for the cos_queue_id2_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID2_VALID UINT32_C(0x4) + /* + * This bit must be '1' for the cos_queue_id3_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID3_VALID UINT32_C(0x8) + /* + * This bit must be '1' for the cos_queue_id4_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID4_VALID UINT32_C(0x10) + /* + * This bit must be '1' for the cos_queue_id5_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID5_VALID UINT32_C(0x20) + /* + * This bit must be '1' for the cos_queue_id6_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID6_VALID UINT32_C(0x40) + /* + * This bit must be '1' for the cos_queue_id7_valid field to be + * configured. + */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_ENABLES_COS_QUEUE_ID7_VALID UINT32_C(0x80) + uint16_t port_id; + /* + * Port ID of port for which the table is being configured. The HWRM + * needs to check whether this function is allowed to configure TC BW + * assignment on this port. + */ + uint8_t queue_id0; + /* ID of CoS Queue 0. */ + uint8_t unused_0; + uint32_t queue_id0_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id0_max_bw; + /* + * Maximum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id0_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id0_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id0_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id1; + /* ID of CoS Queue 1. */ + uint32_t queue_id1_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id1_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id1_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id1_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id1_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id2; + /* ID of CoS Queue 2. */ + uint32_t queue_id2_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id2_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id2_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id2_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id2_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id3; + /* ID of CoS Queue 3. */ + uint32_t queue_id3_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id3_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id3_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id3_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id3_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id4; + /* ID of CoS Queue 4. */ + uint32_t queue_id4_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id4_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id4_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id4_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id4_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id5; + /* ID of CoS Queue 5. */ + uint32_t queue_id5_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id5_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id5_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id5_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id5_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id6; + /* ID of CoS Queue 6. */ + uint32_t queue_id6_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id6_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id6_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id6_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id6_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t queue_id7; + /* ID of CoS Queue 7. */ + uint32_t queue_id7_min_bw; + /* + * Minimum BW allocated to CoS Queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint32_t queue_id7_max_bw; + /* + * Maximum BW allocated to CoS queue in Mbps. The HWRM will translate + * this value into byte counter and time interval used for this COS + * inside the device. + */ + uint8_t queue_id7_tsa_assign; + /* Transmission Selection Algorithm (TSA) for CoS Queue. */ + /* Strict Priority */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_SP UINT32_C(0x0) + /* Enhanced Transmission Selection */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_ETS UINT32_C(0x1) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST UINT32_C(0x2) + /* reserved */ + #define HWRM_QUEUE_COS2BW_CFG_INPUT_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST UINT32_C(0xff) + uint8_t queue_id7_pri_lvl; + /* + * Priority level for strict priority. Valid only when the tsa_assign is + * 0 - Strict Priority (SP) 0..7 - Valid values. 8..255 - Reserved. + */ + uint8_t queue_id7_bw_weight; + /* + * Weight used to allocate remaining BW for this COS after servicing + * guaranteed bandwidths for all COS. + */ + uint8_t unused_1[5]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_queue_cos2bw_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_alloc */ +/* + * Description: This VNIC is a resource in the RX side of the chip that is used + * to represent a virtual host "interface". # At the time of VNIC allocation or + * configuration, the function can specify whether it wants the requested VNIC + * to be the default VNIC for the function or not. # If a function requests + * allocation of a VNIC for the first time and a VNIC is successfully allocated + * by the HWRM, then the HWRM shall make the allocated VNIC as the default VNIC + * for that function. # The default VNIC shall be used for the default action + * for a partition or function. # For each VNIC allocated on a function, a + * mapping on the RX side to map the allocated VNIC to source virtual interface + * shall be performed by the HWRM. This should be hidden to the function driver + * requesting the VNIC allocation. This enables broadcast/multicast replication + * with source knockout. # If multicast replication with source knockout is + * enabled, then the internal VNIC to SVIF mapping data structures shall be + * programmed at the time of VNIC allocation. + */ +/* Input (24 bytes) */ + +struct hwrm_vnic_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is '1', this VNIC is requested to be the default VNIC + * for this function. + */ + #define HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT UINT32_C(0x1) + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t vnic_id; + /* Logical vnic ID */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_free */ +/* + * Description: Free a VNIC resource. Idle any resources associated with the + * VNIC as well as the VNIC. Reset and release all resources associated with the + * VNIC. + */ +/* Input (24 bytes) */ + +struct hwrm_vnic_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t vnic_id; + /* Logical vnic ID */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_cfg */ +/* Description: Configure the RX VNIC structure. */ +/* Input (40 bytes) */ + +struct hwrm_vnic_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is '1', the VNIC is requested to be the default VNIC + * for the function. + */ + #define HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT UINT32_C(0x1) + /* + * When this bit is '1', the VNIC is being configured to strip VLAN in + * the RX path. If set to '0', then VLAN stripping is disabled on this + * VNIC. + */ + #define HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE UINT32_C(0x2) + /* + * When this bit is '1', the VNIC is being configured to buffer receive + * packets in the hardware until the host posts new receive buffers. If + * set to '0', then bd_stall is being configured to be disabled on this + * VNIC. + */ + #define HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE UINT32_C(0x4) + /* + * When this bit is '1', the VNIC is being configured to receive both + * RoCE and non-RoCE traffic. If set to '0', then this VNIC is not + * configured to be operating in dual VNIC mode. + */ + #define HWRM_VNIC_CFG_INPUT_FLAGS_ROCE_DUAL_VNIC_MODE UINT32_C(0x8) + /* + * When this flag is set to '1', the VNIC is requested to be configured + * to receive only RoCE traffic. If this flag is set to '0', then this + * flag shall be ignored by the HWRM. If roce_dual_vnic_mode flag is set + * to '1', then the HWRM client shall not set this flag to '1'. + */ + #define HWRM_VNIC_CFG_INPUT_FLAGS_ROCE_ONLY_VNIC_MODE UINT32_C(0x10) + /* + * When a VNIC uses one destination ring group for certain application + * (e.g. Receive Flow Steering) where exact match is used to direct + * packets to a VNIC with one destination ring group only, there is no + * need to configure RSS indirection table for that VNIC as only one + * destination ring group is used. This flag is used to enable a mode + * where RSS is enabled in the VNIC using a RSS context for computing + * RSS hash but the RSS indirection table is not configured using + * hwrm_vnic_rss_cfg. If this mode is enabled, then the driver should + * not program RSS indirection table for the RSS context that is used + * for computing RSS hash only. + */ + #define HWRM_VNIC_CFG_INPUT_FLAGS_RSS_DFLT_CR_MODE UINT32_C(0x20) + uint32_t enables; + /* This bit must be '1' for the dflt_ring_grp field to be configured. */ + #define HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP UINT32_C(0x1) + /* This bit must be '1' for the rss_rule field to be configured. */ + #define HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE UINT32_C(0x2) + /* This bit must be '1' for the cos_rule field to be configured. */ + #define HWRM_VNIC_CFG_INPUT_ENABLES_COS_RULE UINT32_C(0x4) + /* This bit must be '1' for the lb_rule field to be configured. */ + #define HWRM_VNIC_CFG_INPUT_ENABLES_LB_RULE UINT32_C(0x8) + /* This bit must be '1' for the mru field to be configured. */ + #define HWRM_VNIC_CFG_INPUT_ENABLES_MRU UINT32_C(0x10) + uint16_t vnic_id; + /* Logical vnic ID */ + uint16_t dflt_ring_grp; + /* + * Default Completion ring for the VNIC. This ring will be chosen if + * packet does not match any RSS rules and if there is no COS rule. + */ + uint16_t rss_rule; + /* + * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if there is no + * RSS rule. + */ + uint16_t cos_rule; + /* + * RSS ID for COS rule/table structure. 0xFF... (All Fs) if there is no + * COS rule. + */ + uint16_t lb_rule; + /* + * RSS ID for load balancing rule/table structure. 0xFF... (All Fs) if + * there is no LB rule. + */ + uint16_t mru; + /* + * The maximum receive unit of the vnic. Each vnic is associated with a + * function. The vnic mru value overwrites the mru setting of the + * associated function. The HWRM shall make sure that vnic mru does not + * exceed the mru of the port the function is associated with. + */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_qcfg */ +/* + * Description: Query the RX VNIC structure. This function can be used by a PF + * driver to query its own VNIC resource or VNIC resource of its child VF. This + * function can also be used by a VF driver to query its own VNIC resource. + */ +/* Input (32 bytes) */ + +struct hwrm_vnic_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the vf_id_valid field to be configured. */ + #define HWRM_VNIC_QCFG_INPUT_ENABLES_VF_ID_VALID UINT32_C(0x1) + uint32_t vnic_id; + /* Logical vnic ID */ + uint16_t vf_id; + /* ID of Virtual Function whose VNIC resource is being queried. */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (32 bytes) */ + +struct hwrm_vnic_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t dflt_ring_grp; + /* Default Completion ring for the VNIC. */ + uint16_t rss_rule; + /* + * RSS ID for RSS rule/table structure. 0xFF... (All Fs) if there is no + * RSS rule. + */ + uint16_t cos_rule; + /* + * RSS ID for COS rule/table structure. 0xFF... (All Fs) if there is no + * COS rule. + */ + uint16_t lb_rule; + /* + * RSS ID for load balancing rule/table structure. 0xFF... (All Fs) if + * there is no LB rule. + */ + uint16_t mru; + /* The maximum receive unit of the vnic. */ + uint8_t unused_0; + uint8_t unused_1; + uint32_t flags; + /* When this bit is '1', the VNIC is the default VNIC for the function. */ + #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_DEFAULT UINT32_C(0x1) + /* + * When this bit is '1', the VNIC is configured to strip VLAN in the RX + * path. If set to '0', then VLAN stripping is disabled on this VNIC. + */ + #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_VLAN_STRIP_MODE UINT32_C(0x2) + /* + * When this bit is '1', the VNIC is configured to buffer receive + * packets in the hardware until the host posts new receive buffers. If + * set to '0', then bd_stall is disabled on this VNIC. + */ + #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_BD_STALL_MODE UINT32_C(0x4) + /* + * When this bit is '1', the VNIC is configured to receive both RoCE and + * non-RoCE traffic. If set to '0', then this VNIC is not configured to + * operate in dual VNIC mode. + */ + #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_ROCE_DUAL_VNIC_MODE UINT32_C(0x8) + /* + * When this flag is set to '1', the VNIC is configured to receive only + * RoCE traffic. When this flag is set to '0', the VNIC is not + * configured to receive only RoCE traffic. If roce_dual_vnic_mode flag + * and this flag both are set to '1', then it is an invalid + * configuration of the VNIC. The HWRM should not allow that type of + * mis-configuration by HWRM clients. + */ + #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_ROCE_ONLY_VNIC_MODE UINT32_C(0x10) + /* + * When a VNIC uses one destination ring group for certain application + * (e.g. Receive Flow Steering) where exact match is used to direct + * packets to a VNIC with one destination ring group only, there is no + * need to configure RSS indirection table for that VNIC as only one + * destination ring group is used. When this bit is set to '1', then the + * VNIC is enabled in a mode where RSS is enabled in the VNIC using a + * RSS context for computing RSS hash but the RSS indirection table is + * not configured. + */ + #define HWRM_VNIC_QCFG_OUTPUT_FLAGS_RSS_DFLT_CR_MODE UINT32_C(0x20) + uint32_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t unused_5; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_qcaps */ +/* + * Description: This function is used to query the capabilities of VNIC + * resources. + */ +/* Input (24 bytes) */ + +struct hwrm_vnic_qcaps_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_vnic_qcaps_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t mru; + /* The maximum receive unit that is settable on a vnic. */ + uint8_t unused_0; + uint8_t unused_1; + uint32_t flags; + /* Unused. */ + /* + * When this bit is '1', the capability of stripping VLAN in the RX path + * is supported on VNIC(s). If set to '0', then VLAN stripping + * capability is not supported on VNIC(s). + */ + #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_VLAN_STRIP_CAP UINT32_C(0x2) + /* + * When this bit is '1', the capability to buffer receive packets in the + * hardware until the host posts new receive buffers is supported on + * VNIC(s). If set to '0', then bd_stall capability is not supported on + * VNIC(s). + */ + #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_BD_STALL_CAP UINT32_C(0x4) + /* + * When this bit is '1', the capability to receive both RoCE and non- + * RoCE traffic on VNIC(s) is supported. If set to '0', then the + * capability to receive both RoCE and non-RoCE traffic on VNIC(s) is + * not supported. + */ + #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_ROCE_DUAL_VNIC_CAP UINT32_C(0x8) + /* + * When this bit is set to '1', the capability to configure a VNIC to + * receive only RoCE traffic is supported. When this flag is set to '0', + * the VNIC capability to configure to receive only RoCE traffic is not + * supported. + */ + #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_ROCE_ONLY_VNIC_CAP UINT32_C(0x10) + /* + * When this bit is set to '1', then the capability to enable a VNIC in + * a mode where RSS context without configuring RSS indirection table is + * supported (for RSS hash computation). When this bit is set to '0', + * then a VNIC can not be configured with a mode to enable RSS context + * without configuring RSS indirection table. + */ + #define HWRM_VNIC_QCAPS_OUTPUT_FLAGS_RSS_DFLT_CR_CAP UINT32_C(0x20) + uint32_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t unused_5; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_tpa_cfg */ +/* Description: This function is used to enable/configure TPA on the VNIC. */ +/* Input (40 bytes) */ + +struct hwrm_vnic_tpa_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is '1', the VNIC shall be configured to perform + * transparent packet aggregation (TPA) of non-tunneled TCP packets. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA UINT32_C(0x1) + /* + * When this bit is '1', the VNIC shall be configured to perform + * transparent packet aggregation (TPA) of tunneled TCP packets. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA UINT32_C(0x2) + /* + * When this bit is '1', the VNIC shall be configured to perform + * transparent packet aggregation (TPA) according to Windows Receive + * Segment Coalescing (RSC) rules. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE UINT32_C(0x4) + /* + * When this bit is '1', the VNIC shall be configured to perform + * transparent packet aggregation (TPA) according to Linux Generic + * Receive Offload (GRO) rules. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO UINT32_C(0x8) + /* + * When this bit is '1', the VNIC shall be configured to perform + * transparent packet aggregation (TPA) for TCP packets with IP ECN set + * to non-zero. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN UINT32_C(0x10) + /* + * When this bit is '1', the VNIC shall be configured to perform + * transparent packet aggregation (TPA) for GRE tunneled TCP packets + * only if all packets have the same GRE sequence. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ UINT32_C(0x20) + /* + * When this bit is '1' and the GRO mode is enabled, the VNIC shall be + * configured to perform transparent packet aggregation (TPA) for + * TCP/IPv4 packets with consecutively increasing IPIDs. In other words, + * the last packet that is being aggregated to an already existing + * aggregation context shall have IPID 1 more than the IPID of the last + * packet that was aggregated in that aggregation context. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO_IPID_CHECK UINT32_C(0x40) + /* + * When this bit is '1' and the GRO mode is enabled, the VNIC shall be + * configured to perform transparent packet aggregation (TPA) for TCP + * packets with the same TTL (IPv4) or Hop limit (IPv6) value. + */ + #define HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO_TTL_CHECK UINT32_C(0x80) + uint32_t enables; + /* This bit must be '1' for the max_agg_segs field to be configured. */ + #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS UINT32_C(0x1) + /* This bit must be '1' for the max_aggs field to be configured. */ + #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS UINT32_C(0x2) + /* This bit must be '1' for the max_agg_timer field to be configured. */ + #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_TIMER UINT32_C(0x4) + /* This bit must be '1' for the min_agg_len field to be configured. */ + #define HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN UINT32_C(0x8) + uint16_t vnic_id; + /* Logical vnic ID */ + uint16_t max_agg_segs; + /* + * This is the maximum number of TCP segments that can be aggregated + * (unit is Log2). Max value is 31. + */ + /* 1 segment */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_1 UINT32_C(0x0) + /* 2 segments */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_2 UINT32_C(0x1) + /* 4 segments */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_4 UINT32_C(0x2) + /* 8 segments */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_8 UINT32_C(0x3) + /* Any segment size larger than this is not valid */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX UINT32_C(0x1f) + uint16_t max_aggs; + /* + * This is the maximum number of aggregations this VNIC is allowed (unit + * is Log2). Max value is 7 + */ + /* 1 aggregation */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_1 UINT32_C(0x0) + /* 2 aggregations */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_2 UINT32_C(0x1) + /* 4 aggregations */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_4 UINT32_C(0x2) + /* 8 aggregations */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_8 UINT32_C(0x3) + /* 16 aggregations */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_16 UINT32_C(0x4) + /* Any aggregation size larger than this is not valid */ + #define HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX UINT32_C(0x7) + uint8_t unused_0; + uint8_t unused_1; + uint32_t max_agg_timer; + /* + * This is the maximum amount of time allowed for an aggregation context + * to complete after it was initiated. + */ + uint32_t min_agg_len; + /* + * This is the minimum amount of payload length required to start an + * aggregation context. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_tpa_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_tpa_qcfg */ +/* + * Description: This function can be used to query TPA configuration on the + * VNIC. + */ +/* Input (24 bytes) */ + +struct hwrm_vnic_tpa_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t vnic_id; + /* Logical vnic ID */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (32 bytes) */ + +struct hwrm_vnic_tpa_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t flags; + /* + * When this bit is '1', the VNIC is configured to perform transparent + * packet aggregation (TPA) of non-tunneled TCP packets. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_TPA UINT32_C(0x1) + /* + * When this bit is '1', the VNIC is configured to perform transparent + * packet aggregation (TPA) of tunneled TCP packets. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_ENCAP_TPA UINT32_C(0x2) + /* + * When this bit is '1', the VNIC is configured to perform transparent + * packet aggregation (TPA) according to Windows Receive Segment + * Coalescing (RSC) rules. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_RSC_WND_UPDATE UINT32_C(0x4) + /* + * When this bit is '1', the VNIC is configured to perform transparent + * packet aggregation (TPA) according to Linux Generic Receive Offload + * (GRO) rules. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_GRO UINT32_C(0x8) + /* + * When this bit is '1', the VNIC is configured to perform transparent + * packet aggregation (TPA) for TCP packets with IP ECN set to non-zero. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_AGG_WITH_ECN UINT32_C(0x10) + /* + * When this bit is '1', the VNIC is configured to perform transparent + * packet aggregation (TPA) for GRE tunneled TCP packets only if all + * packets have the same GRE sequence. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ UINT32_C(0x20) + /* + * When this bit is '1' and the GRO mode is enabled, the VNIC is + * configured to perform transparent packet aggregation (TPA) for + * TCP/IPv4 packets with consecutively increasing IPIDs. In other words, + * the last packet that is being aggregated to an already existing + * aggregation context shall have IPID 1 more than the IPID of the last + * packet that was aggregated in that aggregation context. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_GRO_IPID_CHECK UINT32_C(0x40) + /* + * When this bit is '1' and the GRO mode is enabled, the VNIC is + * configured to perform transparent packet aggregation (TPA) for TCP + * packets with the same TTL (IPv4) or Hop limit (IPv6) value. + */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_FLAGS_GRO_TTL_CHECK UINT32_C(0x80) + uint16_t max_agg_segs; + /* + * This is the maximum number of TCP segments that can be aggregated + * (unit is Log2). Max value is 31. + */ + /* 1 segment */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_1 UINT32_C(0x0) + /* 2 segments */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_2 UINT32_C(0x1) + /* 4 segments */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_4 UINT32_C(0x2) + /* 8 segments */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_8 UINT32_C(0x3) + /* Any segment size larger than this is not valid */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGG_SEGS_MAX UINT32_C(0x1f) + uint16_t max_aggs; + /* + * This is the maximum number of aggregations this VNIC is allowed (unit + * is Log2). Max value is 7 + */ + /* 1 aggregation */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_1 UINT32_C(0x0) + /* 2 aggregations */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_2 UINT32_C(0x1) + /* 4 aggregations */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_4 UINT32_C(0x2) + /* 8 aggregations */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_8 UINT32_C(0x3) + /* 16 aggregations */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_16 UINT32_C(0x4) + /* Any aggregation size larger than this is not valid */ + #define HWRM_VNIC_TPA_QCFG_OUTPUT_MAX_AGGS_MAX UINT32_C(0x7) + uint32_t max_agg_timer; + /* + * This is the maximum amount of time allowed for an aggregation context + * to complete after it was initiated. + */ + uint32_t min_agg_len; + /* + * This is the minimum amount of payload length required to start an + * aggregation context. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_rss_cfg */ +/* Description: This function is used to enable RSS configuration. */ +/* Input (48 bytes) */ + +struct hwrm_vnic_rss_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t hash_type; + /* + * When this bit is '1', the RSS hash shall be computed over source and + * destination IPv4 addresses of IPv4 packets. + */ + #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 UINT32_C(0x1) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv4 addresses and source/destination ports of + * TCP/IPv4 packets. + */ + #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 UINT32_C(0x2) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv4 addresses and source/destination ports of + * UDP/IPv4 packets. + */ + #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 UINT32_C(0x4) + /* + * When this bit is '1', the RSS hash shall be computed over source and + * destination IPv4 addresses of IPv6 packets. + */ + #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 UINT32_C(0x8) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv6 addresses and source/destination ports of + * TCP/IPv6 packets. + */ + #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 UINT32_C(0x10) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv6 addresses and source/destination ports of + * UDP/IPv6 packets. + */ + #define HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6 UINT32_C(0x20) + uint32_t unused_0; + uint64_t ring_grp_tbl_addr; + /* This is the address for rss ring group table */ + uint64_t hash_key_tbl_addr; + /* This is the address for rss hash key table */ + uint16_t rss_ctx_idx; + /* Index to the rss indirection table. */ + uint16_t unused_1[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_rss_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_rss_qcfg */ +/* Description: This function is used to query RSS context configuration. */ +/* Input (24 bytes) */ + +struct hwrm_vnic_rss_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t rss_ctx_idx; + /* Index to the rss indirection table. */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (64 bytes) */ + +struct hwrm_vnic_rss_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t hash_type; + /* + * When this bit is '1', the RSS hash shall be computed over source and + * destination IPv4 addresses of IPv4 packets. + */ + #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_IPV4 UINT32_C(0x1) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv4 addresses and source/destination ports of + * TCP/IPv4 packets. + */ + #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_TCP_IPV4 UINT32_C(0x2) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv4 addresses and source/destination ports of + * UDP/IPv4 packets. + */ + #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_UDP_IPV4 UINT32_C(0x4) + /* + * When this bit is '1', the RSS hash shall be computed over source and + * destination IPv4 addresses of IPv6 packets. + */ + #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_IPV6 UINT32_C(0x8) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv6 addresses and source/destination ports of + * TCP/IPv6 packets. + */ + #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_TCP_IPV6 UINT32_C(0x10) + /* + * When this bit is '1', the RSS hash shall be computed over + * source/destination IPv6 addresses and source/destination ports of + * UDP/IPv6 packets. + */ + #define HWRM_VNIC_RSS_QCFG_OUTPUT_HASH_TYPE_UDP_IPV6 UINT32_C(0x20) + uint32_t unused_0; + uint32_t hash_key[10]; + /* This is the value of rss hash key */ + uint32_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_plcmodes_cfg */ +/* + * Description: This function can be used to set placement mode configuration of + * the VNIC. + */ +/* Input (40 bytes) */ + +struct hwrm_vnic_plcmodes_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * When this bit is '1', the VNIC shall be configured to use regular + * placement algorithm. By default, the regular placement algorithm + * shall be enabled on the VNIC. + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_REGULAR_PLACEMENT UINT32_C(0x1) + /* + * When this bit is '1', the VNIC shall be configured use the jumbo + * placement algorithm. + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT UINT32_C(0x2) + /* + * When this bit is '1', the VNIC shall be configured to enable Header- + * Data split for IPv4 packets according to the following rules: # If + * the packet is identified as TCP/IPv4, then the packet is split at the + * beginning of the TCP payload. # If the packet is identified as + * UDP/IPv4, then the packet is split at the beginning of UDP payload. # + * If the packet is identified as non-TCP and non-UDP IPv4 packet, then + * the packet is split at the beginning of the upper layer protocol + * header carried in the IPv4 packet. + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_IPV4 UINT32_C(0x4) + /* + * When this bit is '1', the VNIC shall be configured to enable Header- + * Data split for IPv6 packets according to the following rules: # If + * the packet is identified as TCP/IPv6, then the packet is split at the + * beginning of the TCP payload. # If the packet is identified as + * UDP/IPv6, then the packet is split at the beginning of UDP payload. # + * If the packet is identified as non-TCP and non-UDP IPv6 packet, then + * the packet is split at the beginning of the upper layer protocol + * header carried in the IPv6 packet. + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_IPV6 UINT32_C(0x8) + /* + * When this bit is '1', the VNIC shall be configured to enable Header- + * Data split for FCoE packets at the beginning of FC payload. + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_FCOE UINT32_C(0x10) + /* + * When this bit is '1', the VNIC shall be configured to enable Header- + * Data split for RoCE packets at the beginning of RoCE payload (after + * BTH/GRH headers). + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_HDS_ROCE UINT32_C(0x20) + uint32_t enables; + /* + * This bit must be '1' for the jumbo_thresh_valid field to be + * configured. + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_ENABLES_JUMBO_THRESH_VALID UINT32_C(0x1) + /* This bit must be '1' for the hds_offset_valid field to be configured. */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_ENABLES_HDS_OFFSET_VALID UINT32_C(0x2) + /* + * This bit must be '1' for the hds_threshold_valid field to be + * configured. + */ + #define HWRM_VNIC_PLCMODES_CFG_INPUT_ENABLES_HDS_THRESHOLD_VALID UINT32_C(0x4) + uint32_t vnic_id; + /* Logical vnic ID */ + uint16_t jumbo_thresh; + /* + * When jumbo placement algorithm is enabled, this value is used to + * determine the threshold for jumbo placement. Packets with length + * larger than this value will be placed according to the jumbo + * placement algorithm. + */ + uint16_t hds_offset; + /* + * This value is used to determine the offset into packet buffer where + * the split data (payload) will be placed according to one of of HDS + * placement algorithm. The lengths of packet buffers provided for split + * data shall be larger than this value. + */ + uint16_t hds_threshold; + /* + * When one of the HDS placement algorithm is enabled, this value is + * used to determine the threshold for HDS placement. Packets with + * length larger than this value will be placed according to the HDS + * placement algorithm. This value shall be in multiple of 4 bytes. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_plcmodes_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_plcmodes_qcfg */ +/* + * Description: This function can be used to query placement mode configuration + * of the VNIC. + */ +/* Input (24 bytes) */ + +struct hwrm_vnic_plcmodes_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t vnic_id; + /* Logical vnic ID */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_vnic_plcmodes_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t flags; + /* + * When this bit is '1', the VNIC is configured to use regular placement + * algorithm. + */ + #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_REGULAR_PLACEMENT UINT32_C(0x1) + /* + * When this bit is '1', the VNIC is configured to use the jumbo + * placement algorithm. + */ + #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_JUMBO_PLACEMENT UINT32_C(0x2) + /* + * When this bit is '1', the VNIC is configured to enable Header-Data + * split for IPv4 packets. + */ + #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_IPV4 UINT32_C(0x4) + /* + * When this bit is '1', the VNIC is configured to enable Header-Data + * split for IPv6 packets. + */ + #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_IPV6 UINT32_C(0x8) + /* + * When this bit is '1', the VNIC is configured to enable Header-Data + * split for FCoE packets. + */ + #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_FCOE UINT32_C(0x10) + /* + * When this bit is '1', the VNIC is configured to enable Header-Data + * split for RoCE packets. + */ + #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_HDS_ROCE UINT32_C(0x20) + /* + * When this bit is '1', the VNIC is configured to be the default VNIC + * of the requesting function. + */ + #define HWRM_VNIC_PLCMODES_QCFG_OUTPUT_FLAGS_DFLT_VNIC UINT32_C(0x40) + uint16_t jumbo_thresh; + /* + * When jumbo placement algorithm is enabled, this value is used to + * determine the threshold for jumbo placement. Packets with length + * larger than this value will be placed according to the jumbo + * placement algorithm. + */ + uint16_t hds_offset; + /* + * This value is used to determine the offset into packet buffer where + * the split data (payload) will be placed according to one of of HDS + * placement algorithm. The lengths of packet buffers provided for split + * data shall be larger than this value. + */ + uint16_t hds_threshold; + /* + * When one of the HDS placement algorithm is enabled, this value is + * used to determine the threshold for HDS placement. Packets with + * length larger than this value will be placed according to the HDS + * placement algorithm. This value shall be in multiple of 4 bytes. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_rss_cos_lb_ctx_alloc */ +/* Description: This function is used to allocate COS/Load Balance context. */ +/* Input (16 bytes) */ + +struct hwrm_vnic_rss_cos_lb_ctx_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_rss_cos_lb_ctx_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t rss_cos_lb_ctx_id; + /* rss_cos_lb_ctx_id is 16 b */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_vnic_rss_cos_lb_ctx_free */ +/* Description: This function can be used to free COS/Load Balance context. */ +/* Input (24 bytes) */ + +struct hwrm_vnic_rss_cos_lb_ctx_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t rss_cos_lb_ctx_id; + /* rss_cos_lb_ctx_id is 16 b */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_vnic_rss_cos_lb_ctx_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_ring_alloc */ +/* + * Description: This command allocates and does basic preparation for a ring. + */ +/* Input (80 bytes) */ + +struct hwrm_ring_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the Reserved1 field to be configured. */ + #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED1 UINT32_C(0x1) + /* This bit must be '1' for the Reserved2 field to be configured. */ + #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED2 UINT32_C(0x2) + /* This bit must be '1' for the Reserved3 field to be configured. */ + #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED3 UINT32_C(0x4) + /* + * This bit must be '1' for the stat_ctx_id_valid field to be + * configured. + */ + #define HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID UINT32_C(0x8) + /* This bit must be '1' for the Reserved4 field to be configured. */ + #define HWRM_RING_ALLOC_INPUT_ENABLES_RESERVED4 UINT32_C(0x10) + /* This bit must be '1' for the max_bw_valid field to be configured. */ + #define HWRM_RING_ALLOC_INPUT_ENABLES_MAX_BW_VALID UINT32_C(0x20) + uint8_t ring_type; + /* Ring Type. */ + /* Completion Ring (CR) */ + #define HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL UINT32_C(0x0) + /* TX Ring (TR) */ + #define HWRM_RING_ALLOC_INPUT_RING_TYPE_TX UINT32_C(0x1) + /* RX Ring (RR) */ + #define HWRM_RING_ALLOC_INPUT_RING_TYPE_RX UINT32_C(0x2) + uint8_t unused_0; + uint16_t unused_1; + uint64_t page_tbl_addr; + /* This value is a pointer to the page table for the Ring. */ + uint32_t fbo; + /* First Byte Offset of the first entry in the first page. */ + uint8_t page_size; + /* + * Actual page size in 2^page_size. The supported range is increments in + * powers of 2 from 16 bytes to 1GB. - 4 = 16 B Page size is 16 B. - 12 + * = 4 KB Page size is 4 KB. - 13 = 8 KB Page size is 8 KB. - 16 = 64 KB + * Page size is 64 KB. - 21 = 2 MB Page size is 2 MB. - 22 = 4 MB Page + * size is 4 MB. - 30 = 1 GB Page size is 1 GB. + */ + uint8_t page_tbl_depth; + /* + * This value indicates the depth of page table. For this version of the + * specification, value other than 0 or 1 shall be considered as an + * invalid value. When the page_tbl_depth = 0, then it is treated as a + * special case with the following. 1. FBO and page size fields are not + * valid. 2. page_tbl_addr is the physical address of the first element + * of the ring. + */ + uint8_t unused_2; + uint8_t unused_3; + uint32_t length; + /* + * Number of 16B units in the ring. Minimum size for a ring is 16 16B + * entries. + */ + uint16_t logical_id; + /* + * Logical ring number for the ring to be allocated. This value + * determines the position in the doorbell area where the update to the + * ring will be made. For completion rings, this value is also the MSI-X + * vector number for the function the completion ring is associated + * with. + */ + uint16_t cmpl_ring_id; + /* + * This field is used only when ring_type is a TX ring. This value + * indicates what completion ring the TX ring is associated with. + */ + uint16_t queue_id; + /* + * This field is used only when ring_type is a TX ring. This value + * indicates what CoS queue the TX ring is associated with. + */ + uint8_t unused_4; + uint8_t unused_5; + uint32_t reserved1; + /* This field is reserved for the future use. It shall be set to 0. */ + uint16_t reserved2; + /* This field is reserved for the future use. It shall be set to 0. */ + uint8_t unused_6; + uint8_t unused_7; + uint32_t reserved3; + /* This field is reserved for the future use. It shall be set to 0. */ + uint32_t stat_ctx_id; + /* + * This field is used only when ring_type is a TX ring. This input + * indicates what statistics context this ring should be associated + * with. + */ + uint32_t reserved4; + /* This field is reserved for the future use. It shall be set to 0. */ + uint32_t max_bw; + /* + * This field is used only when ring_type is a TX ring. Maximum BW + * allocated to this TX ring in Mbps. The HWRM will translate this value + * into byte counter and time interval used for this ring inside the + * device. + */ + uint8_t int_mode; + /* + * This field is used only when ring_type is a Completion ring. This + * value indicates what interrupt mode should be used on this completion + * ring. Note: In the legacy interrupt mode, no more than 16 completion + * rings are allowed. + */ + /* Legacy INTA */ + #define HWRM_RING_ALLOC_INPUT_INT_MODE_LEGACY UINT32_C(0x0) + /* Reserved */ + #define HWRM_RING_ALLOC_INPUT_INT_MODE_RSVD UINT32_C(0x1) + /* MSI-X */ + #define HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX UINT32_C(0x2) + /* No Interrupt - Polled mode */ + #define HWRM_RING_ALLOC_INPUT_INT_MODE_POLL UINT32_C(0x3) + uint8_t unused_8[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_ring_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t ring_id; + /* Physical number of ring allocated. */ + uint16_t logical_ring_id; + /* Logical number of ring allocated. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_ring_free */ +/* + * Description: This command is used to free a ring and associated resources. + */ +/* Input (24 bytes) */ + +struct hwrm_ring_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t ring_type; + /* Ring Type. */ + /* Completion Ring (CR) */ + #define HWRM_RING_FREE_INPUT_RING_TYPE_CMPL UINT32_C(0x0) + /* TX Ring (TR) */ + #define HWRM_RING_FREE_INPUT_RING_TYPE_TX UINT32_C(0x1) + /* RX Ring (RR) */ + #define HWRM_RING_FREE_INPUT_RING_TYPE_RX UINT32_C(0x2) + uint8_t unused_0; + uint16_t ring_id; + /* Physical number of ring allocated. */ + uint32_t unused_1; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_ring_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_ring_cmpl_ring_qaggint_params */ +/* + * Description: This command is used to query aggregation and interrupt related + * parameters specified on a given completion ring. + */ +/* Input (24 bytes) */ + +struct hwrm_ring_cmpl_ring_qaggint_params_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t ring_id; + /* Physical number of completion ring. */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (32 bytes) */ + +struct hwrm_ring_cmpl_ring_qaggint_params_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t flags; + /* + * When this bit is set to '1', interrupt max timer is reset whenever a + * completion is received. + */ + #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS_OUTPUT_FLAGS_TIMER_RESET UINT32_C(0x1) + /* + * When this bit is set to '1', ring idle mode aggregation will be + * enabled. + */ + #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS_OUTPUT_FLAGS_RING_IDLE UINT32_C(0x2) + uint16_t num_cmpl_dma_aggr; + /* Number of completions to aggregate before DMA during the normal mode. */ + uint16_t num_cmpl_dma_aggr_during_int; + /* + * Number of completions to aggregate before DMA during the interrupt + * mode. + */ + uint16_t cmpl_aggr_dma_tmr; + /* + * Timer in unit of 80-nsec used to aggregate completions before DMA + * during the normal mode (not in interrupt mode). + */ + uint16_t cmpl_aggr_dma_tmr_during_int; + /* + * Timer in unit of 80-nsec used to aggregate completions before DMA + * during the interrupt mode. + */ + uint16_t int_lat_tmr_min; + /* Minimum time (in unit of 80-nsec) between two interrupts. */ + uint16_t int_lat_tmr_max; + /* + * Maximum wait time (in unit of 80-nsec) spent aggregating completions + * before signaling the interrupt after the interrupt is enabled. + */ + uint16_t num_cmpl_aggr_int; + /* + * Minimum number of completions aggregated before signaling an + * interrupt. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_ring_cmpl_ring_cfg_aggint_params */ +/* + * Description: This command is used to configure aggregation and interrupt + * related parameters specified on a given completion ring. + */ +/* Input (40 bytes) */ + +struct hwrm_ring_cmpl_ring_cfg_aggint_params_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t ring_id; + /* Physical number of completion ring. */ + uint16_t flags; + /* + * When this bit is set to '1', interrupt latency max timer is reset + * whenever a completion is received. + */ + #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET UINT32_C(0x1) + /* + * When this bit is set to '1', ring idle mode aggregation will be + * enabled. + */ + #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE UINT32_C(0x2) + uint16_t num_cmpl_dma_aggr; + /* Number of completions to aggregate before DMA during the normal mode. */ + uint16_t num_cmpl_dma_aggr_during_int; + /* + * Number of completions to aggregate before DMA during the interrupt + * mode. + */ + uint16_t cmpl_aggr_dma_tmr; + /* + * Timer in unit of 80-nsec used to aggregate completions before DMA + * during the normal mode (not in interrupt mode). + */ + uint16_t cmpl_aggr_dma_tmr_during_int; + /* + * Timer in unit of 80-nsec used to aggregate completions before DMA + * during the interrupt mode. + */ + uint16_t int_lat_tmr_min; + /* Minimum time (in unit of 80-nsec) between two interrupts. */ + uint16_t int_lat_tmr_max; + /* + * Maximum wait time (in unit of 80-nsec) spent aggregating cmpls before + * signaling the interrupt after the interrupt is enabled. + */ + uint16_t num_cmpl_aggr_int; + /* + * Minimum number of completions aggregated before signaling an + * interrupt. + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_ring_cmpl_ring_cfg_aggint_params_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_ring_reset */ +/* + * Description: This command is used to reset a given ring. When an RX ring is + * being reset, the HWRM shall perform TPA flush on all VNICs associated with + * the RX ring that is being reset. + */ +/* Input (24 bytes) */ + +struct hwrm_ring_reset_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t ring_type; + /* Ring Type. */ + /* Completion Ring (CR) */ + #define HWRM_RING_RESET_INPUT_RING_TYPE_CMPL UINT32_C(0x0) + /* TX Ring (TR) */ + #define HWRM_RING_RESET_INPUT_RING_TYPE_TX UINT32_C(0x1) + /* RX Ring (RR) */ + #define HWRM_RING_RESET_INPUT_RING_TYPE_RX UINT32_C(0x2) + uint8_t unused_0; + uint16_t ring_id; + /* Physical number of the ring. */ + uint32_t unused_1; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_ring_reset_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_ring_grp_alloc */ +/* + * Description: This API allocates and does basic preparation for a ring group. + */ +/* Input (24 bytes) */ + +struct hwrm_ring_grp_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t cr; + /* This value identifies the CR associated with the ring group. */ + uint16_t rr; + /* This value identifies the main RR associated with the ring group. */ + uint16_t ar; + /* + * This value identifies the aggregation RR associated with the ring + * group. If this value is 0xFF... (All Fs), then no Aggregation ring + * will be set. + */ + uint16_t sc; + /* + * This value identifies the statistics context associated with the ring + * group. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_ring_grp_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t ring_group_id; + /* + * This is the ring group ID value. Use this value to program the + * default ring group for the VNIC or as table entries in an RSS/COS + * context. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_ring_grp_free */ +/* + * Description: This API frees a ring group and associated resources. # If a + * ring in the ring group is reset or free, then the associated rings in the + * ring group shall also be reset/free using hwrm_ring_free. # A function driver + * shall always use hwrm_ring_grp_free after freeing all rings in a group. # As + * a part of executing this command, the HWRM shall reset all associated ring + * group resources. + */ +/* Input (24 bytes) */ + +struct hwrm_ring_grp_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t ring_group_id; + /* This is the ring group ID value. */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_ring_grp_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_l2_filter_alloc */ +/* + * Description: An L2 filter is a filter resource that is used to identify a + * vnic or ring for a packet based on layer 2 fields. Layer 2 fields for + * encapsulated packets include both outer L2 header and/or inner l2 header of + * encapsulated packet. The L2 filter resource covers the following OS specific + * L2 filters. Linux/FreeBSD (per function): # Broadcast enable/disable # List + * of individual multicast filters # All multicast enable/disable filter # + * Unicast filters # Promiscuous mode VMware: # Broadcast enable/disable (per + * physical function) # All multicast enable/disable (per function) # Unicast + * filters per ring or vnic # Promiscuous mode per PF Windows: # Broadcast + * enable/disable (per physical function) # List of individual multicast filters + * (Driver needs to advertise the maximum number of filters supported) # All + * multicast enable/disable per physical function # Unicast filters per vnic # + * Promiscuous mode per PF Implementation notes on the use of VNIC in this + * command: # By default, these filters belong to default vnic for the function. + * # Once these filters are set up, only destination VNIC can be modified. # If + * the destination VNIC is not specified in this command, then the HWRM shall + * only create an l2 context id. HWRM Implementation notes for multicast + * filters: # The hwrm_filter_alloc command can be used to set up multicast + * filters (perfect match or partial match). Each individual function driver can + * set up multicast filters independently. # The HWRM needs to keep track of + * multicast filters set up by function drivers and maintain multicast group + * replication records to enable a subset of functions to receive traffic for a + * specific multicast address. # When a specific multicast filter cannot be set, + * the HWRM shall return an error. In this error case, the driver should fall + * back to using one general filter (rather than specific) for all multicast + * traffic. # When the SR-IOV is enabled, the HWRM needs to additionally track + * source knockout per multicast group record. Examples of setting unicast + * filters: For a unicast MAC based filter, one can use a combination of the + * fields and masks provided in this command to set up the filter. Below are + * some examples: # MAC + no VLAN filter: This filter is used to identify + * traffic that does not contain any VLAN tags and matches destination (or + * source) MAC address. This filter can be set up by setting only l2_addr field + * to be a valid field. All other fields are not valid. The following value is + * set for l2_addr. l2_addr = MAC # MAC + Any VLAN filter: This filter is used + * to identify traffic that carries single VLAN tag and matches (destination or + * source) MAC address. This filter can be set up by setting only l2_addr and + * l2_ovlan_mask fields to be valid fields. All other fields are not valid. The + * following values are set for those two valid fields. l2_addr = MAC, + * l2_ovlan_mask = 0xFFFF # MAC + no VLAN or VLAN ID=0: This filter is used to + * identify untagged traffic that does not contain any VLAN tags or a VLAN tag + * with VLAN ID = 0 and matches destination (or source) MAC address. This filter + * can be set up by setting only l2_addr and l2_ovlan fields to be valid fields. + * All other fields are not valid. The following value are set for l2_addr and + * l2_ovlan. l2_addr = MAC, l2_ovlan = 0x0 # MAC + no VLAN or any VLAN: This + * filter is used to identify traffic that contains zero or 1 VLAN tag and + * matches destination (or source) MAC address. This filter can be set up by + * setting only l2_addr, l2_ovlan, and l2_mask fields to be valid fields. All + * other fields are not valid. The following value are set for l2_addr, + * l2_ovlan, and l2_mask fields. l2_addr = MAC, l2_ovlan = 0x0, l2_ovlan_mask = + * 0xFFFF # MAC + VLAN ID filter: This filter can be set up by setting only + * l2_addr, l2_ovlan, and l2_ovlan_mask fields to be valid fields. All other + * fields are not valid. The following values are set for those three valid + * fields. l2_addr = MAC, l2_ovlan = VLAN ID, l2_ovlan_mask = 0xF000 + */ +/* Input (96 bytes) */ + +struct hwrm_cfa_l2_filter_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0) + /* rx path */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0) + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_LAST HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX + /* + * Setting of this flag indicates the applicability to the loopback + * path. + */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x2) + /* + * Setting of this flag indicates drop action. If this flag is not set, + * then it should be considered accept action. + */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_DROP UINT32_C(0x4) + /* + * If this flag is set, all t_l2_* fields are invalid and they should + * not be specified. If this flag is set, then l2_* fields refer to + * fields of outermost L2 header. + */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST UINT32_C(0x8) + uint32_t enables; + /* This bit must be '1' for the l2_addr field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR UINT32_C(0x1) + /* This bit must be '1' for the l2_addr_mask field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK UINT32_C(0x2) + /* This bit must be '1' for the l2_ovlan field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_OVLAN UINT32_C(0x4) + /* This bit must be '1' for the l2_ovlan_mask field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_OVLAN_MASK UINT32_C(0x8) + /* This bit must be '1' for the l2_ivlan field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN UINT32_C(0x10) + /* This bit must be '1' for the l2_ivlan_mask field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN_MASK UINT32_C(0x20) + /* This bit must be '1' for the t_l2_addr field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_ADDR UINT32_C(0x40) + /* This bit must be '1' for the t_l2_addr_mask field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_ADDR_MASK UINT32_C(0x80) + /* This bit must be '1' for the t_l2_ovlan field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_OVLAN UINT32_C(0x100) + /* This bit must be '1' for the t_l2_ovlan_mask field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_OVLAN_MASK UINT32_C(0x200) + /* This bit must be '1' for the t_l2_ivlan field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_IVLAN UINT32_C(0x400) + /* This bit must be '1' for the t_l2_ivlan_mask field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_T_L2_IVLAN_MASK UINT32_C(0x800) + /* This bit must be '1' for the src_type field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_SRC_TYPE UINT32_C(0x1000) + /* This bit must be '1' for the src_id field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_SRC_ID UINT32_C(0x2000) + /* This bit must be '1' for the tunnel_type field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x4000) + /* This bit must be '1' for the dst_id field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID UINT32_C(0x8000) + /* This bit must be '1' for the mirror_vnic_id field to be configured. */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x10000) + uint8_t l2_addr[6]; + /* + * This value sets the match value for the L2 MAC address. Destination + * MAC address for RX path. Source MAC address for TX path. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t l2_addr_mask[6]; + /* + * This value sets the mask value for the L2 address. A value of 0 will + * mask the corresponding bit from compare. + */ + uint16_t l2_ovlan; + /* This value sets VLAN ID value for outer VLAN. */ + uint16_t l2_ovlan_mask; + /* + * This value sets the mask value for the ovlan id. A value of 0 will + * mask the corresponding bit from compare. + */ + uint16_t l2_ivlan; + /* This value sets VLAN ID value for inner VLAN. */ + uint16_t l2_ivlan_mask; + /* + * This value sets the mask value for the ivlan id. A value of 0 will + * mask the corresponding bit from compare. + */ + uint8_t unused_2; + uint8_t unused_3; + uint8_t t_l2_addr[6]; + /* + * This value sets the match value for the tunnel L2 MAC address. + * Destination MAC address for RX path. Source MAC address for TX path. + */ + uint8_t unused_4; + uint8_t unused_5; + uint8_t t_l2_addr_mask[6]; + /* + * This value sets the mask value for the tunnel L2 address. A value of + * 0 will mask the corresponding bit from compare. + */ + uint16_t t_l2_ovlan; + /* This value sets VLAN ID value for tunnel outer VLAN. */ + uint16_t t_l2_ovlan_mask; + /* + * This value sets the mask value for the tunnel ovlan id. A value of 0 + * will mask the corresponding bit from compare. + */ + uint16_t t_l2_ivlan; + /* This value sets VLAN ID value for tunnel inner VLAN. */ + uint16_t t_l2_ivlan_mask; + /* + * This value sets the mask value for the tunnel ivlan id. A value of 0 + * will mask the corresponding bit from compare. + */ + uint8_t src_type; + /* This value identifies the type of source of the packet. */ + /* Network port */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_NPORT UINT32_C(0x0) + /* Physical function */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_PF UINT32_C(0x1) + /* Virtual function */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_VF UINT32_C(0x2) + /* Virtual NIC of a function */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_VNIC UINT32_C(0x3) + /* Embedded processor for CFA management */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_KONG UINT32_C(0x4) + /* Embedded processor for OOB management */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_APE UINT32_C(0x5) + /* Embedded processor for RoCE */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_BONO UINT32_C(0x6) + /* Embedded processor for network proxy functions */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_SRC_TYPE_TANG UINT32_C(0x7) + uint8_t unused_6; + uint32_t src_id; + /* + * This value is the id of the source. For a network port, it represents + * port_id. For a physical function, it represents fid. For a virtual + * function, it represents vf_id. For a vnic, it represents vnic_id. For + * embedded processors, this id is not valid. Notes: 1. The function ID + * is implied if it src_id is not provided for a src_type that is either + */ + uint8_t tunnel_type; + /* Tunnel Type. */ + /* Non-tunnel */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0) + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + /* Network Virtualization Generic Routing Encapsulation (NVGRE) */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2) + /* Generic Routing Encapsulation (GRE) inside Ethernet payload */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3) + /* IP in IP */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + /* Multi-Protocol Lable Switching (MPLS) */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6) + /* Stateless Transport Tunnel (STT) */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7) + /* Generic Routing Encapsulation (GRE) inside IP datagram payload */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8) + /* Any tunneled traffic */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff) + uint8_t unused_7; + uint16_t dst_id; + /* + * If set, this value shall represent the Logical VNIC ID of the + * destination VNIC for the RX path and network port id of the + * destination port for the TX path. + */ + uint16_t mirror_vnic_id; + /* Logical VNIC ID of the VNIC where traffic is mirrored. */ + uint8_t pri_hint; + /* + * This hint is provided to help in placing the filter in the filter + * table. + */ + /* No preference */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_NO_PREFER UINT32_C(0x0) + /* Above the given filter */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_ABOVE_FILTER UINT32_C(0x1) + /* Below the given filter */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_BELOW_FILTER UINT32_C(0x2) + /* As high as possible */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_MAX UINT32_C(0x3) + /* As low as possible */ + #define HWRM_CFA_L2_FILTER_ALLOC_INPUT_PRI_HINT_MIN UINT32_C(0x4) + uint8_t unused_8; + uint32_t unused_9; + uint64_t l2_filter_id_hint; + /* + * This is the ID of the filter that goes along with the pri_hint. This + * field is valid only for the following values. 1 - Above the given + * filter 2 - Below the given filter + */ +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_cfa_l2_filter_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t l2_filter_id; + /* + * This value identifies a set of CFA data structures used for an L2 + * context. + */ + uint32_t flow_id; + /* + * This is the ID of the flow associated with this filter. This value + * shall be used to match and associate the flow identifier returned in + * completion records. A value of 0xFFFFFFFF shall indicate no flow id. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_l2_filter_free */ +/* + * Description: Free a L2 filter. The HWRM shall free all associated filter + * resources with the L2 filter. + */ +/* Input (24 bytes) */ + +struct hwrm_cfa_l2_filter_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t l2_filter_id; + /* + * This value identifies a set of CFA data structures used for an L2 + * context. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_l2_filter_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_l2_filter_cfg */ +/* Description: Change the configuration of an existing L2 filter */ +/* Input (40 bytes) */ + +struct hwrm_cfa_l2_filter_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0) + /* rx path */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0) + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_LAST HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_PATH_RX + /* + * Setting of this flag indicates drop action. If this flag is not set, + * then it should be considered accept action. + */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_FLAGS_DROP UINT32_C(0x2) + uint32_t enables; + /* This bit must be '1' for the dst_id field to be configured. */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_ENABLES_DST_ID UINT32_C(0x1) + /* + * This bit must be '1' for the new_mirror_vnic_id field to be + * configured. + */ + #define HWRM_CFA_L2_FILTER_CFG_INPUT_ENABLES_NEW_MIRROR_VNIC_ID UINT32_C(0x2) + uint64_t l2_filter_id; + /* + * This value identifies a set of CFA data structures used for an L2 + * context. + */ + uint32_t dst_id; + /* + * If set, this value shall represent the Logical VNIC ID of the + * destination VNIC for the RX path and network port id of the + * destination port for the TX path. + */ + uint32_t new_mirror_vnic_id; + /* New Logical VNIC ID of the VNIC where traffic is mirrored. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_l2_filter_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_l2_set_rx_mask */ +/* Description: This command will set rx mask of the function. */ +/* Input (56 bytes) */ + +struct hwrm_cfa_l2_set_rx_mask_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t vnic_id; + /* VNIC ID */ + uint32_t mask; + /* Reserved for future use. */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_RESERVED UINT32_C(0x1) + /* + * When this bit is '1', the function is requested to accept multi-cast + * packets specified by the multicast addr table. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST UINT32_C(0x2) + /* + * When this bit is '1', the function is requested to accept all multi- + * cast packets. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST UINT32_C(0x4) + /* + * When this bit is '1', the function is requested to accept broadcast + * packets. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST UINT32_C(0x8) + /* + * When this bit is '1', the function is requested to be put in the + * promiscuous mode. The HWRM should accept any function to set up + * promiscuous mode. The HWRM shall follow the semantics below for the + * promiscuous mode support. # When partitioning is not enabled on a + * port (i.e. single PF on the port), then the PF shall be allowed to be + * in the promiscuous mode. When the PF is in the promiscuous mode, then + * it shall receive all host bound traffic on that port. # When + * partitioning is enabled on a port (i.e. multiple PFs per port) and a + * PF on that port is in the promiscuous mode, then the PF receives all + * traffic within that partition as identified by a unique identifier + * for the PF (e.g. S-Tag). If a unique outer VLAN for the PF is + * specified, then the setting of promiscuous mode on that PF shall + * result in the PF receiving all host bound traffic with matching outer + * VLAN. # A VF shall can be set in the promiscuous mode. In the + * promiscuous mode, the VF does not receive any traffic unless a unique + * outer VLAN for the VF is specified. If a unique outer VLAN for the VF + * is specified, then the setting of promiscuous mode on that VF shall + * result in the VF receiving all host bound traffic with the matching + * outer VLAN. # The HWRM shall allow the setting of promiscuous mode on + * a function independently from the promiscuous mode settings on other + * functions. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS UINT32_C(0x10) + /* + * If this flag is set, the corresponding RX filters shall be set up to + * cover multicast/broadcast filters for the outermost Layer 2 + * destination MAC address field. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_OUTERMOST UINT32_C(0x20) + /* + * If this flag is set, the corresponding RX filters shall be set up to + * cover multicast/broadcast filters for the VLAN-tagged packets that + * match the TPID and VID fields of VLAN tags in the VLAN tag table + * specified in this command. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY UINT32_C(0x40) + /* + * If this flag is set, the corresponding RX filters shall be set up to + * cover multicast/broadcast filters for non-VLAN tagged packets and + * VLAN-tagged packets that match the TPID and VID fields of VLAN tags + * in the VLAN tag table specified in this command. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN UINT32_C(0x80) + /* + * If this flag is set, the corresponding RX filters shall be set up to + * cover multicast/broadcast filters for non-VLAN tagged packets and + * VLAN-tagged packets matching any VLAN tag. If this flag is set, then + * the HWRM shall ignore VLAN tags specified in vlan_tag_tbl. If none of + * vlanonly, vlan_nonvlan, and anyvlan_nonvlan flags is set, then the + * HWRM shall ignore VLAN tags specified in vlan_tag_tbl. The HWRM + * client shall set at most one flag out of vlanonly, vlan_nonvlan, and + * anyvlan_nonvlan. + */ + #define HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN UINT32_C(0x100) + uint64_t mc_tbl_addr; + /* This is the address for mcast address tbl. */ + uint32_t num_mc_entries; + /* + * This value indicates how many entries in mc_tbl are valid. Each entry + * is 6 bytes. + */ + uint32_t unused_0; + uint64_t vlan_tag_tbl_addr; + /* + * This is the address for VLAN tag table. Each VLAN entry in the table + * is 4 bytes of a VLAN tag including TPID, PCP, DEI, and VID fields in + * network byte order. + */ + uint32_t num_vlan_tags; + /* + * This value indicates how many entries in vlan_tag_tbl are valid. Each + * entry is 4 bytes. + */ + uint32_t unused_1; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_l2_set_rx_mask_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_tunnel_filter_alloc */ +/* + * Description: This is a tunnel filter that uses fields from tunnel header in + * addition to l2 context. The tunnel filter applies to receive side only. The + * l2_* fields in this command represent fields of inner L2 header. They are + * optional to be specified. It allows l2_filter_id to be created with outer L2 + * header fields that can be shared with multiple tunnel filters specified as + * combinations of inner L2 header fields, tunnel type, and VNI. + */ +/* Input (88 bytes) */ + +struct hwrm_cfa_tunnel_filter_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Setting of this flag indicates the applicability to the loopback + * path. + */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x1) + uint32_t enables; + /* This bit must be '1' for the l2_filter_id field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1) + /* This bit must be '1' for the l2_addr field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR UINT32_C(0x2) + /* This bit must be '1' for the l2_ivlan field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L2_IVLAN UINT32_C(0x4) + /* This bit must be '1' for the l3_addr field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L3_ADDR UINT32_C(0x8) + /* This bit must be '1' for the l3_addr_type field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_L3_ADDR_TYPE UINT32_C(0x10) + /* This bit must be '1' for the t_l3_addr_type field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_T_L3_ADDR_TYPE UINT32_C(0x20) + /* This bit must be '1' for the t_l3_addr field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_T_L3_ADDR UINT32_C(0x40) + /* This bit must be '1' for the tunnel_type field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x80) + /* This bit must be '1' for the vni field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_VNI UINT32_C(0x100) + /* This bit must be '1' for the dst_vnic_id field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_DST_VNIC_ID UINT32_C(0x200) + /* This bit must be '1' for the mirror_vnic_id field to be configured. */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x400) + uint64_t l2_filter_id; + /* + * This value identifies a set of CFA data structures used for an L2 + * context. + */ + uint8_t l2_addr[6]; + /* + * This value sets the match value for the inner L2 MAC address. + * Destination MAC address for RX path. Source MAC address for TX path. + */ + uint16_t l2_ivlan; + /* + * This value sets VLAN ID value for inner VLAN. Only 12-bits of VLAN ID + * are used in setting the filter. + */ + uint32_t l3_addr[4]; + /* + * The value of inner destination IP address to be used in filtering. + * For IPv4, first four bytes represent the IP address. + */ + uint32_t t_l3_addr[4]; + /* + * The value of tunnel destination IP address to be used in filtering. + * For IPv4, first four bytes represent the IP address. + */ + uint8_t l3_addr_type; + /* + * This value indicates the type of inner IP address. 4 - IPv4 6 - IPv6 + * All others are invalid. + */ + uint8_t t_l3_addr_type; + /* + * This value indicates the type of tunnel IP address. 4 - IPv4 6 - IPv6 + * All others are invalid. + */ + uint8_t tunnel_type; + /* Tunnel Type. */ + /* Non-tunnel */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0) + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + /* Network Virtualization Generic Routing Encapsulation (NVGRE) */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2) + /* Generic Routing Encapsulation (GRE) inside Ethernet payload */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3) + /* IP in IP */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + /* Multi-Protocol Lable Switching (MPLS) */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6) + /* Stateless Transport Tunnel (STT) */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7) + /* Generic Routing Encapsulation (GRE) inside IP datagram payload */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8) + /* Any tunneled traffic */ + #define HWRM_CFA_TUNNEL_FILTER_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff) + uint8_t unused_0; + uint32_t vni; + /* + * Virtual Network Identifier (VNI). Only valid with tunnel_types VXLAN, + * NVGRE, and Geneve. Only lower 24-bits of VNI field are used in + * setting up the filter. + */ + uint32_t dst_vnic_id; + /* Logical VNIC ID of the destination VNIC. */ + uint32_t mirror_vnic_id; + /* Logical VNIC ID of the VNIC where traffic is mirrored. */ +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_cfa_tunnel_filter_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t tunnel_filter_id; + /* This value is an opaque id into CFA data structures. */ + uint32_t flow_id; + /* + * This is the ID of the flow associated with this filter. This value + * shall be used to match and associate the flow identifier returned in + * completion records. A value of 0xFFFFFFFF shall indicate no flow id. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_tunnel_filter_free */ +/* Description: Free a tunnel filter */ +/* Input (24 bytes) */ + +struct hwrm_cfa_tunnel_filter_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t tunnel_filter_id; + /* This value is an opaque id into CFA data structures. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_tunnel_filter_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_encap_record_alloc */ +/* + * Description: This command is used to create an encapsulation record. The + * source MAC address and source IP address specified for the source property + * checks shall be used in the encapsulation where applicable. + */ +/* Input (32 bytes) */ + +struct hwrm_cfa_encap_record_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Setting of this flag indicates the applicability to the loopback + * path. + */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x1) + uint8_t encap_type; + /* Encapsulation Type. */ + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_VXLAN UINT32_C(0x1) + /* Network Virtualization Generic Routing Encapsulation (NVGRE) */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_NVGRE UINT32_C(0x2) + /* Generic Routing Encapsulation (GRE) after inside Ethernet payload */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_L2GRE UINT32_C(0x3) + /* IP in IP */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_IPIP UINT32_C(0x4) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_GENEVE UINT32_C(0x5) + /* Multi-Protocol Lable Switching (MPLS) */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_MPLS UINT32_C(0x6) + /* VLAN */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_VLAN UINT32_C(0x7) + /* Generic Routing Encapsulation (GRE) inside IP datagram payload */ + #define HWRM_CFA_ENCAP_RECORD_ALLOC_INPUT_ENCAP_TYPE_IPGRE UINT32_C(0x8) + uint8_t unused_0; + uint16_t unused_1; + uint32_t encap_data[16]; + /* This value is encap data used for the given encap type. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_encap_record_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t encap_record_id; + /* This value is an opaque id into CFA data structures. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_encap_record_free */ +/* Description: Free an encap record */ +/* Input (24 bytes) */ + +struct hwrm_cfa_encap_record_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t encap_record_id; + /* This value is an opaque id into CFA data structures. */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_encap_record_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_ntuple_filter_alloc */ +/* + * Description: This is a ntuple filter that uses fields from L4/L3 header and + * optionally fields from L2. The ntuple filters apply to receive traffic only. + * All L2/L3/L4 header fields are specified in network byte order. These filters + * can be used for Receive Flow Steering (RFS). # For ethertype value, only + * 0x0800 (IPv4) and 0x86dd (IPv6) shall be supported for ntuple filters. # If a + * field specified in this command is not enabled as a valid field, then that + * field shall not be used in matching packet header fields against this filter. + */ +/* Input (128 bytes) */ + +struct hwrm_cfa_ntuple_filter_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Setting of this flag indicates the applicability to the loopback + * path. + */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_LOOPBACK UINT32_C(0x1) + /* + * Setting of this flag indicates drop action. If this flag is not set, + * then it should be considered accept action. + */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_DROP UINT32_C(0x2) + uint32_t enables; + /* This bit must be '1' for the l2_filter_id field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1) + /* This bit must be '1' for the ethertype field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_ETHERTYPE UINT32_C(0x2) + /* This bit must be '1' for the tunnel_type field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x4) + /* This bit must be '1' for the src_macaddr field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_MACADDR UINT32_C(0x8) + /* This bit must be '1' for the ipaddr_type field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_IPADDR_TYPE UINT32_C(0x10) + /* This bit must be '1' for the src_ipaddr field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_IPADDR UINT32_C(0x20) + /* This bit must be '1' for the src_ipaddr_mask field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_IPADDR_MASK UINT32_C(0x40) + /* This bit must be '1' for the dst_ipaddr field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_IPADDR UINT32_C(0x80) + /* This bit must be '1' for the dst_ipaddr_mask field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_IPADDR_MASK UINT32_C(0x100) + /* This bit must be '1' for the ip_protocol field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_IP_PROTOCOL UINT32_C(0x200) + /* This bit must be '1' for the src_port field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_PORT UINT32_C(0x400) + /* This bit must be '1' for the src_port_mask field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_SRC_PORT_MASK UINT32_C(0x800) + /* This bit must be '1' for the dst_port field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_PORT UINT32_C(0x1000) + /* This bit must be '1' for the dst_port_mask field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_PORT_MASK UINT32_C(0x2000) + /* This bit must be '1' for the pri_hint field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_PRI_HINT UINT32_C(0x4000) + /* This bit must be '1' for the ntuple_filter_id field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_NTUPLE_FILTER_ID UINT32_C(0x8000) + /* This bit must be '1' for the dst_id field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_ID UINT32_C(0x10000) + /* This bit must be '1' for the mirror_vnic_id field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x20000) + /* This bit must be '1' for the dst_macaddr field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_DST_MACADDR UINT32_C(0x40000) + uint64_t l2_filter_id; + /* + * This value identifies a set of CFA data structures used for an L2 + * context. + */ + uint8_t src_macaddr[6]; + /* This value indicates the source MAC address in the Ethernet header. */ + uint16_t ethertype; /* big endian */ + /* This value indicates the ethertype in the Ethernet header. */ + uint8_t ip_addr_type; + /* + * This value indicates the type of IP address. 4 - IPv4 6 - IPv6 All + * others are invalid. + */ + /* invalid */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_UNKNOWN UINT32_C(0x0) + /* IPv4 */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV4 UINT32_C(0x4) + /* IPv6 */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6) + uint8_t ip_protocol; + /* + * The value of protocol filed in IP header. Applies to UDP and TCP + * traffic. 6 - UDP 17 - TCP + */ + /* invalid */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_PROTOCOL_UNKNOWN UINT32_C(0x0) + /* UDP */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_PROTOCOL_UDP UINT32_C(0x6) + /* TCP */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_IP_PROTOCOL_TCP UINT32_C(0x11) + uint16_t dst_id; + /* + * If set, this value shall represent the Logical VNIC ID of the + * destination VNIC for the RX path and network port id of the + * destination port for the TX path. + */ + uint16_t mirror_vnic_id; + /* Logical VNIC ID of the VNIC where traffic is mirrored. */ + uint8_t tunnel_type; + /* + * This value indicates the tunnel type for this filter. If this field + * is not specified, then the filter shall apply to both non-tunneled + * and tunneled packets. If this field conflicts with the tunnel_type + * specified in the l2_filter_id, then the HWRM shall return an error + * for this command. + */ + /* Non-tunnel */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0) + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + /* Network Virtualization Generic Routing Encapsulation (NVGRE) */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2) + /* Generic Routing Encapsulation (GRE) inside Ethernet payload */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3) + /* IP in IP */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + /* Multi-Protocol Lable Switching (MPLS) */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6) + /* Stateless Transport Tunnel (STT) */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7) + /* Generic Routing Encapsulation (GRE) inside IP datagram payload */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8) + /* Any tunneled traffic */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff) + uint8_t pri_hint; + /* + * This hint is provided to help in placing the filter in the filter + * table. + */ + /* No preference */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_NO_PREFER UINT32_C(0x0) + /* Above the given filter */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_ABOVE UINT32_C(0x1) + /* Below the given filter */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_BELOW UINT32_C(0x2) + /* As high as possible */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_HIGHEST UINT32_C(0x3) + /* As low as possible */ + #define HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_PRI_HINT_LOWEST UINT32_C(0x4) + uint32_t src_ipaddr[4]; /* big endian */ + /* + * The value of source IP address to be used in filtering. For IPv4, + * first four bytes represent the IP address. + */ + uint32_t src_ipaddr_mask[4]; /* big endian */ + /* + * The value of source IP address mask to be used in filtering. For + * IPv4, first four bytes represent the IP address mask. + */ + uint32_t dst_ipaddr[4]; /* big endian */ + /* + * The value of destination IP address to be used in filtering. For + * IPv4, first four bytes represent the IP address. + */ + uint32_t dst_ipaddr_mask[4]; /* big endian */ + /* + * The value of destination IP address mask to be used in filtering. For + * IPv4, first four bytes represent the IP address mask. + */ + uint16_t src_port; /* big endian */ + /* + * The value of source port to be used in filtering. Applies to UDP and + * TCP traffic. + */ + uint16_t src_port_mask; /* big endian */ + /* + * The value of source port mask to be used in filtering. Applies to UDP + * and TCP traffic. + */ + uint16_t dst_port; /* big endian */ + /* + * The value of destination port to be used in filtering. Applies to UDP + * and TCP traffic. + */ + uint16_t dst_port_mask; /* big endian */ + /* + * The value of destination port mask to be used in filtering. Applies + * to UDP and TCP traffic. + */ + uint64_t ntuple_filter_id_hint; + /* This is the ID of the filter that goes along with the pri_hint. */ +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_cfa_ntuple_filter_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t ntuple_filter_id; + /* This value is an opaque id into CFA data structures. */ + uint32_t flow_id; + /* + * This is the ID of the flow associated with this filter. This value + * shall be used to match and associate the flow identifier returned in + * completion records. A value of 0xFFFFFFFF shall indicate no flow id. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_ntuple_filter_free */ +/* Description: Free an ntuple filter */ +/* Input (24 bytes) */ + +struct hwrm_cfa_ntuple_filter_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t ntuple_filter_id; + /* This value is an opaque id into CFA data structures. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_ntuple_filter_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_ntuple_filter_cfg */ +/* Description: Configure an ntuple filter with new destination VNIC */ +/* Input (40 bytes) */ + +struct hwrm_cfa_ntuple_filter_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the new_dst_id field to be configured. */ + #define HWRM_CFA_NTUPLE_FILTER_CFG_INPUT_ENABLES_NEW_DST_ID UINT32_C(0x1) + /* + * This bit must be '1' for the new_mirror_vnic_id field to be + * configured. + */ + #define HWRM_CFA_NTUPLE_FILTER_CFG_INPUT_ENABLES_NEW_MIRROR_VNIC_ID UINT32_C(0x2) + uint32_t unused_0; + uint64_t ntuple_filter_id; + /* This value is an opaque id into CFA data structures. */ + uint32_t new_dst_id; + /* + * If set, this value shall represent the new Logical VNIC ID of the + * destination VNIC for the RX path and new network port id of the + * destination port for the TX path. + */ + uint32_t new_mirror_vnic_id; + /* New Logical VNIC ID of the VNIC where traffic is mirrored. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_ntuple_filter_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_em_flow_alloc */ +/* + * Description: This is a generic Exact Match (EM) flow that uses fields from + * L4/L3/L2 headers. The EM flows apply to transmit and receive traffic. All + * L2/L3/L4 header fields are specified in network byte order. For each EM flow, + * there is an associated set of actions specified. For tunneled packets, all + * L2/L3/L4 fields specified are fields of inner headers unless otherwise + * specified. # If a field specified in this command is not enabled as a valid + * field, then that field shall not be used in matching packet header fields + * against this EM flow entry. + */ +/* Input (112 bytes) */ + +struct hwrm_cfa_em_flow_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * Enumeration denoting the RX, TX type of the resource. This + * enumeration is used for resources that are similar for both TX and RX + * paths of the chip. + */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH UINT32_C(0x1) + /* tx path */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_TX (UINT32_C(0x0) << 0) + /* rx path */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_RX (UINT32_C(0x1) << 0) + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_LAST HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PATH_RX + /* + * Setting of this flag indicates enabling of a byte counter for a given + * flow. + */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_BYTE_CTR UINT32_C(0x2) + /* + * Setting of this flag indicates enabling of a packet counter for a + * given flow. + */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_PKT_CTR UINT32_C(0x4) + /* + * Setting of this flag indicates de-capsulation action for the given + * flow. + */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_DECAP UINT32_C(0x8) + /* + * Setting of this flag indicates encapsulation action for the given + * flow. + */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_ENCAP UINT32_C(0x10) + /* + * Setting of this flag indicates drop action. If this flag is not set, + * then it should be considered accept action. + */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_FLAGS_DROP UINT32_C(0x20) + uint32_t enables; + /* This bit must be '1' for the l2_filter_id field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_L2_FILTER_ID UINT32_C(0x1) + /* This bit must be '1' for the tunnel_type field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_TUNNEL_TYPE UINT32_C(0x2) + /* This bit must be '1' for the tunnel_id field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_TUNNEL_ID UINT32_C(0x4) + /* This bit must be '1' for the src_macaddr field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_SRC_MACADDR UINT32_C(0x8) + /* This bit must be '1' for the dst_macaddr field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_MACADDR UINT32_C(0x10) + /* This bit must be '1' for the ovlan_vid field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_OVLAN_VID UINT32_C(0x20) + /* This bit must be '1' for the ivlan_vid field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_IVLAN_VID UINT32_C(0x40) + /* This bit must be '1' for the ethertype field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_ETHERTYPE UINT32_C(0x80) + /* This bit must be '1' for the src_ipaddr field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_SRC_IPADDR UINT32_C(0x100) + /* This bit must be '1' for the dst_ipaddr field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_IPADDR UINT32_C(0x200) + /* This bit must be '1' for the ipaddr_type field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_IPADDR_TYPE UINT32_C(0x400) + /* This bit must be '1' for the ip_protocol field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_IP_PROTOCOL UINT32_C(0x800) + /* This bit must be '1' for the src_port field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_SRC_PORT UINT32_C(0x1000) + /* This bit must be '1' for the dst_port field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_PORT UINT32_C(0x2000) + /* This bit must be '1' for the dst_id field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_DST_ID UINT32_C(0x4000) + /* This bit must be '1' for the mirror_vnic_id field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_MIRROR_VNIC_ID UINT32_C(0x8000) + /* This bit must be '1' for the encap_record_id field to be configured. */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_ENCAP_RECORD_ID UINT32_C(0x10000) + uint64_t l2_filter_id; + /* + * This value identifies a set of CFA data structures used for an L2 + * context. + */ + uint8_t tunnel_type; + /* Tunnel Type. */ + /* Non-tunnel */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_NONTUNNEL UINT32_C(0x0) + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + /* Network Virtualization Generic Routing Encapsulation (NVGRE) */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_NVGRE UINT32_C(0x2) + /* Generic Routing Encapsulation (GRE) inside Ethernet payload */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_L2GRE UINT32_C(0x3) + /* IP in IP */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_IPIP UINT32_C(0x4) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + /* Multi-Protocol Lable Switching (MPLS) */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_MPLS UINT32_C(0x6) + /* Stateless Transport Tunnel (STT) */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_STT UINT32_C(0x7) + /* Generic Routing Encapsulation (GRE) inside IP datagram payload */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_IPGRE UINT32_C(0x8) + /* Any tunneled traffic */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_TUNNEL_TYPE_ANYTUNNEL UINT32_C(0xff) + uint8_t unused_0; + uint16_t unused_1; + uint32_t tunnel_id; + /* + * Tunnel identifier. Virtual Network Identifier (VNI). Only valid with + * tunnel_types VXLAN, NVGRE, and Geneve. Only lower 24-bits of VNI + * field are used in setting up the filter. + */ + uint8_t src_macaddr[6]; + /* This value indicates the source MAC address in the Ethernet header. */ + uint8_t unused_2; + uint8_t unused_3; + uint8_t dst_macaddr[6]; + /* + * This value indicates the destination MAC address in the Ethernet + * header. + */ + uint16_t ovlan_vid; + /* + * This value indicates the VLAN ID of the outer VLAN tag in the + * Ethernet header. + */ + uint16_t ivlan_vid; + /* + * This value indicates the VLAN ID of the inner VLAN tag in the + * Ethernet header. + */ + uint16_t ethertype; /* big endian */ + /* This value indicates the ethertype in the Ethernet header. */ + uint8_t ip_addr_type; + /* + * This value indicates the type of IP address. 4 - IPv4 6 - IPv6 All + * others are invalid. + */ + /* invalid */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_UNKNOWN UINT32_C(0x0) + /* IPv4 */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV4 UINT32_C(0x4) + /* IPv6 */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_ADDR_TYPE_IPV6 UINT32_C(0x6) + uint8_t ip_protocol; + /* + * The value of protocol filed in IP header. Applies to UDP and TCP + * traffic. 6 - UDP 17 - TCP + */ + /* invalid */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_PROTOCOL_UNKNOWN UINT32_C(0x0) + /* UDP */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_PROTOCOL_UDP UINT32_C(0x6) + /* TCP */ + #define HWRM_CFA_EM_FLOW_ALLOC_INPUT_IP_PROTOCOL_TCP UINT32_C(0x11) + uint8_t unused_4; + uint8_t unused_5; + uint32_t src_ipaddr[4]; /* big endian */ + /* + * The value of source IP address to be used in filtering. For IPv4, + * first four bytes represent the IP address. + */ + uint32_t dst_ipaddr[4]; /* big endian */ + /* + * The value of destination IP address to be used in filtering. For + * IPv4, first four bytes represent the IP address. + */ + uint16_t src_port; /* big endian */ + /* + * The value of source port to be used in filtering. Applies to UDP and + * TCP traffic. + */ + uint16_t dst_port; /* big endian */ + /* + * The value of destination port to be used in filtering. Applies to UDP + * and TCP traffic. + */ + uint16_t dst_id; + /* + * If set, this value shall represent the Logical VNIC ID of the + * destination VNIC for the RX path and network port id of the + * destination port for the TX path. + */ + uint16_t mirror_vnic_id; + /* Logical VNIC ID of the VNIC where traffic is mirrored. */ + uint32_t encap_record_id; + /* Logical ID of the encapsulation record. */ + uint32_t unused_6; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_cfa_em_flow_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t em_filter_id; + /* This value is an opaque id into CFA data structures. */ + uint32_t flow_id; + /* + * This is the ID of the flow associated with this filter. This value + * shall be used to match and associate the flow identifier returned in + * completion records. A value of 0xFFFFFFFF shall indicate no flow id. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_em_flow_free */ +/* Description: Free an EM flow table entry */ +/* Input (24 bytes) */ + +struct hwrm_cfa_em_flow_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t em_filter_id; + /* This value is an opaque id into CFA data structures. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_em_flow_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_cfa_em_flow_cfg */ +/* Description: Configure an EM flow with new destination VNIC */ +/* Input (40 bytes) */ + +struct hwrm_cfa_em_flow_cfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the new_dst_id field to be configured. */ + #define HWRM_CFA_EM_FLOW_CFG_INPUT_ENABLES_NEW_DST_ID UINT32_C(0x1) + /* + * This bit must be '1' for the new_mirror_vnic_id field to be + * configured. + */ + #define HWRM_CFA_EM_FLOW_CFG_INPUT_ENABLES_NEW_MIRROR_VNIC_ID UINT32_C(0x2) + uint32_t unused_0; + uint64_t em_filter_id; + /* This value is an opaque id into CFA data structures. */ + uint32_t new_dst_id; + /* + * If set, this value shall represent the new Logical VNIC ID of the + * destination VNIC for the RX path and network port id of the + * destination port for the TX path. + */ + uint32_t new_mirror_vnic_id; + /* New Logical VNIC ID of the VNIC where traffic is mirrored. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_cfa_em_flow_cfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_tunnel_dst_port_query */ +/* + * Description: This function is called by a driver to query tunnel type + * specific destination port configuration. + */ +/* Input (24 bytes) */ + +struct hwrm_tunnel_dst_port_query_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t tunnel_type; + /* Tunnel Type. */ + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_TUNNEL_DST_PORT_QUERY_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + uint8_t unused_0[7]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_tunnel_dst_port_query_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t tunnel_dst_port_id; + /* + * This field represents the identifier of L4 destination port used for + * the given tunnel type. This field is valid for specific tunnel types + * that use layer 4 (e.g. UDP) transports for tunneling. + */ + uint16_t tunnel_dst_port_val; /* big endian */ + /* + * This field represents the value of L4 destination port identified by + * tunnel_dst_port_id. This field is valid for specific tunnel types + * that use layer 4 (e.g. UDP) transports for tunneling. This field is + * in network byte order. A value of 0 means that the destination port + * is not configured. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_tunnel_dst_port_alloc */ +/* + * Description: This function is called by a driver to allocate l4 destination + * port for a specific tunnel type. The destination port value is provided in + * the input. If the HWRM supports only one global destination port for a tunnel + * type, then the HWRM shall keep track of its usage as described below. # The + * first caller that allocates a destination port shall always succeed and the + * HWRM shall save the destination port configuration for that tunnel type and + * increment the usage count to 1. # Subsequent callers allocating the same + * destination port for that tunnel type shall succeed and the HWRM shall + * increment the usage count for that port for each subsequent caller that + * succeeds. # Any subsequent caller trying to allocate a different destination + * port for that tunnel type shall fail until the usage count for the original + * destination port goes to zero. # A caller that frees a port will cause the + * usage count for that port to decrement. + */ +/* Input (24 bytes) */ + +struct hwrm_tunnel_dst_port_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t tunnel_type; + /* Tunnel Type. */ + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + uint8_t unused_0; + uint16_t tunnel_dst_port_val; /* big endian */ + /* + * This field represents the value of L4 destination port used for the + * given tunnel type. This field is valid for specific tunnel types that + * use layer 4 (e.g. UDP) transports for tunneling. This field is in + * network byte order. A value of 0 shall fail the command. + */ + uint32_t unused_1; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_tunnel_dst_port_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t tunnel_dst_port_id; + /* + * Identifier of a tunnel L4 destination port value. Only applies to + * tunnel types that has l4 destination port parameters. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_tunnel_dst_port_free */ +/* + * Description: This function is called by a driver to free l4 destination port + * for a specific tunnel type. + */ +/* Input (24 bytes) */ + +struct hwrm_tunnel_dst_port_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t tunnel_type; + /* Tunnel Type. */ + /* Virtual eXtensible Local Area Network (VXLAN) */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_VXLAN UINT32_C(0x1) + /* Generic Network Virtualization Encapsulation (Geneve) */ + #define HWRM_TUNNEL_DST_PORT_FREE_INPUT_TUNNEL_TYPE_GENEVE UINT32_C(0x5) + uint8_t unused_0; + uint16_t tunnel_dst_port_id; + /* + * Identifier of a tunnel L4 destination port value. Only applies to + * tunnel types that has l4 destination port parameters. + */ + uint32_t unused_1; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_tunnel_dst_port_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_stat_ctx_alloc */ +/* + * Description: This command allocates and does basic preparation for a stat + * context. + */ +/* Input (32 bytes) */ + +struct hwrm_stat_ctx_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t stats_dma_addr; + /* This is the address for statistic block. */ + uint32_t update_period_ms; + /* + * The statistic block update period in ms. e.g. 250ms, 500ms, 750ms, + * 1000ms. + */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_stat_ctx_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t stat_ctx_id; + /* This is the statistics context ID value. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_stat_ctx_free */ +/* Description: This command is used to free a stat context. */ +/* Input (24 bytes) */ + +struct hwrm_stat_ctx_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t stat_ctx_id; + /* ID of the statistics context that is being queried. */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_stat_ctx_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t stat_ctx_id; + /* This is the statistics context ID value. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_stat_ctx_query */ +/* Description: This command returns statistics of a context. */ +/* Input (24 bytes) */ + +struct hwrm_stat_ctx_query_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t stat_ctx_id; + /* ID of the statistics context that is being queried. */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (176 bytes) */ + +struct hwrm_stat_ctx_query_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t tx_ucast_pkts; + /* Number of transmitted unicast packets */ + uint64_t tx_mcast_pkts; + /* Number of transmitted multicast packets */ + uint64_t tx_bcast_pkts; + /* Number of transmitted broadcast packets */ + uint64_t tx_err_pkts; + /* Number of transmitted packets with error */ + uint64_t tx_drop_pkts; + /* Number of dropped packets on transmit path */ + uint64_t tx_ucast_bytes; + /* Number of transmitted bytes for unicast traffic */ + uint64_t tx_mcast_bytes; + /* Number of transmitted bytes for multicast traffic */ + uint64_t tx_bcast_bytes; + /* Number of transmitted bytes for broadcast traffic */ + uint64_t rx_ucast_pkts; + /* Number of received unicast packets */ + uint64_t rx_mcast_pkts; + /* Number of received multicast packets */ + uint64_t rx_bcast_pkts; + /* Number of received broadcast packets */ + uint64_t rx_err_pkts; + /* Number of received packets with error */ + uint64_t rx_drop_pkts; + /* Number of dropped packets on received path */ + uint64_t rx_ucast_bytes; + /* Number of received bytes for unicast traffic */ + uint64_t rx_mcast_bytes; + /* Number of received bytes for multicast traffic */ + uint64_t rx_bcast_bytes; + /* Number of received bytes for broadcast traffic */ + uint64_t rx_agg_pkts; + /* Number of aggregated unicast packets */ + uint64_t rx_agg_bytes; + /* Number of aggregated unicast bytes */ + uint64_t rx_agg_events; + /* Number of aggregation events */ + uint64_t rx_agg_aborts; + /* Number of aborted aggregations */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_stat_ctx_clr_stats */ +/* Description: This command clears statistics of a context. */ +/* Input (24 bytes) */ + +struct hwrm_stat_ctx_clr_stats_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t stat_ctx_id; + /* ID of the statistics context that is being queried. */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_stat_ctx_clr_stats_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_fw_reset */ +/* + * Description: This function is called by a driver to self reset the firmware + * running on the processor indicated by the embedded_proc_type. + */ +/* Input (24 bytes) */ + +struct hwrm_fw_reset_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t embedded_proc_type; + /* Type of embedded processor. */ + /* Boot Processor */ + #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_BOOT UINT32_C(0x0) + /* Management Processor */ + #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_MGMT UINT32_C(0x1) + /* Network control processor */ + #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_NETCTRL UINT32_C(0x2) + /* RoCE control processor */ + #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_ROCE UINT32_C(0x3) + /* Reserved */ + #define HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_RSVD UINT32_C(0x4) + uint8_t selfrst_status; + /* Type of self reset. */ + /* No Self Reset */ + #define HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTNONE UINT32_C(0x0) + /* Self Reset as soon as possible to do so safely */ + #define HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTASAP UINT32_C(0x1) + /* Self Reset on PCIe Reset */ + #define HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTPCIERST UINT32_C(0x2) + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_fw_reset_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t selfrst_status; + /* Type of self reset. */ + /* No Self Reset */ + #define HWRM_FW_RESET_OUTPUT_SELFRST_STATUS_SELFRSTNONE UINT32_C(0x0) + /* Self Reset as soon as possible to do so safely */ + #define HWRM_FW_RESET_OUTPUT_SELFRST_STATUS_SELFRSTASAP UINT32_C(0x1) + /* Self Reset on PCIe Reset */ + #define HWRM_FW_RESET_OUTPUT_SELFRST_STATUS_SELFRSTPCIERST UINT32_C(0x2) + uint8_t unused_0; + uint16_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_fw_qstatus */ +/* + * Description: This function is called by a driver to query the status of the + * firmware running on the processor indicated by the embedded_proc_type. + */ +/* Input (24 bytes) */ + +struct hwrm_fw_qstatus_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint8_t embedded_proc_type; + /* Type of embedded processor. */ + /* Boot Processor */ + #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_BOOT UINT32_C(0x0) + /* Management Processor */ + #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_MGMT UINT32_C(0x1) + /* Network control processor */ + #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_NETCTRL UINT32_C(0x2) + /* RoCE control processor */ + #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_ROCE UINT32_C(0x3) + /* Reserved */ + #define HWRM_FW_QSTATUS_INPUT_EMBEDDED_PROC_TYPE_RSVD UINT32_C(0x4) + uint8_t unused_0[7]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_fw_qstatus_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t selfrst_status; + /* Type of self reset. */ + /* No Self Reset */ + #define HWRM_FW_QSTATUS_OUTPUT_SELFRST_STATUS_SELFRSTNONE UINT32_C(0x0) + /* Self Reset as soon as possible to do so safely */ + #define HWRM_FW_QSTATUS_OUTPUT_SELFRST_STATUS_SELFRSTASAP UINT32_C(0x1) + /* Self Reset on PCIe Reset */ + #define HWRM_FW_QSTATUS_OUTPUT_SELFRST_STATUS_SELFRSTPCIERST UINT32_C(0x2) + uint8_t unused_0; + uint16_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_fw_set_time */ +/* + * Description: Inform the HWRM firmware of the current date/time. Ideally, the + * date/time will be current time in GMT/UTC and the zone value will be 0 + * (indicating UTC). If the time zone is not known, the zone value shall be + * 0xffff. Other values for zone are discouraged, but if specified, they + * indicate the number of minutes east of UTC, while zones west of UTC are + * represented with a 2's complement negative value (e.g. PST would be -480 + * while PDT would be -420). + */ +/* Input (32 bytes) */ + +struct hwrm_fw_set_time_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t year; + /* Current year */ + /* Date/time is not known */ + #define HWRM_FW_SET_TIME_INPUT_YEAR_UNKNOWN UINT32_C(0x0) + uint8_t month; + /* Current month of year (1-12) */ + uint8_t day; + /* Current day of month (1-31) */ + uint8_t hour; + /* Current hour (0-23) */ + uint8_t minute; + /* Current minute (0-59) */ + uint8_t second; + /* Current second (0-59) */ + uint8_t unused_0; + uint16_t millisecond; + /* Current millisecond (0-999) */ + uint16_t zone; + /* Minutes east of UTC, 0xffff if TZ is not known */ + /* Time zone is Coordinated Universal Time (UTC) */ + #define HWRM_FW_SET_TIME_INPUT_ZONE_UTC UINT32_C(0x0) + /* Time zone is not known */ + #define HWRM_FW_SET_TIME_INPUT_ZONE_UNKNOWN UINT32_C(0xffff) + uint32_t unused_1; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_fw_set_time_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_fw_get_time */ +/* Description: Query the HWRM firmware's notion of the current date/time. */ +/* Input (16 bytes) */ + +struct hwrm_fw_get_time_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_fw_get_time_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t year; + /* Current year */ + /* Date/time is not known */ + #define HWRM_FW_GET_TIME_OUTPUT_YEAR_UNKNOWN UINT32_C(0x0) + uint8_t month; + /* Current month of year (1-12) */ + uint8_t day; + /* Current day of month (1-31) */ + uint8_t hour; + /* Current hour (0-23) */ + uint8_t minute; + /* Current minute (0-59) */ + uint8_t second; + /* Current second (0-59) */ + uint8_t unused_0; + uint16_t millisecond; + /* Current millisecond (0-999) */ + uint16_t zone; + /* Minutes east of UTC, 0xffff if TZ is not known */ + /* Time zone is Coordinated Universal Time (UTC) */ + #define HWRM_FW_GET_TIME_OUTPUT_ZONE_UTC UINT32_C(0x0) + /* Time zone is not known */ + #define HWRM_FW_GET_TIME_OUTPUT_ZONE_UNKNOWN UINT32_C(0xffff) + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_exec_fwd_resp */ +/* + * Description: This command is used to send an encapsulated request to the + * HWRM. This command instructs the HWRM to execute the request and forward the + * response of the encapsulated request to the location specified in the + * original request that is encapsulated. The target id of this command shall be + * set to 0xFFFF (HWRM). The response location in this command shall be used to + * acknowledge the receipt of the encapsulated request and forwarding of the + * response. + */ +/* Input (128 bytes) */ + +struct hwrm_exec_fwd_resp_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t encap_request[26]; + /* + * This is an encapsulated request. This request should be executed by + * the HWRM and the response should be provided in the response buffer + * inside the encapsulated request. + */ + uint16_t encap_resp_target_id; + /* + * This value indicates the target id of the response to the + * encapsulated request. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - + * 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_exec_fwd_resp_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_reject_fwd_resp */ +/* + * Description: This command is used to send an encapsulated request to the + * HWRM. This command instructs the HWRM to reject the request and forward the + * error response of the encapsulated request to the location specified in the + * original request that is encapsulated. The target id of this command shall be + * set to 0xFFFF (HWRM). The response location in this command shall be used to + * acknowledge the receipt of the encapsulated request and forwarding of the + * response. + */ +/* Input (128 bytes) */ + +struct hwrm_reject_fwd_resp_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t encap_request[26]; + /* + * This is an encapsulated request. This request should be rejected by + * the HWRM and the error response should be provided in the response + * buffer inside the encapsulated request. + */ + uint16_t encap_resp_target_id; + /* + * This value indicates the target id of the response to the + * encapsulated request. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - + * 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_reject_fwd_resp_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_fwd_resp */ +/* + * Description: This command is used to send an encapsulated response to the + * HWRM. The HWRM shall forward this response based on the target id. The + * response address provided in this command shall be used to acknowledge the + * receipt of the encapsulated response. The encapsulated response address + * provided in this command shall be used to provide the encapsulated response. + */ +/* Input (40 bytes) */ + +struct hwrm_fwd_resp_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t encap_resp_target_id; + /* + * This value indicates the target id of the encapsulated response. 0x0 + * - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE - Reserved for + * internal processors 0xFFFF - HWRM + */ + uint16_t encap_resp_cmpl_ring; + /* + * This value indicates the completion ring the encapsulated response + * will be optionally completed on. If the value is -1, then no CR + * completion shall be generated for the encapsulated response. Any + * other value must be a valid CR ring_id value. If a valid + * encap_resp_cmpl_ring is provided, then a CR completion shall be + * generated for the encapsulated response. + */ + uint16_t encap_resp_len; + /* This field indicates the length of encapsulated response. */ + uint8_t unused_0; + uint8_t unused_1; + uint64_t encap_resp_addr; + /* + * This is the host address where the encapsulated response will be + * written. This area must be 16B aligned and must be cleared to zero + * before the original request is made. + */ + uint32_t encap_resp[24]; + /* This is an encapsulated response. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_fwd_resp_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_fwd_async_event_cmpl */ +/* + * Description: This command is used to send an encapsulated asynchronous event + * completion to the HWRM. The HWRM shall forward this asynchronous event + * completion to target(s) specified in the command. The HWRM shall complete + * this command only after forwarding asynchronous event completion to specified + * targets. + */ +/* Input (32 bytes) */ + +struct hwrm_fwd_async_event_cmpl_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t encap_async_event_target_id; + /* + * This value indicates the target id of the encapsulated asynchronous + * event. 0x0 - 0xFFF8 - Used for function ids 0xFFF8 - 0xFFFE - + * Reserved for internal processors 0xFFFF - Broadcast to all children + * VFs (only applicable when a PF is the requester) + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2[3]; + uint8_t unused_3; + uint32_t encap_async_event_cmpl[4]; + /* This is an encapsulated asynchronous event completion. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_fwd_async_event_cmpl_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_temp_monitor_query */ +/* + * Description: A temperature monitor is used to query the device temperature. + */ +/* Input (16 bytes) */ + +struct hwrm_temp_monitor_query_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_temp_monitor_query_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t temp; + /* The HWRM shall provide the current temperature of device in Celsius. */ + uint8_t unused_0; + uint16_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_wol_filter_alloc */ +/* + * Description: A Wake-On-LAN (WoL) filter is a filter resource that is used to + * identify a WoL packet. # Among all function drivers, the HWRM shall only + * allow PF drivers to allocate WoL filters. # The HWRM shall not allow VF + * drivers to allocate any WoL filters. # When partitioning is enabled and WoL + * is supported, the HWRM shall support at least one WoL filter per partition. # + * The HWRM shall retain a WoL filter setting until the filter is freed. # If + * the HWRM client is a function driver, then the HWRM shall not allow the HWRM + * client to set up WoL filters on the port that the function is not associated + * with. # If the HWRM client is one of the trusted embedded services (e.g. + * management service), the the HWRM shall allow the HWRM client to set up WoL + * filters on any port of the device. + */ +/* Input (64 bytes) */ + +struct hwrm_wol_filter_alloc_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + uint32_t enables; + /* This bit must be '1' for the mac_address field to be configured. */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS UINT32_C(0x1) + /* This bit must be '1' for the pattern_offset field to be configured. */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_OFFSET UINT32_C(0x2) + /* This bit must be '1' for the pattern_buf_size field to be configured. */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_BUF_SIZE UINT32_C(0x4) + /* This bit must be '1' for the pattern_buf_addr field to be configured. */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_BUF_ADDR UINT32_C(0x8) + /* + * This bit must be '1' for the pattern_mask_addr field to be + * configured. + */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_MASK_ADDR UINT32_C(0x10) + /* + * This bit must be '1' for the pattern_mask_size field to be + * configured. + */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_PATTERN_MASK_SIZE UINT32_C(0x20) + uint16_t port_id; + /* Port ID of port on which WoL filter is configured. */ + uint8_t wol_type; + /* This value represents a Wake-on-LAN type. */ + /* Magic Paket */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT UINT32_C(0x0) + /* Bitmap */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_BMP UINT32_C(0x1) + /* Invalid */ + #define HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_INVALID UINT32_C(0xff) + uint8_t unused_0; + uint32_t unused_1; + uint8_t mac_address[6]; + /* + * # If this field is enabled and magic packet WoL filter type is + * specified in this command, the value set in this field shall be used + * in setting the magic packet based WoL filter. # If this field is not + * enabled and magic packet WoL filter type is specified and port id is + * specified to 0xFF in this command, then the HWRM shall use default + * MAC address configured on the function associated with the HWRM + * client. # If this field is not enabled and magic packet WoL filter + * type is specified and port id is not specified to 0xFF in this + * command, then the HWRM shall use default MAC address configured on + * the port. + */ + uint16_t pattern_offset; + /* + * The offset from the beginning of MAC header where pattern should be + * matched. Applies to bitmap WoL. + */ + uint16_t pattern_buf_size; + /* The size of the pattern that is being matched. Applies to bitmap WoL. */ + uint16_t pattern_mask_size; + /* The size of the pattern mask. Applies to bitmap WoL. */ + uint32_t unused_2; + uint64_t pattern_buf_addr; + /* Physical address of the pattern buffer. Applies to bitmap WoL. */ + uint64_t pattern_mask_addr; + /* Physical address of the pattern mask. Applies to bitmap WoL. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_wol_filter_alloc_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t wol_filter_id; + /* This value identifies a Wake-on-LAN (WoL) filter. */ + uint8_t unused_0; + uint16_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_wol_filter_free */ +/* + * Description: Free a WoL filter. # Among all function drivers, the HWRM shall + * only allow PF drivers to free WoL filters. # The HWRM shall not allow VF + * drivers to free any WoL filters. # The HWRM shall not allow a function driver + * to free an Out-Of-Box WoL filter. # The HWRM shall not allow a function + * driver to free a WoL filter on a port that the corresponding function is not + * associated with. # The HWRM shall not allow a function driver to free a WoL + * filter on a function that the function driver is not associated with. + */ +/* Input (32 bytes) */ + +struct hwrm_wol_filter_free_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t flags; + /* + * # When this bit is set to '1', then all active WoL filters on the + * port are requested to be freed. # If the a function driver sets this + * flag to '1', then the HWRM shall free all active WoL filters that are + * not set by other function drivers on that port. + */ + #define HWRM_WOL_FILTER_FREE_INPUT_FLAGS_FREE_ALL_WOL_FILTERS UINT32_C(0x1) + uint32_t enables; + /* This bit must be '1' for the wol_filter_id field to be configured. */ + #define HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID UINT32_C(0x1) + uint16_t port_id; + /* Port ID of the port on which WoL filter(s) is (are) being freed. */ + uint8_t wol_filter_id; + /* The HWRM shall ignore this field if free_all_wol_filters flag is set. */ + uint8_t unused_0[5]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_wol_filter_free_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_wol_filter_qcfg */ +/* + * Description: Query WoL filter configuration. # Among all function drivers, + * the HWRM shall only allow PF drivers to query WoL filters. # The HWRM shall + * not allow VF drivers to query any WoL filters. # The HWRM shall return WoL + * filters that are active on the associated port for which this query is being + * performed. # If the HWRM client is a function driver, then the HWRM shall not + * allow the HWRM client to query WoL filters that are set up by other function + * drivers. # If the HWRM client is a function driver, then the HWRM shall not + * allow the HWRM client to query WoL filters on the port that the function is + * not associated with. # If the HWRM client is one of the trusted embedded + * service (e.g. management service), the the HWRM shall allow the HWRM client + * to query WoL filters on any port of the device. + */ +/* Input (56 bytes) */ + +struct hwrm_wol_filter_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* Port ID of port on which WoL filter that is being queried. */ + uint16_t handle; + /* + * This is an opaque handle used to access filters. # The HWRM client + * shall set this field to 0x0000 to begin the query. # After the first + * query, the HWRM client shall retrieve next filters (if they exist) + * using the HWRM provided handle in the response. + */ + uint32_t unused_0; + uint64_t pattern_buf_addr; + /* + * Physical address of the pattern buffer. Applies to bitmap WoL filter + * only. # Value of 0 indicates an invalid buffer address. If this field + * is set to 0, then HWRM shall ignore pattern_buf_size. # If the HWRM + * client provides an invalid buffer address for the pattern, then the + * HWRM is not required to provide pattern when the response contains a + * bitmap WoL filter. + */ + uint64_t pattern_buf_size; + /* The sixe of the pattern buffer. Applies to bitmap WoL filter only. */ + uint64_t pattern_mask_addr; + /* + * Physical address of the pattern mask. Applies to bitmap WoL filter + * only. # Value of 0 indicates an invalid pattern mask address. If this + * field is set to 0, then HWRM shall ignore pattern_mask_size. # If the + * HWRM client provides an invalid mask address for the pattern, then + * the HWRM is not required to provide mask when the response contains a + * bitmap WoL filter. + */ + uint64_t pattern_mask_size; + /* + * The size of the buffer for pattern mask. Applies to bitmap WoL filter + * only. + */ +} __attribute__((packed)); + +/* Output (32 bytes) */ + +struct hwrm_wol_filter_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t next_handle; + /* + * This is the next handle that is used to access filters. # If this + * field is set to 0x0000, then no WoL filters are currently configured + * on this port and all other fields in the output shall be ignored by + * the HWRM client. # If this field is set to neither 0x0000 nor 0xFFFF, + * then the wol_filter_id is valid and the parameters provided in the + * response are based on the wol_type. # If this field is set to 0xFFFF, + * then there are no remaining configured WoL filters to be queried for + * the queried function after this response, wol_filter_id is valid and + * the parameters provided in the response are based on the wol_type. + */ + uint8_t wol_filter_id; + /* This value identifies the filter returned in this response. */ + uint8_t wol_type; + /* + * This value identifies the type of WoL filter returned in this + * response. + */ + /* Magic Paket */ + #define HWRM_WOL_FILTER_QCFG_OUTPUT_WOL_TYPE_MAGICPKT UINT32_C(0x0) + /* Bitmap */ + #define HWRM_WOL_FILTER_QCFG_OUTPUT_WOL_TYPE_BMP UINT32_C(0x1) + /* Invalid */ + #define HWRM_WOL_FILTER_QCFG_OUTPUT_WOL_TYPE_INVALID UINT32_C(0xff) + uint32_t unused_0; + uint8_t mac_address[6]; + /* + * The MAC address value used by the WoL filter. Applies to magic packet + * based WoL. + */ + uint16_t pattern_offset; + /* + * The offset from the beginning of MAC header where pattern should be + * matched. Applies to bitmap WoL. + */ + uint16_t pattern_size; + /* + * The actual size of the pattern that is being returned. Applies to + * bitmap WoL. + */ + uint16_t pattern_mask_size; + /* + * The actual size of the pattern mask that is being returned. Applies + * to bitmap WoL. + */ + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_wol_reason_qcfg */ +/* Description: Query WoL reason for the last system wake up. */ +/* Input (40 bytes) */ + +struct hwrm_wol_reason_qcfg_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t port_id; + /* Port ID of port for which this query is for. */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2[3]; + uint8_t unused_3; + uint64_t wol_pkt_buf_addr; + /* Physical address of the packet buffer for querying WoL packet. */ + uint64_t wol_pkt_buf_size; + /* The size of the buffer for the WoL packet. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_wol_reason_qcfg_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint8_t wol_filter_id; + /* + * This value identifies the filter that matched the last WoL packet. + * This id is only valid with valid WoL reason. + */ + uint8_t wol_reason; + /* + * This value identifies the type of WoL reason returned in this + * response. When the wol_type is set to invalid, then there is no WoL + * event that happened during last system wake-up. + */ + /* Magic Paket */ + #define HWRM_WOL_REASON_QCFG_OUTPUT_WOL_REASON_MAGICPKT UINT32_C(0x0) + /* Bitmap */ + #define HWRM_WOL_REASON_QCFG_OUTPUT_WOL_REASON_BMP UINT32_C(0x1) + /* Invalid */ + #define HWRM_WOL_REASON_QCFG_OUTPUT_WOL_REASON_INVALID UINT32_C(0xff) + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t unused_4; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_dbg_dump */ +/* + * Description: This command is used by to initiate the dump of debug + * information to a driver specified address. + */ +/* Input (40 bytes) */ + +struct hwrm_dbg_dump_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t handle; + /* + * Handle used to dump debug data. handle = 0 indicates the beginning of + * the dump. handle != 0 indicates the request to dump the next part. + */ + uint32_t unused_0; + uint64_t host_dbg_dump_addr; + /* + * Address of the host buffer where the debug data is requested to be + * dumped. + */ + uint64_t host_dbg_dump_addr_len; + /* Length of host buffer used for transferring debug data. */ +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_dbg_dump_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t nexthandle; + /* + * Handle used to indicate availability of additional debug data. + * nexthandle = 0 indicates that there is no more debug data available. + * nexthandle != 0 indicates the handle value that should be used to + * request the next part of debug data. + */ + uint32_t dbg_data_len; + /* The number of bytes of debug data written to debug dump buffer. */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_raw_write_blk */ +/* + * Note: Write an unmanaged block of data at any physical offset within the + * NVRAM. Used for initial provisioning/manufacturing purposes only. Implemented + * in the ChiMP boot-strap firmware (fwutil.bin) only. + */ +/* Input (32 bytes) */ + +struct hwrm_nvm_raw_write_blk_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t host_src_addr; + /* + * 64-bit Host Source Address. This is the loation of the source data to + * be written. + */ + uint32_t dest_addr; + /* + * 32-bit Destination Address. This is the NVRAM byte-offset where the + * source data will be written to. + */ + uint32_t len; + /* Length of data to be written, in bytes. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_raw_write_blk_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_read */ +/* + * Note: Read the contents of an NVRAM item as referenced (indexed) by an + * existing directory entry. + */ +/* Input (40 bytes) */ + +struct hwrm_nvm_read_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t host_dest_addr; + /* + * 64-bit Host Destination Address. This is the host address where the + * data will be written to. + */ + uint16_t dir_idx; + /* The 0-based index of the directory entry. */ + uint8_t unused_0; + uint8_t unused_1; + uint32_t offset; + /* The NVRAM byte-offset to read from. */ + uint32_t len; + /* The length of the data to be read, in bytes. */ + uint32_t unused_2; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_read_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_raw_dump */ +/* Note: Dump a raw block of data from NVRAM. */ +/* Input (32 bytes) */ + +struct hwrm_nvm_raw_dump_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t host_dest_addr; + /* + * 64-bit Host Destination Address. This is the host address where the + * data will be written to. + */ + uint32_t offset; + /* 32-bit NVRAM byte-offset to read from. */ + uint32_t len; + /* Total length of NVRAM contents to be read, in bytes. */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_raw_dump_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_get_dir_entries */ +/* + * Description: Read the NVRAM directory. Each directory entry is at least 24 + * bytes in length and contains the: - 16-bit directory entry type + * (BNX_DIR_TYPE_* value) - 16-bit ordinal (instance of this directory entry + * type) - 16-bit extension flags (identifies inactive entries and entries for + * firmware update) - 16-bit attribute flags (identifies entries with a + * purposely invalid chksum value) - 32-bit byte-offset into NVRAM where this + * item data is located - 32-bit length of allocated NVRAM for item, in bytes + * (multiple of block size) - 32-bit length of data (excluding padding), in + * bytes (may be 0) - 32-bit data checksum (CRC-32) See the + * bnxnvm_directory_entry_t definition in the file bnxnvm_defs.h. + */ +/* Input (24 bytes) */ + +struct hwrm_nvm_get_dir_entries_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t host_dest_addr; + /* + * 64-bit Host Destination Address. This is the host address where the + * directory will be written. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_get_dir_entries_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_get_dir_info */ +/* Note: Get Directory Header info. */ +/* Input (16 bytes) */ + +struct hwrm_nvm_get_dir_info_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_nvm_get_dir_info_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t entries; + /* Number of directory entries in the directory. */ + uint32_t entry_length; + /* Size of each directory entry, in bytes. */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_write */ +/* + * Note: Write to the allocated NVRAM of an item referenced by an existing + * directory entry. + */ +/* Input (48 bytes) */ + +struct hwrm_nvm_write_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t host_src_addr; + /* 64-bit Host Source Address. This is where the source data is. */ + uint16_t dir_type; + /* + * The Directory Entry Type (valid values are defined in the + * bnxnvm_directory_type enum defined in the file bnxnvm_defs.h). + */ + uint16_t dir_ordinal; + /* + * Directory ordinal. The 0-based instance of the combined Directory + * Entry Type and Extension. + */ + uint16_t dir_ext; + /* + * The Directory Entry Extension flags (see BNX_DIR_EXT_* in the file + * bnxnvm_defs.h). + */ + uint16_t dir_attr; + /* + * Directory Entry Attribute flags (see BNX_DIR_ATTR_* in the file + * bnxnvm_defs.h). + */ + uint32_t dir_data_length; + /* + * Length of data to write, in bytes. May be less than or equal to the + * allocated size for the directory entry. The data length stored in the + * directory entry will be updated to reflect this value once the write + * is complete. + */ + uint16_t option; + /* Option. */ + uint16_t flags; + /* + * When this bit is '1', the original active image will not be removed. + * TBD: what purpose is this? + */ + #define HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG UINT32_C(0x1) + uint32_t dir_item_length; + /* + * The requested length of the allocated NVM for the item, in bytes. + * This value may be greater than or equal to the specified data length + * (dir_data_length). If this value is less than the specified data + * length, it will be ignored. The response will contain the actual + * allocated item length, which may be greater than the requested item + * length. The purpose for allocating more than the required number of + * bytes for an item's data is to pre-allocate extra storage (padding) + * to accommodate the potential future growth of an item (e.g. upgraded + * firmware with a size increase, log growth, expanded configuration + * data). + */ + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_write_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t dir_item_length; + /* + * Length of the allocated NVM for the item, in bytes. The value may be + * greater than or equal to the specified data length or the requested + * item length. The actual item length used when creating a new + * directory entry will be a multiple of an NVM block size. + */ + uint16_t dir_idx; + /* The directory index of the created or modified item. */ + uint8_t unused_0; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_modify */ +/* + * Note: Modify the contents of an NVRAM item as referenced (indexed) by an + * existing directory entry. + */ +/* Input (40 bytes) */ + +struct hwrm_nvm_modify_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint64_t host_src_addr; + /* 64-bit Host Source Address. This is where the modified data is. */ + uint16_t dir_idx; + /* 16-bit directory entry index. */ + uint8_t unused_0; + uint8_t unused_1; + uint32_t offset; + /* 32-bit NVRAM byte-offset to modify content from. */ + uint32_t len; + /* + * Length of data to be modified, in bytes. The length shall be non- + * zero. + */ + uint32_t unused_2; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_modify_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_find_dir_entry */ +/* + * Note: Search a directory entry in the directory by either directory entry + * index or directory entry parameters. + */ +/* Input (32 bytes) */ + +struct hwrm_nvm_find_dir_entry_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the dir_idx_valid field to be configured. */ + #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID UINT32_C(0x1) + uint16_t dir_idx; + /* Directory Entry Index */ + uint16_t dir_type; + /* Directory Entry (Image) Type */ + uint16_t dir_ordinal; + /* Directory ordinal. The instance of this Directory Type */ + uint16_t dir_ext; + /* The Directory Entry Extension flags. */ + uint8_t opt_ordinal; + /* This value indicates the search option using dir_ordinal. */ + #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_MASK UINT32_C(0x3) + #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_SFT 0 + /* Equal to specified ordinal value. */ + #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_EQ UINT32_C(0x0) + /* Greater than or equal to specified ordinal value */ + #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_GE UINT32_C(0x1) + /* Greater than specified ordinal value */ + #define HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_GT UINT32_C(0x2) + uint8_t unused_1[3]; +} __attribute__((packed)); + +/* Output (32 bytes) */ + +struct hwrm_nvm_find_dir_entry_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t dir_item_length; + /* Allocated NVRAM for this directory entry, in bytes. */ + uint32_t dir_data_length; + /* Size of the stored data for this directory entry, in bytes. */ + uint32_t fw_ver; + /* + * Firmware version. Only valid if the directory entry is for embedded + * firmware stored in APE_BIN Format. + */ + uint16_t dir_ordinal; + /* Directory ordinal. */ + uint16_t dir_idx; + /* Directory Entry Index */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_erase_dir_entry */ +/* + * Note: Remove a directory entry specified by the directory entry index from + * the directory. + */ +/* Input (24 bytes) */ + +struct hwrm_nvm_erase_dir_entry_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t dir_idx; + /* Directory Entry Index */ + uint16_t unused_0[3]; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_erase_dir_entry_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_get_dev_info */ +/* + * Note: Get device info. Return Manufacturer_ID, Device_ID, block_size, + * nvram_size, reserved_size and available_size. + */ +/* Input (16 bytes) */ + +struct hwrm_nvm_get_dev_info_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ +} __attribute__((packed)); + +/* Output (32 bytes) */ + +struct hwrm_nvm_get_dev_info_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint16_t manufacturer_id; + /* Manufacturer ID. */ + uint16_t device_id; + /* Device ID. */ + uint32_t sector_size; + /* Sector size of the NVRAM device. */ + uint32_t nvram_size; + /* Total size, in bytes of the NVRAM device. */ + uint32_t reserved_size; + uint32_t available_size; + /* + * Available size that can be used, in bytes. Available size is the + * NVRAM size take away the used size and reserved size. + */ + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_mod_dir_entry */ +/* Note: Modify a directory entry parameters in the directory. */ +/* Input (32 bytes) */ + +struct hwrm_nvm_mod_dir_entry_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t enables; + /* This bit must be '1' for the checksum field to be configured. */ + #define HWRM_NVM_MOD_DIR_ENTRY_INPUT_ENABLES_CHECKSUM UINT32_C(0x1) + uint16_t dir_idx; + /* Directory Entry Index */ + uint16_t dir_ordinal; + /* Directory ordinal. The (0-based) instance of this Directory Type. */ + uint16_t dir_ext; + /* + * The Directory Entry Extension flags (see BNX_DIR_EXT_* for extension + * flag definitions). + */ + uint16_t dir_attr; + /* + * Directory Entry Attribute flags (see BNX_DIR_ATTR_* for attribute + * flag definitions). + */ + uint32_t checksum; + /* + * If valid, then this field updates the checksum value of the content + * in the directory entry. + */ +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_mod_dir_entry_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_verify_update */ +/* + * Description: Verify updated content of a directory entry. Before this + * verification, there should be two valid directory entries of the given + * directory type (one with "UPDATE" directory extension flag and the current + * one "ACTIVE"). Below are steps the HWRM performs for executing this command: + * # The HWRM finds the directory entry with "UDPATE" extension flag based on + * input parameters. The new directory entry should already have updated + * contents. # The HWRM performs signature verification of the updated content. + * # If the signature verification is successful, the two directory entries are + * switched (the verified updated entry is made active and the current "ACTIVE" + * entry is marked with "UPDATE" extension flag). Implementation notes: # The + * HWRM shall allow this command to be requested against any dir_type value (and + * not limit it to a subset). # In the case of an updated HWRM firmware, the new + * firmware version shall not automatically take effect (i.e. be executed). + */ +/* Input (24 bytes) */ + +struct hwrm_nvm_verify_update_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint16_t dir_type; + /* Directory Entry Type, to be verified. */ + uint16_t dir_ordinal; + /* Directory ordinal. The instance of the Directory Type to be verified. */ + uint16_t dir_ext; + /* + * The Directory Entry Extension flags. The "UPDATE" extension flag must + * be set in this value. A corresponding directory entry with the same + * type and ordinal values but *without* the "UPDATE" extension flag + * must also exist. The other flags of the extension must be identical + * between the active and update entries. + */ + uint16_t unused_0; +} __attribute__((packed)); + +/* Output (16 bytes) */ + +struct hwrm_nvm_verify_update_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint32_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +/* hwrm_nvm_install_update */ +/* + * Description: Install a staged NVM package. A package file must first be + * staged into the "UPDATE" NVM item. This staging is accomplished using the + * nvm_write and/or nvm_modify HWRM commands. + */ +/* Input (24 bytes) */ + +struct hwrm_nvm_install_update_input { + uint16_t req_type; + /* + * This value indicates what type of request this is. The format for the + * rest of the command is determined by this field. + */ + uint16_t cmpl_ring; + /* + * This value indicates the what completion ring the request will be + * optionally completed on. If the value is -1, then no CR completion + * will be generated. Any other value must be a valid CR ring_id value + * for this function. + */ + uint16_t seq_id; + /* This value indicates the command sequence number. */ + uint16_t target_id; + /* + * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids + * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM + */ + uint64_t resp_addr; + /* + * This is the host address where the response will be written when the + * request is complete. This area must be 16B aligned and must be + * cleared to zero before the request is made. + */ + uint32_t install_type; + /* + * Installation type. If the value 3 through 0xffff is used, only + * packaged items with that type value will be installed and conditional + * installation directives for those packaged items will be over-ridden + * (i.e. 'create' or 'replace' will be treated as 'install'). + */ + /* + * Perform a normal package installation. Conditional + * installation directives (e.g. 'create' and 'replace') of + * packaged items will be followed. + */ + #define HWRM_NVM_INSTALL_UPDATE_INPUT_INSTALL_TYPE_NORMAL UINT32_C(0x0) + /* + * Install all packaged items regardless of installation + * directive (i.e. treat all packaged items as though they have + * an installation directive of 'install'). + */ + #define HWRM_NVM_INSTALL_UPDATE_INPUT_INSTALL_TYPE_ALL UINT32_C(0xffffffff) + uint32_t unused_0; +} __attribute__((packed)); + +/* Output (24 bytes) */ + +struct hwrm_nvm_install_update_output { + uint16_t error_code; + /* + * Pass/Fail or error type Note: receiver to verify the in parameters, + * and fail the call with an error when appropriate + */ + uint16_t req_type; + /* This field returns the type of original request. */ + uint16_t seq_id; + /* This field provides original sequence number of the command. */ + uint16_t resp_len; + /* + * This field is the length of the response in bytes. The last byte of + * the response is a valid flag that will read as '1' when the command + * has been completely written to memory. + */ + uint64_t installed_items; + /* + * Bit-mask of successfully installed items. Bit-0 corresponding to the + * first packaged item, Bit-1 for the second item, etc. A value of 0 + * indicates that no items were successfully installed. + */ + uint8_t result; + /* result is 8 b */ + /* There was no problem with the package installation. */ + #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESULT_SUCCESS UINT32_C(0x0) + uint8_t problem_item; + /* problem_item is 8 b */ + /* There was no problem with any packaged items. */ + #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_PROBLEM_ITEM_NONE UINT32_C(0x0) + /* There was a problem with the NVM package itself. */ + #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_PROBLEM_ITEM_PACKAGE UINT32_C(0xff) + uint8_t reset_required; + /* reset_required is 8 b */ + /* + * No reset is required for installed/updated firmware or + * microcode to take effect. + */ + #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESET_REQUIRED_NONE UINT32_C(0x0) + /* + * A PCIe reset (e.g. system reboot) is required for newly + * installed/updated firmware or microcode to take effect. + */ + #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESET_REQUIRED_PCI UINT32_C(0x1) + /* + * A controller power reset (e.g. system power-cycle) is + * required for newly installed/updated firmware or microcode to + * take effect. Some newly installed/updated firmware or + * microcode may still take effect upon the next PCIe reset. + */ + #define HWRM_NVM_INSTALL_UPDATE_OUTPUT_RESET_REQUIRED_POWER UINT32_C(0x2) + uint8_t unused_0; + uint8_t unused_1; + uint8_t unused_2; + uint8_t unused_3; + uint8_t valid; + /* + * This field is used in Output records to indicate that the output is + * completely written to RAM. This field should be read as '1' to + * indicate that the output has been completely written. When writing a + * command completion or response to an internal processor, the order of + * writes has to be such that this field is written last. + */ +} __attribute__((packed)); + +#endif /* _HSI_STRUCT_DEF_EXTERNAL_H_ */ diff --git a/sys/dev/bnxt/if_bnxt.c b/sys/dev/bnxt/if_bnxt.c new file mode 100644 index 00000000000..2cca3ec6e92 --- /dev/null +++ b/sys/dev/bnxt/if_bnxt.c @@ -0,0 +1,2360 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2016 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "opt_inet.h" +#include "opt_inet6.h" +#include "opt_rss.h" + +#include "ifdi_if.h" + +#include "bnxt.h" +#include "bnxt_hwrm.h" +#include "bnxt_ioctl.h" +#include "bnxt_sysctl.h" +#include "hsi_struct_def.h" + +/* + * PCI Device ID Table + */ + +static pci_vendor_info_t bnxt_vendor_info_array[] = +{ + PVID(BROADCOM_VENDOR_ID, BCM57301, + "Broadcom BCM57301 NetXtreme-C 10Gb Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57302, + "Broadcom BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57304, + "Broadcom BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57402, + "Broadcom BCM57402 NetXtreme-E 10Gb Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57404, + "Broadcom BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57406, + "Broadcom BCM57406 NetXtreme-E 10GBase-T Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57402_NPAR, + "Broadcom BCM57402 NetXtreme-E Partition"), + PVID(BROADCOM_VENDOR_ID, BCM57407, + "Broadcom BCM57407 NetXtreme-E 10GBase-T Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57404_NPAR, + "Broadcom BCM57404 NetXtreme-E Partition"), + PVID(BROADCOM_VENDOR_ID, BCM57406_NPAR, + "Broadcom BCM57406 NetXtreme-E Partition"), + PVID(BROADCOM_VENDOR_ID, BCM57407_SFP, + "Broadcom BCM57407 NetXtreme-E 25Gb Ethernet Controller"), + PVID(BROADCOM_VENDOR_ID, BCM57304_VF, + "Broadcom BCM57304 NetXtreme-C Virtual Function"), + PVID(BROADCOM_VENDOR_ID, BCM57404_VF, + "Broadcom BCM57404 NetXtreme-E Virtual Function"), + /* required last entry */ + + PVID_END +}; + +/* + * Function prototypes + */ + +static void *bnxt_register(device_t dev); + +/* Soft queue setup and teardown */ +static int bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, + uint64_t *paddrs, int ntxqs, int ntxqsets); +static int bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, + uint64_t *paddrs, int nrxqs, int nrxqsets); +static void bnxt_queues_free(if_ctx_t ctx); + +/* Device setup and teardown */ +static int bnxt_attach_pre(if_ctx_t ctx); +static int bnxt_attach_post(if_ctx_t ctx); +static int bnxt_detach(if_ctx_t ctx); + +/* Device configuration */ +static void bnxt_init(if_ctx_t ctx); +static void bnxt_stop(if_ctx_t ctx); +static void bnxt_multi_set(if_ctx_t ctx); +static int bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu); +static void bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr); +static int bnxt_media_change(if_ctx_t ctx); +static int bnxt_promisc_set(if_ctx_t ctx, int flags); +static uint64_t bnxt_get_counter(if_ctx_t, ift_counter); +static void bnxt_update_admin_status(if_ctx_t ctx); + +/* Interrupt enable / disable */ +static void bnxt_intr_enable(if_ctx_t ctx); +static int bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid); +static void bnxt_disable_intr(if_ctx_t ctx); +static int bnxt_msix_intr_assign(if_ctx_t ctx, int msix); + +/* vlan support */ +static void bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag); +static void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag); + +/* ioctl */ +static int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); + +/* Internal support functions */ +static int bnxt_probe_phy(struct bnxt_softc *softc); +static void bnxt_add_media_types(struct bnxt_softc *softc); +static int bnxt_pci_mapping(struct bnxt_softc *softc); +static void bnxt_pci_mapping_free(struct bnxt_softc *softc); +static int bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state); +static int bnxt_handle_def_cp(void *arg); +static int bnxt_handle_rx_cp(void *arg); +static void bnxt_clear_ids(struct bnxt_softc *softc); +static void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr); +static void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr); +static void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr); +static void bnxt_def_cp_task(void *context); +static void bnxt_handle_async_event(struct bnxt_softc *softc, + struct cmpl_base *cmpl); +static uint8_t get_phy_type(struct bnxt_softc *softc); +static uint64_t bnxt_get_baudrate(struct bnxt_link_info *link); + +/* + * Device Interface Declaration + */ + +static device_method_t bnxt_methods[] = { + /* Device interface */ + DEVMETHOD(device_register, bnxt_register), + DEVMETHOD(device_probe, iflib_device_probe), + DEVMETHOD(device_attach, iflib_device_attach), + DEVMETHOD(device_detach, iflib_device_detach), + DEVMETHOD(device_shutdown, iflib_device_shutdown), + DEVMETHOD(device_suspend, iflib_device_suspend), + DEVMETHOD(device_resume, iflib_device_resume), + DEVMETHOD_END +}; + +static driver_t bnxt_driver = { + "bnxt", bnxt_methods, sizeof(struct bnxt_softc), +}; + +devclass_t bnxt_devclass; +DRIVER_MODULE(bnxt, pci, bnxt_driver, bnxt_devclass, 0, 0); + +MODULE_DEPEND(bnxt, pci, 1, 1, 1); +MODULE_DEPEND(bnxt, ether, 1, 1, 1); +MODULE_DEPEND(bnxt, iflib, 1, 1, 1); + +static device_method_t bnxt_iflib_methods[] = { + DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc), + DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc), + DEVMETHOD(ifdi_queues_free, bnxt_queues_free), + + DEVMETHOD(ifdi_attach_pre, bnxt_attach_pre), + DEVMETHOD(ifdi_attach_post, bnxt_attach_post), + DEVMETHOD(ifdi_detach, bnxt_detach), + + DEVMETHOD(ifdi_init, bnxt_init), + DEVMETHOD(ifdi_stop, bnxt_stop), + DEVMETHOD(ifdi_multi_set, bnxt_multi_set), + DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set), + DEVMETHOD(ifdi_media_status, bnxt_media_status), + DEVMETHOD(ifdi_media_change, bnxt_media_change), + DEVMETHOD(ifdi_promisc_set, bnxt_promisc_set), + DEVMETHOD(ifdi_get_counter, bnxt_get_counter), + DEVMETHOD(ifdi_update_admin_status, bnxt_update_admin_status), + + DEVMETHOD(ifdi_intr_enable, bnxt_intr_enable), + DEVMETHOD(ifdi_queue_intr_enable, bnxt_queue_intr_enable), + DEVMETHOD(ifdi_intr_disable, bnxt_disable_intr), + DEVMETHOD(ifdi_msix_intr_assign, bnxt_msix_intr_assign), + + DEVMETHOD(ifdi_vlan_register, bnxt_vlan_register), + DEVMETHOD(ifdi_vlan_unregister, bnxt_vlan_unregister), + + DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl), + + DEVMETHOD_END +}; + +static driver_t bnxt_iflib_driver = { + "bnxt", bnxt_iflib_methods, sizeof(struct bnxt_softc) +}; + +/* + * iflib shared context + */ + +char bnxt_driver_version[] = "https://github.com/Broadcom/freebsd-nxt/commits/bnxt-dev"; +extern struct if_txrx bnxt_txrx; +static struct if_shared_ctx bnxt_sctx_init = { + .isc_magic = IFLIB_MAGIC, + .isc_txrx = &bnxt_txrx, + .isc_driver = &bnxt_iflib_driver, + .isc_nfl = 2, // Number of Free Lists + .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ, + .isc_q_align = PAGE_SIZE, + .isc_tx_maxsize = BNXT_TSO_SIZE, + .isc_tx_maxsegsize = BNXT_TSO_SIZE, + .isc_rx_maxsize = BNXT_TSO_SIZE, + .isc_rx_maxsegsize = BNXT_TSO_SIZE, + + // Only use a single segment to avoid page size constraints + .isc_rx_nsegments = 1, + .isc_ntxqs = 2, + .isc_nrxqs = 3, + .isc_nrxd_min = {16, 16, 16}, + .isc_nrxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 8, + PAGE_SIZE / sizeof(struct rx_prod_pkt_bd), + PAGE_SIZE / sizeof(struct rx_prod_pkt_bd)}, + .isc_nrxd_max = {INT32_MAX, INT32_MAX, INT32_MAX}, + .isc_ntxd_min = {16, 16, 16}, + .isc_ntxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 2, + PAGE_SIZE / sizeof(struct tx_bd_short)}, + .isc_ntxd_max = {INT32_MAX, INT32_MAX, INT32_MAX}, + + .isc_admin_intrcnt = 1, + .isc_vendor_info = bnxt_vendor_info_array, + .isc_driver_version = bnxt_driver_version, +}; + +if_shared_ctx_t bnxt_sctx = &bnxt_sctx_init; + +/* + * Device Methods + */ + +static void * +bnxt_register(device_t dev) +{ + return bnxt_sctx; +} + +/* + * Device Dependent Configuration Functions +*/ + +/* Soft queue setup and teardown */ +static int +bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, + uint64_t *paddrs, int ntxqs, int ntxqsets) +{ + struct bnxt_softc *softc; + int i; + int rc; + + softc = iflib_get_softc(ctx); + + softc->tx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * ntxqsets, + M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->tx_cp_rings) { + device_printf(iflib_get_dev(ctx), + "unable to allocate TX completion rings\n"); + rc = ENOMEM; + goto cp_alloc_fail; + } + softc->tx_rings = malloc(sizeof(struct bnxt_ring) * ntxqsets, + M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->tx_rings) { + device_printf(iflib_get_dev(ctx), + "unable to allocate TX rings\n"); + rc = ENOMEM; + goto ring_alloc_fail; + } + rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * ntxqsets, + &softc->tx_stats, 0); + if (rc) + goto dma_alloc_fail; + bus_dmamap_sync(softc->tx_stats.idi_tag, softc->tx_stats.idi_map, + BUS_DMASYNC_PREREAD); + + for (i = 0; i < ntxqsets; i++) { + /* Set up the completion ring */ + softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; + softc->tx_cp_rings[i].ring.phys_id = + (uint16_t)HWRM_NA_SIGNATURE; + softc->tx_cp_rings[i].ring.softc = softc; + softc->tx_cp_rings[i].ring.id = + (softc->scctx->isc_nrxqsets * 2) + 1 + i; + softc->tx_cp_rings[i].ring.doorbell = + softc->tx_cp_rings[i].ring.id * 0x80; + softc->tx_cp_rings[i].ring.ring_size = + softc->scctx->isc_ntxd[0]; + softc->tx_cp_rings[i].ring.vaddr = vaddrs[i * ntxqs]; + softc->tx_cp_rings[i].ring.paddr = paddrs[i * ntxqs]; + + /* Set up the TX ring */ + softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->tx_rings[i].softc = softc; + softc->tx_rings[i].id = + (softc->scctx->isc_nrxqsets * 2) + 1 + i; + softc->tx_rings[i].doorbell = softc->tx_rings[i].id * 0x80; + softc->tx_rings[i].ring_size = softc->scctx->isc_ntxd[1]; + softc->tx_rings[i].vaddr = vaddrs[i * ntxqs + 1]; + softc->tx_rings[i].paddr = paddrs[i * ntxqs + 1]; + + bnxt_create_tx_sysctls(softc, i); + } + + softc->ntxqsets = ntxqsets; + return rc; + +dma_alloc_fail: + free(softc->tx_rings, M_DEVBUF); +ring_alloc_fail: + free(softc->tx_cp_rings, M_DEVBUF); +cp_alloc_fail: + return rc; +} + +static void +bnxt_queues_free(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + + // Free TX queues + iflib_dma_free(&softc->tx_stats); + free(softc->tx_rings, M_DEVBUF); + softc->tx_rings = NULL; + free(softc->tx_cp_rings, M_DEVBUF); + softc->tx_cp_rings = NULL; + softc->ntxqsets = 0; + + // Free RX queues + iflib_dma_free(&softc->rx_stats); + free(softc->grp_info, M_DEVBUF); + free(softc->ag_rings, M_DEVBUF); + free(softc->rx_rings, M_DEVBUF); + free(softc->rx_cp_rings, M_DEVBUF); +} + +static int +bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, + uint64_t *paddrs, int nrxqs, int nrxqsets) +{ + struct bnxt_softc *softc; + int i; + int rc; + + softc = iflib_get_softc(ctx); + + softc->rx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * nrxqsets, + M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->rx_cp_rings) { + device_printf(iflib_get_dev(ctx), + "unable to allocate RX completion rings\n"); + rc = ENOMEM; + goto cp_alloc_fail; + } + softc->rx_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets, + M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->rx_rings) { + device_printf(iflib_get_dev(ctx), + "unable to allocate RX rings\n"); + rc = ENOMEM; + goto ring_alloc_fail; + } + softc->ag_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets, + M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->ag_rings) { + device_printf(iflib_get_dev(ctx), + "unable to allocate aggregation rings\n"); + rc = ENOMEM; + goto ag_alloc_fail; + } + softc->grp_info = malloc(sizeof(struct bnxt_grp_info) * nrxqsets, + M_DEVBUF, M_NOWAIT | M_ZERO); + if (!softc->grp_info) { + device_printf(iflib_get_dev(ctx), + "unable to allocate ring groups\n"); + rc = ENOMEM; + goto grp_alloc_fail; + } + + rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * nrxqsets, + &softc->rx_stats, 0); + if (rc) + goto hw_stats_alloc_fail; + bus_dmamap_sync(softc->rx_stats.idi_tag, softc->rx_stats.idi_map, + BUS_DMASYNC_PREREAD); + + for (i = 0; i < nrxqsets; i++) { + /* Allocation the completion ring */ + softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; + softc->rx_cp_rings[i].ring.phys_id = + (uint16_t)HWRM_NA_SIGNATURE; + softc->rx_cp_rings[i].ring.softc = softc; + softc->rx_cp_rings[i].ring.id = i + 1; + softc->rx_cp_rings[i].ring.doorbell = + softc->rx_cp_rings[i].ring.id * 0x80; + /* + * If this ring overflows, RX stops working. + */ + softc->rx_cp_rings[i].ring.ring_size = + softc->scctx->isc_nrxd[0]; + softc->rx_cp_rings[i].ring.vaddr = vaddrs[i * nrxqs]; + softc->rx_cp_rings[i].ring.paddr = paddrs[i * nrxqs]; + + /* Allocate the RX ring */ + softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->rx_rings[i].softc = softc; + softc->rx_rings[i].id = i + 1; + softc->rx_rings[i].doorbell = softc->rx_rings[i].id * 0x80; + softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1]; + softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1]; + softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1]; + + /* Allocate the AG ring */ + softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->ag_rings[i].softc = softc; + softc->ag_rings[i].id = nrxqsets + i + 1; + softc->ag_rings[i].doorbell = softc->ag_rings[i].id * 0x80; + softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2]; + softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2]; + softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2]; + + /* Allocate the ring group */ + softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->grp_info[i].stats_ctx = + softc->rx_cp_rings[i].stats_ctx_id; + softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; + softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; + softc->grp_info[i].cp_ring_id = + softc->rx_cp_rings[i].ring.phys_id; + + bnxt_create_rx_sysctls(softc, i); + } + + /* And finally, the VNIC */ + softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; + softc->vnic_info.flow_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->vnic_info.filter_id = -1; + softc->vnic_info.def_ring_grp = (uint16_t)HWRM_NA_SIGNATURE; + softc->vnic_info.cos_rule = (uint16_t)HWRM_NA_SIGNATURE; + softc->vnic_info.lb_rule = (uint16_t)HWRM_NA_SIGNATURE; + softc->vnic_info.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST; + softc->vnic_info.mc_list_count = 0; + softc->vnic_info.flags = BNXT_VNIC_FLAG_DEFAULT; + rc = iflib_dma_alloc(ctx, BNXT_MAX_MC_ADDRS * ETHER_ADDR_LEN, + &softc->vnic_info.mc_list, 0); + if (rc) + goto mc_list_alloc_fail; + + /* The VNIC RSS Hash Key */ + rc = iflib_dma_alloc(ctx, HW_HASH_KEY_SIZE, + &softc->vnic_info.rss_hash_key_tbl, 0); + if (rc) + goto rss_hash_alloc_fail; + bus_dmamap_sync(softc->vnic_info.rss_hash_key_tbl.idi_tag, + softc->vnic_info.rss_hash_key_tbl.idi_map, + BUS_DMASYNC_PREWRITE); + memcpy(softc->vnic_info.rss_hash_key_tbl.idi_vaddr, + softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE); + + /* Allocate the RSS tables */ + rc = iflib_dma_alloc(ctx, HW_HASH_INDEX_SIZE * sizeof(uint16_t), + &softc->vnic_info.rss_grp_tbl, 0); + if (rc) + goto rss_grp_alloc_fail; + bus_dmamap_sync(softc->vnic_info.rss_grp_tbl.idi_tag, + softc->vnic_info.rss_grp_tbl.idi_map, + BUS_DMASYNC_PREWRITE); + memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff, + softc->vnic_info.rss_grp_tbl.idi_size); + + softc->nrxqsets = nrxqsets; + return rc; + +rss_grp_alloc_fail: + iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); +rss_hash_alloc_fail: + iflib_dma_free(&softc->vnic_info.mc_list); +mc_list_alloc_fail: + iflib_dma_free(&softc->rx_stats); +hw_stats_alloc_fail: + free(softc->grp_info, M_DEVBUF); +grp_alloc_fail: + free(softc->ag_rings, M_DEVBUF); +ag_alloc_fail: + free(softc->rx_rings, M_DEVBUF); +ring_alloc_fail: + free(softc->rx_cp_rings, M_DEVBUF); +cp_alloc_fail: + return rc; +} + +/* Device setup and teardown */ +static int +bnxt_attach_pre(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + if_softc_ctx_t scctx; + int rc = 0; + + softc->ctx = ctx; + softc->dev = iflib_get_dev(ctx); + softc->media = iflib_get_media(ctx); + softc->scctx = iflib_get_softc_ctx(ctx); + softc->sctx = iflib_get_sctx(ctx); + scctx = softc->scctx; + + switch (softc->sctx->isc_vendor_info->pvi_device_id) { + case BCM57402_NPAR: + case BCM57404_NPAR: + case BCM57406_NPAR: + softc->flags |= BNXT_FLAG_NPAR; + break; + case BCM57304_VF: + case BCM57404_VF: + softc->flags |= BNXT_FLAG_VF; + break; + } + + pci_enable_busmaster(softc->dev); + + if (bnxt_pci_mapping(softc)) + return (ENXIO); + + /* HWRM setup/init */ + BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev)); + rc = bnxt_alloc_hwrm_dma_mem(softc); + if (rc) + goto dma_fail; + + /* Allocate the TPA start buffer */ + softc->tpa_start = malloc(sizeof(struct bnxt_full_tpa_start) * + (RX_TPA_START_CMPL_AGG_ID_MASK >> RX_TPA_START_CMPL_AGG_ID_SFT), + M_DEVBUF, M_NOWAIT | M_ZERO); + if (softc->tpa_start == NULL) { + rc = ENOMEM; + device_printf(softc->dev, + "Unable to allocate space for TPA\n"); + goto tpa_failed; + } + + /* Get firmware version and compare with driver */ + softc->ver_info = malloc(sizeof(struct bnxt_ver_info), + M_DEVBUF, M_NOWAIT | M_ZERO); + if (softc->ver_info == NULL) { + rc = ENOMEM; + device_printf(softc->dev, + "Unable to allocate space for version info\n"); + goto ver_alloc_fail; + } + /* Default minimum required HWRM version */ + softc->ver_info->hwrm_min_major = 1; + softc->ver_info->hwrm_min_minor = 2; + softc->ver_info->hwrm_min_update = 2; + + rc = bnxt_hwrm_ver_get(softc); + if (rc) { + device_printf(softc->dev, "attach: hwrm ver get failed\n"); + goto ver_fail; + } + + /* Get NVRAM info */ + softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info), + M_DEVBUF, M_NOWAIT | M_ZERO); + if (softc->nvm_info == NULL) { + rc = ENOMEM; + device_printf(softc->dev, + "Unable to allocate space for NVRAM info\n"); + goto nvm_alloc_fail; + } + rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id, + &softc->nvm_info->device_id, &softc->nvm_info->sector_size, + &softc->nvm_info->size, &softc->nvm_info->reserved_size, + &softc->nvm_info->available_size); + + /* Register the driver with the FW */ + rc = bnxt_hwrm_func_drv_rgtr(softc); + if (rc) { + device_printf(softc->dev, "attach: hwrm drv rgtr failed\n"); + goto drv_rgtr_fail; + } + + /* Get the HW capabilities */ + rc = bnxt_hwrm_func_qcaps(softc); + if (rc) + goto failed; + iflib_set_mac(ctx, softc->func.mac_addr); + + /* Get the queue config */ + rc = bnxt_hwrm_queue_qportcfg(softc); + if (rc) { + device_printf(softc->dev, "attach: hwrm qportcfg failed\n"); + goto failed; + } + + /* Now perform a function reset */ + rc = bnxt_hwrm_func_reset(softc); + bnxt_clear_ids(softc); + if (rc) + goto failed; + + /* Now set up iflib sc */ + scctx->isc_tx_nsegments = 31, + scctx->isc_tx_tso_segments_max = 31; + scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE; + scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE; + scctx->isc_vectors = softc->func.max_cp_rings; + if (scctx->isc_nrxd[0] < + ((scctx->isc_nrxd[1] * 4) + scctx->isc_nrxd[2])) + device_printf(softc->dev, + "WARNING: nrxd0 (%d) should be at least 4 * nrxd1 (%d) + nrxd2 (%d). Driver may be unstable\n", + scctx->isc_nrxd[0], scctx->isc_nrxd[1], scctx->isc_nrxd[2]); + if (scctx->isc_ntxd[0] < scctx->isc_ntxd[1] * 2) + device_printf(softc->dev, + "WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d). Driver may be unstable\n", + scctx->isc_ntxd[0], scctx->isc_ntxd[1]); + scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0]; + scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) * + scctx->isc_ntxd[1]; + scctx->isc_rxqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_nrxd[0]; + scctx->isc_rxqsizes[1] = sizeof(struct rx_prod_pkt_bd) * + scctx->isc_nrxd[1]; + scctx->isc_rxqsizes[2] = sizeof(struct rx_prod_pkt_bd) * + scctx->isc_nrxd[2]; + scctx->isc_max_rxqsets = min(pci_msix_count(softc->dev)-1, + softc->func.max_cp_rings - 1); + scctx->isc_max_rxqsets = min(scctx->isc_max_rxqsets, + softc->func.max_rx_rings); + scctx->isc_max_txqsets = min(softc->func.max_rx_rings, + softc->func.max_cp_rings - scctx->isc_max_rxqsets - 1); + scctx->isc_rss_table_size = HW_HASH_INDEX_SIZE; + scctx->isc_rss_table_mask = scctx->isc_rss_table_size - 1; + + /* iflib will map and release this bar */ + scctx->isc_msix_bar = pci_msix_table_bar(softc->dev); + + /* Allocate the default completion ring */ + softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; + softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->def_cp_ring.ring.softc = softc; + softc->def_cp_ring.ring.id = 0; + softc->def_cp_ring.ring.doorbell = softc->def_cp_ring.ring.id * 0x80; + softc->def_cp_ring.ring.ring_size = PAGE_SIZE / + sizeof(struct cmpl_base); + rc = iflib_dma_alloc(ctx, + sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size, + &softc->def_cp_ring_mem, 0); + softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr; + softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr; + iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task, + "dflt_cp"); + + rc = bnxt_init_sysctl_ctx(softc); + if (rc) + goto init_sysctl_failed; + rc = bnxt_create_nvram_sysctls(softc->nvm_info); + if (rc) + goto failed; + + arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0); + softc->vnic_info.rss_hash_type = + HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 | + HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 | + HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 | + HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 | + HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 | + HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6; + rc = bnxt_create_config_sysctls_pre(softc); + if (rc) + goto failed; + + /* Initialize the vlan list */ + SLIST_INIT(&softc->vnic_info.vlan_tags); + softc->vnic_info.vlan_tag_list.idi_vaddr = NULL; + + return (rc); + +failed: + bnxt_free_sysctl_ctx(softc); +init_sysctl_failed: + bnxt_hwrm_func_drv_unrgtr(softc, false); +drv_rgtr_fail: + free(softc->nvm_info, M_DEVBUF); +nvm_alloc_fail: +ver_fail: + free(softc->ver_info, M_DEVBUF); +ver_alloc_fail: + free(softc->tpa_start, M_DEVBUF); +tpa_failed: + bnxt_free_hwrm_dma_mem(softc); +dma_fail: + BNXT_HWRM_LOCK_DESTROY(softc); + bnxt_pci_mapping_free(softc); + pci_disable_busmaster(softc->dev); + return (rc); +} + +static int +bnxt_attach_post(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + if_t ifp = iflib_get_ifp(ctx); + int capabilities, enabling; + int rc; + + bnxt_create_config_sysctls_post(softc); + + /* Update link state etc... */ + rc = bnxt_probe_phy(softc); + if (rc) + goto failed; + + /* Needs to be done after probing the phy */ + bnxt_create_ver_sysctls(softc); + bnxt_add_media_types(softc); + ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); + + if_sethwassist(ifp, (CSUM_TCP | CSUM_UDP | CSUM_TCP_IPV6 | + CSUM_UDP_IPV6 | CSUM_TSO)); + + capabilities = + /* These are translated to hwassit bits */ + IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 | + /* These are checked by iflib */ + IFCAP_LRO | IFCAP_VLAN_HWFILTER | + /* These are part of the iflib mask */ + IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_VLAN_MTU | + IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | + /* These likely get lost... */ + IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU; + + if_setcapabilities(ifp, capabilities); + + enabling = capabilities; + + if_setcapenable(ifp, enabling); + + softc->scctx->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + + ETHER_CRC_LEN; + +failed: + return rc; +} + +static int +bnxt_detach(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct bnxt_vlan_tag *tag; + struct bnxt_vlan_tag *tmp; + int i; + + bnxt_do_disable_intr(&softc->def_cp_ring); + bnxt_free_sysctl_ctx(softc); + bnxt_hwrm_func_reset(softc); + bnxt_clear_ids(softc); + iflib_irq_free(ctx, &softc->def_cp_ring.irq); + iflib_config_gtask_deinit(&softc->def_cp_task); + /* We need to free() these here... */ + for (i = softc->nrxqsets-1; i>=0; i--) { + iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); + } + iflib_dma_free(&softc->vnic_info.mc_list); + iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); + iflib_dma_free(&softc->vnic_info.rss_grp_tbl); + if (softc->vnic_info.vlan_tag_list.idi_vaddr) + iflib_dma_free(&softc->vnic_info.vlan_tag_list); + SLIST_FOREACH_SAFE(tag, &softc->vnic_info.vlan_tags, next, tmp) + free(tag, M_DEVBUF); + iflib_dma_free(&softc->def_cp_ring_mem); + free(softc->tpa_start, M_DEVBUF); + free(softc->ver_info, M_DEVBUF); + free(softc->nvm_info, M_DEVBUF); + + bnxt_hwrm_func_drv_unrgtr(softc, false); + bnxt_free_hwrm_dma_mem(softc); + BNXT_HWRM_LOCK_DESTROY(softc); + + pci_disable_busmaster(softc->dev); + bnxt_pci_mapping_free(softc); + + return 0; +} + +/* Device configuration */ +static void +bnxt_init(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct ifmediareq ifmr; + int i, j; + int rc; + + rc = bnxt_hwrm_func_reset(softc); + if (rc) + return; + bnxt_clear_ids(softc); + + /* Allocate the default completion ring */ + softc->def_cp_ring.cons = UINT32_MAX; + softc->def_cp_ring.v_bit = 1; + bnxt_mark_cpr_invalid(&softc->def_cp_ring); + rc = bnxt_hwrm_ring_alloc(softc, + HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, + &softc->def_cp_ring.ring, + (uint16_t)HWRM_NA_SIGNATURE, + HWRM_NA_SIGNATURE, true); + if (rc) + goto fail; + + /* And now set the default CP ring as the async CP ring */ + rc = bnxt_hwrm_func_cfg(softc); + if (rc) + goto fail; + + for (i = 0; i < softc->nrxqsets; i++) { + /* Allocate the statistics context */ + rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i], + softc->rx_stats.idi_paddr + + (sizeof(struct ctx_hw_stats) * i)); + if (rc) + goto fail; + + /* Allocate the completion ring */ + softc->rx_cp_rings[i].cons = UINT32_MAX; + softc->rx_cp_rings[i].v_bit = 1; + softc->rx_cp_rings[i].last_idx = UINT32_MAX; + bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]); + rc = bnxt_hwrm_ring_alloc(softc, + HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, + &softc->rx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, + HWRM_NA_SIGNATURE, true); + if (rc) + goto fail; + + /* Allocate the RX ring */ + rc = bnxt_hwrm_ring_alloc(softc, + HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, + &softc->rx_rings[i], (uint16_t)HWRM_NA_SIGNATURE, + HWRM_NA_SIGNATURE, false); + if (rc) + goto fail; + BNXT_RX_DB(&softc->rx_rings[i], 0); + /* TODO: Cumulus+ doesn't need the double doorbell */ + BNXT_RX_DB(&softc->rx_rings[i], 0); + + /* Allocate the AG ring */ + rc = bnxt_hwrm_ring_alloc(softc, + HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, + &softc->ag_rings[i], (uint16_t)HWRM_NA_SIGNATURE, + HWRM_NA_SIGNATURE, false); + if (rc) + goto fail; + BNXT_RX_DB(&softc->rx_rings[i], 0); + /* TODO: Cumulus+ doesn't need the double doorbell */ + BNXT_RX_DB(&softc->ag_rings[i], 0); + + /* Allocate the ring group */ + softc->grp_info[i].stats_ctx = + softc->rx_cp_rings[i].stats_ctx_id; + softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; + softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; + softc->grp_info[i].cp_ring_id = + softc->rx_cp_rings[i].ring.phys_id; + rc = bnxt_hwrm_ring_grp_alloc(softc, &softc->grp_info[i]); + if (rc) + goto fail; + + } + + /* Allocate the VNIC RSS context */ + rc = bnxt_hwrm_vnic_ctx_alloc(softc, &softc->vnic_info.rss_id); + if (rc) + goto fail; + + /* Allocate the vnic */ + softc->vnic_info.def_ring_grp = softc->grp_info[0].grp_id; + softc->vnic_info.mru = softc->scctx->isc_max_frame_size; + rc = bnxt_hwrm_vnic_alloc(softc, &softc->vnic_info); + if (rc) + goto fail; + rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info); + if (rc) + goto fail; + rc = bnxt_hwrm_set_filter(softc, &softc->vnic_info); + if (rc) + goto fail; + + /* Enable RSS on the VNICs */ + for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) { + ((uint16_t *) + softc->vnic_info.rss_grp_tbl.idi_vaddr)[i] = + htole16(softc->grp_info[j].grp_id); + if (++j == softc->nrxqsets) + j = 0; + } + + rc = bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, + softc->vnic_info.rss_hash_type); + if (rc) + goto fail; + +#ifdef notyet + /* Enable LRO/TPA/GRO */ + rc = bnxt_hwrm_vnic_tpa_cfg(softc, &softc->vnic_info, + (if_getcapenable(iflib_get_ifp(ctx)) & IFCAP_LRO) ? + HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA : 0); + if (rc) + goto fail; +#endif + + for (i = 0; i < softc->ntxqsets; i++) { + /* Allocate the statistics context */ + rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->tx_cp_rings[i], + softc->tx_stats.idi_paddr + + (sizeof(struct ctx_hw_stats) * i)); + if (rc) + goto fail; + + /* Allocate the completion ring */ + softc->tx_cp_rings[i].cons = UINT32_MAX; + softc->tx_cp_rings[i].v_bit = 1; + bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]); + rc = bnxt_hwrm_ring_alloc(softc, + HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, + &softc->tx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, + HWRM_NA_SIGNATURE, false); + if (rc) + goto fail; + + /* Allocate the TX ring */ + rc = bnxt_hwrm_ring_alloc(softc, + HWRM_RING_ALLOC_INPUT_RING_TYPE_TX, + &softc->tx_rings[i], softc->tx_cp_rings[i].ring.phys_id, + softc->tx_cp_rings[i].stats_ctx_id, false); + if (rc) + goto fail; + BNXT_TX_DB(&softc->tx_rings[i], 0); + /* TODO: Cumulus+ doesn't need the double doorbell */ + BNXT_TX_DB(&softc->tx_rings[i], 0); + } + + bnxt_do_enable_intr(&softc->def_cp_ring); + bnxt_media_status(softc->ctx, &ifmr); + return; + +fail: + bnxt_hwrm_func_reset(softc); + bnxt_clear_ids(softc); + return; +} + +static void +bnxt_stop(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + + bnxt_do_disable_intr(&softc->def_cp_ring); + bnxt_hwrm_func_reset(softc); + bnxt_clear_ids(softc); + return; +} + +static void +bnxt_multi_set(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + if_t ifp = iflib_get_ifp(ctx); + uint8_t *mta; + int cnt, mcnt; + + mcnt = if_multiaddr_count(ifp, -1); + + if (mcnt > BNXT_MAX_MC_ADDRS) { + softc->vnic_info.rx_mask |= + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; + bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); + } + else { + softc->vnic_info.rx_mask &= + ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; + mta = softc->vnic_info.mc_list.idi_vaddr; + bzero(mta, softc->vnic_info.mc_list.idi_size); + if_multiaddr_array(ifp, mta, &cnt, mcnt); + bus_dmamap_sync(softc->vnic_info.mc_list.idi_tag, + softc->vnic_info.mc_list.idi_map, BUS_DMASYNC_PREWRITE); + softc->vnic_info.mc_list_count = cnt; + softc->vnic_info.rx_mask |= + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST; + if (bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info)) + device_printf(softc->dev, + "set_multi: rx_mask set failed\n"); + } +} + +static int +bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + + if (mtu > BNXT_MAX_MTU) + return EINVAL; + + softc->scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; + return 0; +} + +static void +bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct bnxt_link_info *link_info = &softc->link_info; + uint8_t phy_type = get_phy_type(softc); + + bnxt_update_link(softc, true); + + ifmr->ifm_status = IFM_AVALID; + ifmr->ifm_active = IFM_ETHER; + + if (link_info->link_up) + ifmr->ifm_status |= IFM_ACTIVE; + else + ifmr->ifm_status &= ~IFM_ACTIVE; + + if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL) + ifmr->ifm_active |= IFM_FDX; + else + ifmr->ifm_active |= IFM_HDX; + + switch (link_info->link_speed) { + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB: + ifmr->ifm_active |= IFM_100_T; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB: + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: + ifmr->ifm_active |= IFM_1000_KX; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: + ifmr->ifm_active |= IFM_1000_T; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: + ifmr->ifm_active |= IFM_1000_SGMII; + break; + default: + ifmr->ifm_active |= IFM_UNKNOWN; + break; + } + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB: + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: + ifmr->ifm_active |= IFM_2500_KX; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: + ifmr->ifm_active |= IFM_2500_T; + break; + default: + ifmr->ifm_active |= IFM_UNKNOWN; + break; + } + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB: + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: + ifmr->ifm_active |= IFM_10G_CR1; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: + ifmr->ifm_active |= IFM_10G_KR; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: + ifmr->ifm_active |= IFM_10G_LR; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: + ifmr->ifm_active |= IFM_10G_SR; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: + ifmr->ifm_active |= IFM_10G_KX4; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: + ifmr->ifm_active |= IFM_10G_T; + break; + default: + ifmr->ifm_active |= IFM_UNKNOWN; + break; + } + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB: + ifmr->ifm_active |= IFM_20G_KR2; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB: + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: + ifmr->ifm_active |= IFM_25G_CR; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: + ifmr->ifm_active |= IFM_25G_KR; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: + ifmr->ifm_active |= IFM_25G_SR; + break; + default: + ifmr->ifm_active |= IFM_UNKNOWN; + break; + } + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB: + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: + ifmr->ifm_active |= IFM_40G_CR4; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: + ifmr->ifm_active |= IFM_40G_KR4; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: + ifmr->ifm_active |= IFM_40G_LR4; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: + ifmr->ifm_active |= IFM_40G_SR4; + break; + default: + ifmr->ifm_active |= IFM_UNKNOWN; + break; + } + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: + ifmr->ifm_active |= IFM_50G_CR2; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: + ifmr->ifm_active |= IFM_50G_KR2; + break; + default: + ifmr->ifm_active |= IFM_UNKNOWN; + break; + } + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: + ifmr->ifm_active |= IFM_100G_CR4; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: + ifmr->ifm_active |= IFM_100G_KR4; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: + ifmr->ifm_active |= IFM_100G_LR4; + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: + ifmr->ifm_active |= IFM_100G_SR4; + break; + default: + ifmr->ifm_active |= IFM_UNKNOWN; + break; + } + default: + return; + } + + if (link_info->pause == (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) + ifmr->ifm_active |= (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE); + else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) + ifmr->ifm_active |= IFM_ETH_TXPAUSE; + else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) + ifmr->ifm_active |= IFM_ETH_RXPAUSE; + + bnxt_report_link(softc); + return; +} + +static int +bnxt_media_change(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct ifmedia *ifm = iflib_get_media(ctx); + struct ifmediareq ifmr; + int rc; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return EINVAL; + + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_100_T: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB; + break; + case IFM_1000_KX: + case IFM_1000_T: + case IFM_1000_SGMII: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB; + break; + case IFM_2500_KX: + case IFM_2500_T: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB; + break; + case IFM_10G_CR1: + case IFM_10G_KR: + case IFM_10G_LR: + case IFM_10G_SR: + case IFM_10G_T: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB; + break; + case IFM_20G_KR2: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB; + break; + case IFM_25G_CR: + case IFM_25G_KR: + case IFM_25G_SR: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB; + break; + case IFM_40G_CR4: + case IFM_40G_KR4: + case IFM_40G_LR4: + case IFM_40G_SR4: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB; + break; + case IFM_50G_CR2: + case IFM_50G_KR2: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB; + break; + case IFM_100G_CR4: + case IFM_100G_KR4: + case IFM_100G_LR4: + case IFM_100G_SR4: + softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; + softc->link_info.req_link_speed = + HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB; + break; + default: + device_printf(softc->dev, + "Unsupported media type! Using auto\n"); + /* Fall-through */ + case IFM_AUTO: + // Auto + softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; + break; + } + rc = bnxt_hwrm_set_link_setting(softc, true, true); + bnxt_media_status(softc->ctx, &ifmr); + return rc; +} + +static int +bnxt_promisc_set(if_ctx_t ctx, int flags) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + if_t ifp = iflib_get_ifp(ctx); + int rc; + + if (ifp->if_flags & IFF_ALLMULTI || + if_multiaddr_count(ifp, -1) > BNXT_MAX_MC_ADDRS) + softc->vnic_info.rx_mask |= + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; + else + softc->vnic_info.rx_mask &= + ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; + + if (ifp->if_flags & IFF_PROMISC) + softc->vnic_info.rx_mask |= + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS | + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN; + else + softc->vnic_info.rx_mask &= + ~(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS | + HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN); + + rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); + + return rc; +} + +static uint64_t +bnxt_get_counter(if_ctx_t ctx, ift_counter cnt) +{ + if_t ifp = iflib_get_ifp(ctx); + + if (cnt < IFCOUNTERS) + return if_get_counter_default(ifp, cnt); + + return 0; +} + +static void +bnxt_update_admin_status(if_ctx_t ctx) +{ + /* TODO: do we need to do anything here? */ + return; +} + +static void inline +bnxt_do_enable_intr(struct bnxt_cp_ring *cpr) +{ + if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) { + /* First time enabling, do not set index */ + if (cpr->cons == UINT32_MAX) + BNXT_CP_ENABLE_DB(&cpr->ring); + else + BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons); + } +} + +static void inline +bnxt_do_disable_intr(struct bnxt_cp_ring *cpr) +{ + if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) + BNXT_CP_DISABLE_DB(&cpr->ring); +} + +/* Enable all interrupts */ +static void +bnxt_intr_enable(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + int i; + + bnxt_do_enable_intr(&softc->def_cp_ring); + for (i = 0; i < softc->nrxqsets; i++) + bnxt_do_enable_intr(&softc->rx_cp_rings[i]); + + return; +} + +/* Enable interrupt for a single queue */ +static int +bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + + bnxt_do_enable_intr(&softc->rx_cp_rings[qid]); + return 0; +} + +/* Disable all interrupts */ +static void +bnxt_disable_intr(if_ctx_t ctx) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + int i; + + /* + * NOTE: These TX interrupts should never get enabled, so don't + * update the index + */ + for (i = 0; i < softc->ntxqsets; i++) + bnxt_do_disable_intr(&softc->tx_cp_rings[i]); + for (i = 0; i < softc->nrxqsets; i++) + bnxt_do_disable_intr(&softc->rx_cp_rings[i]); + + return; +} + +static int +bnxt_msix_intr_assign(if_ctx_t ctx, int msix) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + int rc; + int i; + + rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq, + softc->def_cp_ring.ring.id + 1, IFLIB_INTR_ADMIN, + bnxt_handle_def_cp, softc, 0, "def_cp"); + if (rc) { + device_printf(iflib_get_dev(ctx), + "Failed to register default completion ring handler\n"); + return rc; + } + + for (i=0; iscctx->isc_nrxqsets; i++) { + rc = iflib_irq_alloc_generic(ctx, &softc->rx_cp_rings[i].irq, + softc->rx_cp_rings[i].ring.id + 1, IFLIB_INTR_RX, + bnxt_handle_rx_cp, &softc->rx_cp_rings[i], i, "rx_cp"); + if (rc) { + device_printf(iflib_get_dev(ctx), + "Failed to register RX completion ring handler\n"); + i--; + goto fail; + } + } + + for (i=0; iscctx->isc_ntxqsets; i++) + iflib_softirq_alloc_generic(ctx, i + 1, IFLIB_INTR_TX, NULL, i, + "tx_cp"); + + return rc; + +fail: + for (; i>=0; i--) + iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); + iflib_irq_free(ctx, &softc->def_cp_ring.irq); + return rc; +} + +/* + * We're explicitly allowing duplicates here. They will need to be + * removed as many times as they are added. + */ +static void +bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct bnxt_vlan_tag *new_tag; + + new_tag = malloc(sizeof(struct bnxt_vlan_tag), M_DEVBUF, M_NOWAIT); + if (new_tag == NULL) + return; + new_tag->tag = vtag; + new_tag->tpid = 8100; + SLIST_INSERT_HEAD(&softc->vnic_info.vlan_tags, new_tag, next); +}; + +static void +bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct bnxt_vlan_tag *vlan_tag; + + SLIST_FOREACH(vlan_tag, &softc->vnic_info.vlan_tags, next) { + if (vlan_tag->tag == vtag) { + SLIST_REMOVE(&softc->vnic_info.vlan_tags, vlan_tag, + bnxt_vlan_tag, next); + free(vlan_tag, M_DEVBUF); + break; + } + } +} + +static int +bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) +{ + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct ifreq *ifr = (struct ifreq *)data; + struct ifreq_buffer *ifbuf = &ifr->ifr_ifru.ifru_buffer; + struct bnxt_ioctl_header *ioh = + (struct bnxt_ioctl_header *)(ifbuf->buffer); + int rc = ENOTSUP; + struct bnxt_ioctl_data *iod = NULL; + + switch (command) { + case SIOCGPRIVATE_0: + if ((rc = priv_check(curthread, PRIV_DRIVER)) != 0) + goto exit; + + iod = malloc(ifbuf->length, M_DEVBUF, M_NOWAIT | M_ZERO); + if (!iod) { + rc = ENOMEM; + goto exit; + } + copyin(ioh, iod, ifbuf->length); + + switch (ioh->type) { + case BNXT_HWRM_NVM_FIND_DIR_ENTRY: + { + struct bnxt_ioctl_hwrm_nvm_find_dir_entry *find = + &iod->find; + + rc = bnxt_hwrm_nvm_find_dir_entry(softc, find->type, + &find->ordinal, find->ext, &find->index, + find->use_index, find->search_opt, + &find->data_length, &find->item_length, + &find->fw_ver); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_READ: + { + struct bnxt_ioctl_hwrm_nvm_read *rd = &iod->read; + struct iflib_dma_info dma_data; + size_t offset; + size_t remain; + size_t csize; + + /* + * Some HWRM versions can't read more than 0x8000 bytes + */ + rc = iflib_dma_alloc(softc->ctx, + min(rd->length, 0x8000), &dma_data, BUS_DMA_NOWAIT); + if (rc) + break; + for (remain = rd->length, offset = 0; + remain && offset < rd->length; offset += 0x8000) { + csize = min(remain, 0x8000); + rc = bnxt_hwrm_nvm_read(softc, rd->index, + rd->offset + offset, csize, &dma_data); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + break; + } + else { + copyout(dma_data.idi_vaddr, + rd->data + offset, csize); + iod->hdr.rc = 0; + } + remain -= csize; + } + if (iod->hdr.rc == 0) + copyout(iod, ioh, ifbuf->length); + + iflib_dma_free(&dma_data); + rc = 0; + goto exit; + } + case BNXT_HWRM_FW_RESET: + { + struct bnxt_ioctl_hwrm_fw_reset *rst = + &iod->reset; + + rc = bnxt_hwrm_fw_reset(softc, rst->processor, + &rst->selfreset); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_FW_QSTATUS: + { + struct bnxt_ioctl_hwrm_fw_qstatus *qstat = + &iod->status; + + rc = bnxt_hwrm_fw_qstatus(softc, qstat->processor, + &qstat->selfreset); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_WRITE: + { + struct bnxt_ioctl_hwrm_nvm_write *wr = + &iod->write; + + rc = bnxt_hwrm_nvm_write(softc, wr->data, true, + wr->type, wr->ordinal, wr->ext, wr->attr, + wr->option, wr->data_length, wr->keep, + &wr->item_length, &wr->index); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_ERASE_DIR_ENTRY: + { + struct bnxt_ioctl_hwrm_nvm_erase_dir_entry *erase = + &iod->erase; + + rc = bnxt_hwrm_nvm_erase_dir_entry(softc, erase->index); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_GET_DIR_INFO: + { + struct bnxt_ioctl_hwrm_nvm_get_dir_info *info = + &iod->dir_info; + + rc = bnxt_hwrm_nvm_get_dir_info(softc, &info->entries, + &info->entry_length); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_GET_DIR_ENTRIES: + { + struct bnxt_ioctl_hwrm_nvm_get_dir_entries *get = + &iod->dir_entries; + struct iflib_dma_info dma_data; + + rc = iflib_dma_alloc(softc->ctx, get->max_size, + &dma_data, BUS_DMA_NOWAIT); + if (rc) + break; + rc = bnxt_hwrm_nvm_get_dir_entries(softc, &get->entries, + &get->entry_length, &dma_data); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + copyout(dma_data.idi_vaddr, get->data, + get->entry_length * get->entries); + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + iflib_dma_free(&dma_data); + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_VERIFY_UPDATE: + { + struct bnxt_ioctl_hwrm_nvm_verify_update *vrfy = + &iod->verify; + + rc = bnxt_hwrm_nvm_verify_update(softc, vrfy->type, + vrfy->ordinal, vrfy->ext); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_INSTALL_UPDATE: + { + struct bnxt_ioctl_hwrm_nvm_install_update *inst = + &iod->install; + + rc = bnxt_hwrm_nvm_install_update(softc, + inst->install_type, &inst->installed_items, + &inst->result, &inst->problem_item, + &inst->reset_required); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_NVM_MODIFY: + { + struct bnxt_ioctl_hwrm_nvm_modify *mod = &iod->modify; + + rc = bnxt_hwrm_nvm_modify(softc, mod->index, + mod->offset, mod->data, true, mod->length); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_FW_GET_TIME: + { + struct bnxt_ioctl_hwrm_fw_get_time *gtm = + &iod->get_time; + + rc = bnxt_hwrm_fw_get_time(softc, >m->year, + >m->month, >m->day, >m->hour, >m->minute, + >m->second, >m->millisecond, >m->zone); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + case BNXT_HWRM_FW_SET_TIME: + { + struct bnxt_ioctl_hwrm_fw_set_time *stm = + &iod->set_time; + + rc = bnxt_hwrm_fw_set_time(softc, stm->year, + stm->month, stm->day, stm->hour, stm->minute, + stm->second, stm->millisecond, stm->zone); + if (rc) { + iod->hdr.rc = rc; + copyout(&iod->hdr.rc, &ioh->rc, + sizeof(ioh->rc)); + } + else { + iod->hdr.rc = 0; + copyout(iod, ioh, ifbuf->length); + } + + rc = 0; + goto exit; + } + } + break; + } + +exit: + if (iod) + free(iod, M_DEVBUF); + return rc; +} + +/* + * Support functions + */ +static int +bnxt_probe_phy(struct bnxt_softc *softc) +{ + struct bnxt_link_info *link_info = &softc->link_info; + int rc = 0; + + rc = bnxt_update_link(softc, false); + if (rc) { + device_printf(softc->dev, + "Probe phy can't update link (rc: %x)\n", rc); + return (rc); + } + + /*initialize the ethool setting copy with NVM settings */ + if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) + link_info->autoneg |= BNXT_AUTONEG_SPEED; + + if (link_info->auto_pause & (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) { + if (link_info->auto_pause == ( + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) + link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; + link_info->req_flow_ctrl = link_info->auto_pause; + } else if (link_info->force_pause & ( + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) { + link_info->req_flow_ctrl = link_info->force_pause; + } + link_info->req_duplex = link_info->duplex_setting; + if (link_info->autoneg & BNXT_AUTONEG_SPEED) + link_info->req_link_speed = link_info->auto_link_speed; + else + link_info->req_link_speed = link_info->force_link_speed; + return (rc); +} + +static void +bnxt_add_media_types(struct bnxt_softc *softc) +{ + struct bnxt_link_info *link_info = &softc->link_info; + uint16_t supported; + uint8_t phy_type = get_phy_type(softc); + + supported = link_info->support_speeds; + + /* Auto is always supported */ + ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); + + if (softc->flags & BNXT_FLAG_NPAR) + return; + + switch (phy_type) { + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_100G_CR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_50G_CR2, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_40G_CR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_25G_CR, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_10G_CR1, 0, + NULL); + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN: + /* Auto only */ + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_100G_KR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_50G_KR2, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_40G_KR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_25G_KR, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_20G_KR2, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KR, 0, + NULL); + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_100G_LR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_40G_LR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_10G_LR, 0, + NULL); + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_100G_SR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_40G_SR4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_25G_SR, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_10G_SR, 0, + NULL); + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KX4, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_2500_KX, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_1000_KX, 0, + NULL); + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE: + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MB) + ifmedia_add(softc->media, IFM_ETHER | IFM_10_T, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MB) + ifmedia_add(softc->media, IFM_ETHER | IFM_100_T, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_1000_T, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_2500_T, 0, + NULL); + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_10G_T, 0, + NULL); + break; + case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) + ifmedia_add(softc->media, IFM_ETHER | IFM_1000_SGMII, 0, + NULL); + break; + } + + return; +} + +static int +bnxt_map_bar(struct bnxt_softc *softc, struct bnxt_bar_info *bar, int bar_num, bool shareable) +{ + uint32_t flag; + + if (bar->res != NULL) { + device_printf(softc->dev, "Bar %d already mapped\n", bar_num); + return EDOOFUS; + } + + bar->rid = PCIR_BAR(bar_num); + flag = RF_ACTIVE; + if (shareable) + flag |= RF_SHAREABLE; + + if ((bar->res = + bus_alloc_resource_any(softc->dev, + SYS_RES_MEMORY, + &bar->rid, + flag)) == NULL) { + device_printf(softc->dev, + "PCI BAR%d mapping failure\n", bar_num); + return (ENXIO); + } + bar->tag = rman_get_bustag(bar->res); + bar->handle = rman_get_bushandle(bar->res); + bar->size = rman_get_size(bar->res); + + return 0; +} + +static int +bnxt_pci_mapping(struct bnxt_softc *softc) +{ + int rc; + + rc = bnxt_map_bar(softc, &softc->hwrm_bar, 0, true); + if (rc) + return rc; + + rc = bnxt_map_bar(softc, &softc->doorbell_bar, 2, false); + + return rc; +} + +static void +bnxt_pci_mapping_free(struct bnxt_softc *softc) +{ + if (softc->hwrm_bar.res != NULL) + bus_release_resource(softc->dev, SYS_RES_MEMORY, + softc->hwrm_bar.rid, softc->hwrm_bar.res); + softc->hwrm_bar.res = NULL; + + if (softc->doorbell_bar.res != NULL) + bus_release_resource(softc->dev, SYS_RES_MEMORY, + softc->doorbell_bar.rid, softc->doorbell_bar.res); + softc->doorbell_bar.res = NULL; +} + +static int +bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state) +{ + struct bnxt_link_info *link_info = &softc->link_info; + uint8_t link_up = link_info->link_up; + int rc = 0; + + rc = bnxt_hwrm_port_phy_qcfg(softc); + if (rc) + goto exit; + + /* TODO: need to add more logic to report VF link */ + if (chng_link_state) { + if (link_info->phy_link_status == + HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) + link_info->link_up = 1; + else + link_info->link_up = 0; + if (link_up != link_info->link_up) + bnxt_report_link(softc); + } else { + /* always link down if not require to update link state */ + link_info->link_up = 0; + } + +exit: + return rc; +} + +void +bnxt_report_link(struct bnxt_softc *softc) +{ + const char *duplex = NULL, *flow_ctrl = NULL; + + if (softc->link_info.link_up == softc->link_info.last_link_up) { + if (!softc->link_info.link_up) + return; + if (softc->link_info.pause == softc->link_info.last_pause && + softc->link_info.duplex == softc->link_info.last_duplex) + return; + } + + if (softc->link_info.link_up) { + if (softc->link_info.duplex == + HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL) + duplex = "full duplex"; + else + duplex = "half duplex"; + if (softc->link_info.pause == ( + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) + flow_ctrl = "FC - receive & transmit"; + else if (softc->link_info.pause == + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) + flow_ctrl = "FC - transmit"; + else if (softc->link_info.pause == + HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) + flow_ctrl = "FC - receive"; + else + flow_ctrl = "none"; + iflib_link_state_change(softc->ctx, LINK_STATE_UP, + IF_Gbps(100)); + device_printf(softc->dev, "Link is UP %s, %s\n", duplex, + flow_ctrl); + } else { + iflib_link_state_change(softc->ctx, LINK_STATE_DOWN, + bnxt_get_baudrate(&softc->link_info)); + device_printf(softc->dev, "Link is Down\n"); + } + + softc->link_info.last_link_up = softc->link_info.link_up; + softc->link_info.last_pause = softc->link_info.pause; + softc->link_info.last_duplex = softc->link_info.duplex; +} + +static int +bnxt_handle_rx_cp(void *arg) +{ + struct bnxt_cp_ring *cpr = arg; + + /* Disable further interrupts for this queue */ + BNXT_CP_DISABLE_DB(&cpr->ring); + return FILTER_SCHEDULE_THREAD; +} + +static int +bnxt_handle_def_cp(void *arg) +{ + struct bnxt_softc *softc = arg; + + BNXT_CP_DISABLE_DB(&softc->def_cp_ring.ring); + GROUPTASK_ENQUEUE(&softc->def_cp_task); + return FILTER_HANDLED; +} + +static void +bnxt_clear_ids(struct bnxt_softc *softc) +{ + int i; + + softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; + softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; + for (i = 0; i < softc->ntxqsets; i++) { + softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; + softc->tx_cp_rings[i].ring.phys_id = + (uint16_t)HWRM_NA_SIGNATURE; + softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; + } + for (i = 0; i < softc->nrxqsets; i++) { + softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; + softc->rx_cp_rings[i].ring.phys_id = + (uint16_t)HWRM_NA_SIGNATURE; + softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; + softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; + } + softc->vnic_info.filter_id = -1; + softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; + softc->vnic_info.rss_id = (uint16_t)HWRM_NA_SIGNATURE; + memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff, + softc->vnic_info.rss_grp_tbl.idi_size); +} + +static void +bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr) +{ + struct cmpl_base *cmp = (void *)cpr->ring.vaddr; + int i; + + for (i = 0; i < cpr->ring.ring_size; i++) + cmp[i].info3_v = !cpr->v_bit; +} + +static void +bnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl) +{ + struct hwrm_async_event_cmpl *ae = (void *)cmpl; + uint16_t async_id = le16toh(ae->event_id); + struct ifmediareq ifmr; + + switch (async_id) { + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: + bnxt_media_status(softc->ctx, &ifmr); + break; + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE: + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR: + device_printf(softc->dev, + "Unhandled async completion type %u\n", async_id); + break; + default: + device_printf(softc->dev, + "Unknown async completion type %u\n", async_id); + break; + } +} + +static void +bnxt_def_cp_task(void *context) +{ + if_ctx_t ctx = context; + struct bnxt_softc *softc = iflib_get_softc(ctx); + struct bnxt_cp_ring *cpr = &softc->def_cp_ring; + + /* Handle completions on the default completion ring */ + struct cmpl_base *cmpl; + uint32_t cons = cpr->cons; + bool v_bit = cpr->v_bit; + bool last_v_bit; + uint32_t last_cons; + uint16_t type; + + for (;;) { + last_cons = cons; + last_v_bit = v_bit; + NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); + cmpl = &((struct cmpl_base *)cpr->ring.vaddr)[cons]; + + if (!CMP_VALID(cmpl, v_bit)) + break; + + type = le16toh(cmpl->type) & CMPL_BASE_TYPE_MASK; + switch (type) { + case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: + bnxt_handle_async_event(softc, cmpl); + break; + case CMPL_BASE_TYPE_TX_L2: + case CMPL_BASE_TYPE_RX_L2: + case CMPL_BASE_TYPE_RX_AGG: + case CMPL_BASE_TYPE_RX_TPA_START: + case CMPL_BASE_TYPE_RX_TPA_END: + case CMPL_BASE_TYPE_STAT_EJECT: + case CMPL_BASE_TYPE_HWRM_DONE: + case CMPL_BASE_TYPE_HWRM_FWD_REQ: + case CMPL_BASE_TYPE_HWRM_FWD_RESP: + case CMPL_BASE_TYPE_CQ_NOTIFICATION: + case CMPL_BASE_TYPE_SRQ_EVENT: + case CMPL_BASE_TYPE_DBQ_EVENT: + case CMPL_BASE_TYPE_QP_EVENT: + case CMPL_BASE_TYPE_FUNC_EVENT: + device_printf(softc->dev, + "Unhandled completion type %u\n", type); + break; + default: + device_printf(softc->dev, + "Unknown completion type %u\n", type); + break; + } + } + + cpr->cons = last_cons; + cpr->v_bit = last_v_bit; + BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons); +} + +static uint8_t +get_phy_type(struct bnxt_softc *softc) +{ + struct bnxt_link_info *link_info = &softc->link_info; + uint8_t phy_type = link_info->phy_type; + uint16_t supported; + + if (phy_type != HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN) + return phy_type; + + /* Deduce the phy type from the media type and supported speeds */ + supported = link_info->support_speeds; + + if (link_info->media_type == + HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP) + return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET; + if (link_info->media_type == + HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_DAC) { + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) + return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX; + if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB) + return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR; + return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR; + } + if (link_info->media_type == + HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_FIBRE) + return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR; + + return phy_type; +} + +bool +bnxt_check_hwrm_version(struct bnxt_softc *softc) +{ + char buf[16]; + + sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major, + softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update); + if (softc->ver_info->hwrm_min_major > softc->ver_info->hwrm_if_major) { + device_printf(softc->dev, + "WARNING: HWRM version %s is too old (older than %s)\n", + softc->ver_info->hwrm_if_ver, buf); + return false; + } + else if(softc->ver_info->hwrm_min_major == + softc->ver_info->hwrm_if_major) { + if (softc->ver_info->hwrm_min_minor > + softc->ver_info->hwrm_if_minor) { + device_printf(softc->dev, + "WARNING: HWRM version %s is too old (older than %s)\n", + softc->ver_info->hwrm_if_ver, buf); + return false; + } + else if (softc->ver_info->hwrm_min_minor == + softc->ver_info->hwrm_if_minor) { + if (softc->ver_info->hwrm_min_update > + softc->ver_info->hwrm_if_update) { + device_printf(softc->dev, + "WARNING: HWRM version %s is too old (older than %s)\n", + softc->ver_info->hwrm_if_ver, buf); + return false; + } + } + } + return true; +} + +static uint64_t +bnxt_get_baudrate(struct bnxt_link_info *link) +{ + switch (link->link_speed) { + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB: + return IF_Mbps(100); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB: + return IF_Gbps(1); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB: + return IF_Gbps(2); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB: + return IF_Mbps(2500); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB: + return IF_Gbps(10); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB: + return IF_Gbps(20); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB: + return IF_Gbps(25); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB: + return IF_Gbps(40); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: + return IF_Gbps(50); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: + return IF_Gbps(100); + case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB: + return IF_Mbps(10); + } + return IF_Gbps(100); +} diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c index d801f17cd05..e0c0bf75d4e 100644 --- a/sys/dev/cpuctl/cpuctl.c +++ b/sys/dev/cpuctl/cpuctl.c @@ -63,7 +63,7 @@ static d_ioctl_t cpuctl_ioctl; # define DPRINTF(...) #endif -#define UCODE_SIZE_MAX (32 * 1024) +#define UCODE_SIZE_MAX (4 * 1024 * 1024) static int cpuctl_do_msr(int cpu, cpuctl_msr_args_t *data, u_long cmd, struct thread *td); diff --git a/sys/dev/dme/if_dme.c b/sys/dev/dme/if_dme.c new file mode 100644 index 00000000000..b18b97753d1 --- /dev/null +++ b/sys/dev/dme/if_dme.c @@ -0,0 +1,1061 @@ +/* + * Copyright (C) 2015 Alexander Kabaev + * Copyright (C) 2010 Andrew Turner + * 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. + */ + +/* A driver for the Davicom DM9000 MAC. */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "miibus_if.h" + +struct dme_softc { + struct ifnet *dme_ifp; + device_t dme_dev; + device_t dme_miibus; + bus_space_handle_t dme_handle; + bus_space_tag_t dme_tag; + int dme_rev; + int dme_bits; + struct resource *dme_res; + struct resource *dme_irq; + void *dme_intrhand; + struct mtx dme_mtx; + struct callout dme_tick_ch; + struct gpiobus_pin *gpio_rset; + uint32_t dme_ticks; + uint8_t dme_macaddr[ETHER_ADDR_LEN]; + regulator_t dme_vcc_regulator; + uint8_t dme_txbusy: 1; + uint8_t dme_txready: 1; + uint16_t dme_txlen; +}; + +#define DME_CHIP_DM9000 0x00 +#define DME_CHIP_DM9000A 0x19 +#define DME_CHIP_DM9000B 0x1a + +#define DME_INT_PHY 1 + +static int dme_probe(device_t); +static int dme_attach(device_t); +static int dme_detach(device_t); + +static void dme_intr(void *arg); +static void dme_init_locked(struct dme_softc *); + +static void dme_prepare(struct dme_softc *); +static void dme_transmit(struct dme_softc *); + +static int dme_miibus_writereg(device_t dev, int phy, int reg, int data); +static int dme_miibus_readreg(device_t dev, int phy, int reg); + +/* The bit on the address bus attached to the CMD pin */ +#define BASE_ADDR 0x000 +#define CMD_ADDR BASE_ADDR +#define DATA_BIT 1 +#define DATA_ADDR 0x002 + +#undef DME_TRACE + +#ifdef DME_TRACE +#define DTR3 TR3 +#define DTR4 TR4 +#else +#define NOTR(args...) (void)0 +#define DTR3 NOTR +#define DTR4 NOTR +#endif + +static uint8_t +dme_read_reg(struct dme_softc *sc, uint8_t reg) +{ + + /* Send the register to read from */ + bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, reg); + bus_space_barrier(sc->dme_tag, sc->dme_handle, CMD_ADDR, 1, + BUS_SPACE_BARRIER_WRITE); + + /* Get the value of the register */ + return bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR); +} + +static void +dme_write_reg(struct dme_softc *sc, uint8_t reg, uint8_t value) +{ + + /* Send the register to write to */ + bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, reg); + bus_space_barrier(sc->dme_tag, sc->dme_handle, CMD_ADDR, 1, + BUS_SPACE_BARRIER_WRITE); + + /* Write the value to the register */ + bus_space_write_1(sc->dme_tag, sc->dme_handle, DATA_ADDR, value); + bus_space_barrier(sc->dme_tag, sc->dme_handle, DATA_ADDR, 1, + BUS_SPACE_BARRIER_WRITE); +} + +static void +dme_reset(struct dme_softc *sc) +{ + u_int ncr; + + /* Send a soft reset #1 */ + dme_write_reg(sc, DME_NCR, NCR_RST | NCR_LBK_MAC); + DELAY(100); /* Wait for the MAC to reset */ + ncr = dme_read_reg(sc, DME_NCR); + if (ncr & NCR_RST) + device_printf(sc->dme_dev, "device did not complete first reset\n"); + + /* Send a soft reset #2 per Application Notes v1.22 */ + dme_write_reg(sc, DME_NCR, 0); + dme_write_reg(sc, DME_NCR, NCR_RST | NCR_LBK_MAC); + DELAY(100); /* Wait for the MAC to reset */ + ncr = dme_read_reg(sc, DME_NCR); + if (ncr & NCR_RST) + device_printf(sc->dme_dev, "device did not complete second reset\n"); + + /* Reset trasmit state */ + sc->dme_txbusy = 0; + sc->dme_txready = 0; + + DTR3("dme_reset, flags %#x busy %d ready %d", + sc->dme_ifp ? sc->dme_ifp->if_drv_flags : 0, + sc->dme_txbusy, sc->dme_txready); +} + +/* + * Parse string MAC address into usable form + */ +static int +dme_parse_macaddr(const char *str, uint8_t *mac) +{ + int count, i; + unsigned int amac[ETHER_ADDR_LEN]; /* Aligned version */ + + count = sscanf(str, "%x%*c%x%*c%x%*c%x%*c%x%*c%x", + &amac[0], &amac[1], &amac[2], + &amac[3], &amac[4], &amac[5]); + if (count < ETHER_ADDR_LEN) { + memset(mac, 0, ETHER_ADDR_LEN); + return (1); + } + + /* Copy aligned to result */ + for (i = 0; i < ETHER_ADDR_LEN; i ++) + mac[i] = (amac[i] & 0xff); + + return (0); +} + +/* + * Try to determine our own MAC address + */ +static void +dme_get_macaddr(struct dme_softc *sc) +{ + char devid_str[32]; + char *var; + int i; + + /* Cannot use resource_string_value with static hints mode */ + snprintf(devid_str, 32, "hint.%s.%d.macaddr", + device_get_name(sc->dme_dev), + device_get_unit(sc->dme_dev)); + + /* Try resource hints */ + if ((var = kern_getenv(devid_str)) != NULL) { + if (!dme_parse_macaddr(var, sc->dme_macaddr)) { + device_printf(sc->dme_dev, "MAC address: %s (hints)\n", var); + return; + } + } + + /* + * Try to read MAC address from the device, in case U-Boot has + * pre-programmed one for us. + */ + for (i = 0; i < ETHER_ADDR_LEN; i++) + sc->dme_macaddr[i] = dme_read_reg(sc, DME_PAR(i)); + + device_printf(sc->dme_dev, "MAC address %6D (existing)\n", + sc->dme_macaddr, ":"); +} + +static void +dme_config(struct dme_softc *sc) +{ + int i; + + /* Mask all interrupts and reset receive pointer */ + dme_write_reg(sc, DME_IMR, IMR_PAR); + + /* Disable GPIO0 to enable the internal PHY */ + dme_write_reg(sc, DME_GPCR, 1); + dme_write_reg(sc, DME_GPR, 0); + +#if 0 + /* + * Supposedly requires special initialization for DSP PHYs + * used by DM9000B. Maybe belongs in dedicated PHY driver? + */ + if (sc->dme_rev == DME_CHIP_DM9000B) { + dme_miibus_writereg(sc->dme_dev, DME_INT_PHY, MII_BMCR, + BMCR_RESET); + dme_miibus_writereg(sc->dme_dev, DME_INT_PHY, MII_DME_DSPCR, + DSPCR_INIT); + /* Wait 100ms for it to complete. */ + for (i = 0; i < 100; i++) { + int reg; + + reg = dme_miibus_readreg(sc->dme_dev, DME_INT_PHY, MII_BMCR); + if ((reg & BMCR_RESET) == 0) + break; + DELAY(1000); + } + } +#endif + + /* Select the internal PHY and normal loopback */ + dme_write_reg(sc, DME_NCR, NCR_LBK_NORMAL); + /* Clear any TX requests */ + dme_write_reg(sc, DME_TCR, 0); + /* Setup backpressure thresholds to 4k and 600us */ + dme_write_reg(sc, DME_BPTR, BPTR_BPHW(3) | BPTR_JPT(0x0f)); + /* Setup flow control */ + dme_write_reg(sc, DME_FCTR, FCTR_HWOT(0x3) | FCTR_LWOT(0x08)); + /* Enable flow control */ + dme_write_reg(sc, DME_FCR, 0xff); + /* Clear special modes */ + dme_write_reg(sc, DME_SMCR, 0); + /* Clear TX status */ + dme_write_reg(sc, DME_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); + /* Clear interrrupts */ + dme_write_reg(sc, DME_ISR, 0xff); + /* Set multicast address filter */ + for (i = 0; i < 8; i++) + dme_write_reg(sc, DME_MAR(i), 0xff); + /* Set the MAC address */ + for (i = 0; i < ETHER_ADDR_LEN; i++) + dme_write_reg(sc, DME_PAR(i), sc->dme_macaddr[i]); + /* Enable the RX buffer */ + dme_write_reg(sc, DME_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); + + /* Enable interrupts we care about */ + dme_write_reg(sc, DME_IMR, IMR_PAR | IMR_PRI | IMR_PTI); +} + +void +dme_prepare(struct dme_softc *sc) +{ + struct ifnet *ifp; + struct mbuf *m, *mp; + uint16_t total_len, len; + + DME_ASSERT_LOCKED(sc); + + KASSERT(sc->dme_txready == 0, + ("dme_prepare: called with txready set\n")); + + ifp = sc->dme_ifp; + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) { + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + DTR3("dme_prepare none, flags %#x busy %d ready %d", + sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready); + return; /* Nothing to transmit */ + } + + /* Element has now been removed from the queue, so we better send it */ + BPF_MTAP(ifp, m); + + /* Setup the controller to accept the writes */ + bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, DME_MWCMD); + + /* + * TODO: Fix the case where an mbuf is + * not a multiple of the write size. + */ + total_len = 0; + for (mp = m; mp != NULL; mp = mp->m_next) { + len = mp->m_len; + + /* Ignore empty parts */ + if (len == 0) + continue; + + total_len += len; + +#if 0 + bus_space_write_multi_2(sc->dme_tag, sc->dme_handle, + DATA_ADDR, mtod(mp, uint16_t *), (len + 1) / 2); +#else + bus_space_write_multi_1(sc->dme_tag, sc->dme_handle, + DATA_ADDR, mtod(mp, uint8_t *), len); +#endif + } + + if (total_len % (sc->dme_bits >> 3) != 0) + panic("dme_prepare: length is not compatible with IO_MODE"); + + sc->dme_txlen = total_len; + sc->dme_txready = 1; + DTR3("dme_prepare done, flags %#x busy %d ready %d", + sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready); + + m_freem(m); +} + +void +dme_transmit(struct dme_softc *sc) +{ + + DME_ASSERT_LOCKED(sc); + KASSERT(sc->dme_txready, ("transmit without txready")); + + dme_write_reg(sc, DME_TXPLL, sc->dme_txlen & 0xff); + dme_write_reg(sc, DME_TXPLH, (sc->dme_txlen >> 8) & 0xff ); + + /* Request to send the packet */ + dme_read_reg(sc, DME_ISR); + + dme_write_reg(sc, DME_TCR, TCR_TXREQ); + + sc->dme_txready = 0; + sc->dme_txbusy = 1; + DTR3("dme_transmit done, flags %#x busy %d ready %d", + sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready); +} + + +static void +dme_start_locked(struct ifnet *ifp) +{ + struct dme_softc *sc; + + sc = ifp->if_softc; + DME_ASSERT_LOCKED(sc); + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return; + + DTR3("dme_start, flags %#x busy %d ready %d", + sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready); + KASSERT(sc->dme_txbusy == 0 || sc->dme_txready == 0, + ("dme: send without empty queue\n")); + + dme_prepare(sc); + + if (sc->dme_txbusy == 0) { + /* We are ready to transmit right away */ + dme_transmit(sc); + dme_prepare(sc); /* Prepare next one */ + } + /* + * We need to wait until the current packet has + * been transmitted. + */ + if (sc->dme_txready != 0) + ifp->if_drv_flags |= IFF_DRV_OACTIVE; +} + +static void +dme_start(struct ifnet *ifp) +{ + struct dme_softc *sc; + + sc = ifp->if_softc; + DME_LOCK(sc); + dme_start_locked(ifp); + DME_UNLOCK(sc); +} + +static void +dme_stop(struct dme_softc *sc) +{ + struct ifnet *ifp; + + DME_ASSERT_LOCKED(sc); + /* Disable receiver */ + dme_write_reg(sc, DME_RCR, 0x00); + /* Mask interrupts */ + dme_write_reg(sc, DME_IMR, 0x00); + /* Stop poll */ + callout_stop(&sc->dme_tick_ch); + + ifp = sc->dme_ifp; + ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + + DTR3("dme_stop, flags %#x busy %d ready %d", + sc->dme_ifp->if_drv_flags, sc->dme_txbusy, sc->dme_txready); + sc->dme_txbusy = 0; + sc->dme_txready = 0; +} + +static int +dme_rxeof(struct dme_softc *sc) +{ + struct ifnet *ifp; + struct mbuf *m; + int len, i; + + DME_ASSERT_LOCKED(sc); + + ifp = sc->dme_ifp; + + /* Read the first byte to check it correct */ + (void)dme_read_reg(sc, DME_MRCMDX); + i = bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR); + switch(bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR)) { + case 1: + /* Correct value */ + break; + case 0: + return 1; + default: + /* Error */ + return -1; + } + + i = dme_read_reg(sc, DME_MRRL); + i |= dme_read_reg(sc, DME_MRRH) << 8; + + len = dme_read_reg(sc, DME_ROCR); + + bus_space_write_1(sc->dme_tag, sc->dme_handle, CMD_ADDR, DME_MRCMD); + len = 0; + switch(sc->dme_bits) { + case 8: + i = bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR); + i <<= 8; + i |= bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR); + + len = bus_space_read_1(sc->dme_tag, sc->dme_handle, DATA_ADDR); + len |= bus_space_read_1(sc->dme_tag, sc->dme_handle, + DATA_ADDR) << 8; + break; + case 16: + bus_space_read_2(sc->dme_tag, sc->dme_handle, DATA_ADDR); + len = bus_space_read_2(sc->dme_tag, sc->dme_handle, DATA_ADDR); + break; + case 32: + { + uint32_t reg; + + reg = bus_space_read_4(sc->dme_tag, sc->dme_handle, DATA_ADDR); + len = reg & 0xFFFF; + break; + } + } + + MGETHDR(m, M_NOWAIT, MT_DATA); + if (m == NULL) + return -1; + + if (len > MHLEN - ETHER_ALIGN) { + MCLGET(m, M_NOWAIT); + if (!(m->m_flags & M_EXT)) { + m_freem(m); + return -1; + } + } + + m->m_pkthdr.rcvif = ifp; + m->m_len = m->m_pkthdr.len = len; + m_adj(m, ETHER_ALIGN); + + /* Read the data */ +#if 0 + bus_space_read_multi_2(sc->dme_tag, sc->dme_handle, DATA_ADDR, + mtod(m, uint16_t *), (len + 1) / 2); +#else + bus_space_read_multi_1(sc->dme_tag, sc->dme_handle, DATA_ADDR, + mtod(m, uint8_t *), len); +#endif + if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + DME_UNLOCK(sc); + (*ifp->if_input)(ifp, m); + DME_LOCK(sc); + + return 0; +} + +static void +dme_tick(void *arg) +{ + struct dme_softc *sc; + struct mii_data *mii; + + sc = (struct dme_softc *)arg; + + /* Probably too frequent? */ + mii = device_get_softc(sc->dme_miibus); + mii_tick(mii); + + callout_reset(&sc->dme_tick_ch, hz, dme_tick, sc); +} + +static void +dme_intr(void *arg) +{ + struct dme_softc *sc; + uint32_t intr_status; + + sc = (struct dme_softc *)arg; + + DME_LOCK(sc); + + intr_status = dme_read_reg(sc, DME_ISR); + dme_write_reg(sc, DME_ISR, intr_status); + + DTR4("dme_intr flags %#x busy %d ready %d intr %#x", + sc->dme_ifp->if_drv_flags, sc->dme_txbusy, + sc->dme_txready, intr_status); + + if (intr_status & ISR_PT) { + uint8_t nsr, tx_status; + + sc->dme_txbusy = 0; + + nsr = dme_read_reg(sc, DME_NSR); + + if (nsr & NSR_TX1END) + tx_status = dme_read_reg(sc, DME_TSR1); + else if (nsr & NSR_TX2END) + tx_status = dme_read_reg(sc, DME_TSR2); + else + tx_status = 1; + + DTR4("dme_intr flags %#x busy %d ready %d nsr %#x", + sc->dme_ifp->if_drv_flags, sc->dme_txbusy, + sc->dme_txready, nsr); + + /* Prepare packet to send if none is currently pending */ + if (sc->dme_txready == 0) + dme_prepare(sc); + /* Send the packet out of one is waiting for transmit */ + if (sc->dme_txready != 0) { + /* Initiate transmission of the prepared packet */ + dme_transmit(sc); + /* Prepare next packet to send */ + dme_prepare(sc); + /* + * We need to wait until the current packet has + * been transmitted. + */ + if (sc->dme_txready != 0) + sc->dme_ifp->if_drv_flags |= IFF_DRV_OACTIVE; + } + } + + if (intr_status & ISR_PR) { + /* Read the packets off the device */ + while (dme_rxeof(sc) == 0) + continue; + } + DME_UNLOCK(sc); +} + +static void +dme_setmode(struct dme_softc *sc) +{ +} + +static int +dme_ioctl(struct ifnet *ifp, u_long command, caddr_t data) +{ + struct dme_softc *sc; + struct mii_data *mii; + struct ifreq *ifr; + int error = 0; + + sc = ifp->if_softc; + ifr = (struct ifreq *)data; + + switch (command) { + case SIOCSIFFLAGS: + /* + * Switch interface state between "running" and + * "stopped", reflecting the UP flag. + */ + DME_LOCK(sc); + if (ifp->if_flags & IFF_UP) { + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + dme_init_locked(sc); + } + } else { + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + dme_stop(sc); + } + } + dme_setmode(sc); + DME_UNLOCK(sc); + break; + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + mii = device_get_softc(sc->dme_miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); + break; + default: + error = ether_ioctl(ifp, command, data); + break; + } + return (error); +} + +static void dme_init_locked(struct dme_softc *sc) +{ + struct ifnet *ifp = sc->dme_ifp; + + DME_ASSERT_LOCKED(sc); + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + return; + + dme_reset(sc); + dme_config(sc); + + ifp->if_drv_flags |= IFF_DRV_RUNNING; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + + callout_reset(&sc->dme_tick_ch, hz, dme_tick, sc); +} + +static void +dme_init(void *xcs) +{ + struct dme_softc *sc = xcs; + + DME_LOCK(sc); + dme_init_locked(sc); + DME_UNLOCK(sc); +} + +static int +dme_ifmedia_upd(struct ifnet *ifp) +{ + struct dme_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = device_get_softc(sc->dme_miibus); + + DME_LOCK(sc); + mii_mediachg(mii); + DME_UNLOCK(sc); + + return (0); +} + +static void +dme_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct dme_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = device_get_softc(sc->dme_miibus); + + DME_LOCK(sc); + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; + DME_UNLOCK(sc); +} + +static struct ofw_compat_data compat_data[] = { + { "davicom,dm9000", true }, + { NULL, false } +}; + +static int +dme_probe(device_t dev) +{ + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + device_set_desc(dev, "Davicom DM9000"); + return (0); +} + +static int +dme_attach(device_t dev) +{ + struct dme_softc *sc; + struct ifnet *ifp; + int error, rid; + uint32_t data; + + sc = device_get_softc(dev); + sc->dme_dev = dev; + + error = 0; + + mtx_init(&sc->dme_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, + MTX_DEF); + callout_init_mtx(&sc->dme_tick_ch, &sc->dme_mtx, 0); + + rid = 0; + sc->dme_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->dme_res == NULL) { + device_printf(dev, "unable to map memory\n"); + error = ENXIO; + goto fail; + } + + rid = 0; + sc->dme_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->dme_irq == NULL) { + device_printf(dev, "unable to map memory\n"); + error = ENXIO; + goto fail; + } + /* + * Power the chip up, if necessary + */ + error = regulator_get_by_ofw_property(dev, 0, "vcc-supply", &sc->dme_vcc_regulator); + if (error == 0) { + error = regulator_enable(sc->dme_vcc_regulator); + if (error != 0) { + device_printf(dev, "unable to enable power supply\n"); + error = ENXIO; + goto fail; + } + } + + /* + * Delay a little. This seems required on rev-1 boards (green.) + */ + DELAY(100000); + + /* Bring controller out of reset */ + error = ofw_gpiobus_parse_gpios(dev, "reset-gpios", &sc->gpio_rset); + if (error > 1) { + device_printf(dev, "too many reset gpios\n"); + sc->gpio_rset = NULL; + error = ENXIO; + goto fail; + } + + if (sc->gpio_rset != NULL) { + error = GPIO_PIN_SET(sc->gpio_rset->dev, sc->gpio_rset->pin, 0); + if (error != 0) { + device_printf(dev, "Cannot configure GPIO pin %d on %s\n", + sc->gpio_rset->pin, device_get_nameunit(sc->gpio_rset->dev)); + goto fail; + } + + error = GPIO_PIN_SETFLAGS(sc->gpio_rset->dev, sc->gpio_rset->pin, + GPIO_PIN_OUTPUT); + if (error != 0) { + device_printf(dev, "Cannot configure GPIO pin %d on %s\n", + sc->gpio_rset->pin, device_get_nameunit(sc->gpio_rset->dev)); + goto fail; + } + + DELAY(2000); + + error = GPIO_PIN_SET(sc->gpio_rset->dev, sc->gpio_rset->pin, 1); + if (error != 0) { + device_printf(dev, "Cannot configure GPIO pin %d on %s\n", + sc->gpio_rset->pin, device_get_nameunit(sc->gpio_rset->dev)); + goto fail; + } + + DELAY(4000); + } else + device_printf(dev, "Unable to find reset GPIO\n"); + + sc->dme_tag = rman_get_bustag(sc->dme_res); + sc->dme_handle = rman_get_bushandle(sc->dme_res); + + /* Reset the chip as soon as possible */ + dme_reset(sc); + + /* Figure IO mode */ + switch((dme_read_reg(sc, DME_ISR) >> 6) & 0x03) { + case 0: + /* 16 bit */ + sc->dme_bits = 16; + break; + case 1: + /* 32 bit */ + sc->dme_bits = 32; + break; + case 2: + /* 8 bit */ + sc->dme_bits = 8; + break; + default: + /* reserved */ + device_printf(dev, "Unable to determine device mode\n"); + error = ENXIO; + goto fail; + } + + DELAY(100000); + + /* Read vendor and device id's */ + data = dme_read_reg(sc, DME_VIDH) << 8; + data |= dme_read_reg(sc, DME_VIDL); + device_printf(dev, "Vendor ID: 0x%04x\n", data); + + /* Read vendor and device id's */ + data = dme_read_reg(sc, DME_PIDH) << 8; + data |= dme_read_reg(sc, DME_PIDL); + device_printf(dev, "Product ID: 0x%04x\n", data); + + /* Chip revision */ + data = dme_read_reg(sc, DME_CHIPR); + device_printf(dev, "Revision: 0x%04x\n", data); + if (data != DME_CHIP_DM9000A && data != DME_CHIP_DM9000B) + data = DME_CHIP_DM9000; + sc->dme_rev = data; + + device_printf(dev, "using %d-bit IO mode\n", sc->dme_bits); + KASSERT(sc->dme_bits == 8, ("wrong io mode")); + + /* Try to figure our mac address */ + dme_get_macaddr(sc); + + /* Configure chip after reset */ + dme_config(sc); + + ifp = sc->dme_ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) { + device_printf(dev, "unable to allocate ifp\n"); + error = ENOSPC; + goto fail; + } + ifp->if_softc = sc; + + /* Setup MII */ + error = mii_attach(dev, &sc->dme_miibus, ifp, dme_ifmedia_upd, + dme_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); + /* This should never happen as the DM9000 contains it's own PHY */ + if (error != 0) { + device_printf(dev, "PHY probe failed\n"); + goto fail; + } + + if_initname(ifp, device_get_name(dev), device_get_unit(dev)); + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_start = dme_start; + ifp->if_ioctl = dme_ioctl; + ifp->if_init = dme_init; + IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + + ether_ifattach(ifp, sc->dme_macaddr); + + error = bus_setup_intr(dev, sc->dme_irq, INTR_TYPE_NET | INTR_MPSAFE, + NULL, dme_intr, sc, &sc->dme_intrhand); + if (error) { + device_printf(dev, "couldn't set up irq\n"); + ether_ifdetach(ifp); + goto fail; + } +fail: + if (error != 0) + dme_detach(dev); + return (error); +} + +static int +dme_detach(device_t dev) +{ + struct dme_softc *sc; + struct ifnet *ifp; + + sc = device_get_softc(dev); + KASSERT(mtx_initialized(&sc->dme_mtx), ("dme mutex not initialized")); + + ifp = sc->dme_ifp; + + if (device_is_attached(dev)) { + DME_LOCK(sc); + dme_stop(sc); + DME_UNLOCK(sc); + ether_ifdetach(ifp); + callout_drain(&sc->dme_tick_ch); + } + + if (sc->dme_miibus) + device_delete_child(dev, sc->dme_miibus); + bus_generic_detach(dev); + + if (sc->dme_vcc_regulator != 0) + regulator_release(sc->dme_vcc_regulator); + if (sc->dme_intrhand) + bus_teardown_intr(dev, sc->dme_irq, sc->dme_intrhand); + if (sc->dme_irq) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dme_irq); + if (sc->dme_res) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->dme_res); + + if (ifp != NULL) + if_free(ifp); + + mtx_destroy(&sc->dme_mtx); + + return (0); +} + +/* + * The MII bus interface + */ +static int +dme_miibus_readreg(device_t dev, int phy, int reg) +{ + struct dme_softc *sc; + int i, rval; + + /* We have up to 4 PHY's */ + if (phy >= 4) + return (0); + + sc = device_get_softc(dev); + + /* Send the register to read to the phy and start the read */ + dme_write_reg(sc, DME_EPAR, (phy << 6) | reg); + dme_write_reg(sc, DME_EPCR, EPCR_EPOS | EPCR_ERPRR); + + /* Wait for the data to be read */ + for (i = 0; i < DME_TIMEOUT; i++) { + if ((dme_read_reg(sc, DME_EPCR) & EPCR_ERRE) == 0) + break; + DELAY(1); + } + + /* Clear the comand */ + dme_write_reg(sc, DME_EPCR, 0); + + if (i == DME_TIMEOUT) + return (0); + + rval = (dme_read_reg(sc, DME_EPDRH) << 8) | dme_read_reg(sc, DME_EPDRL); + return (rval); +} + +static int +dme_miibus_writereg(device_t dev, int phy, int reg, int data) +{ + struct dme_softc *sc; + int i; + + /* We have up to 4 PHY's */ + if (phy > 3) + return (0); + + sc = device_get_softc(dev); + + /* Send the register and data to write to the phy */ + dme_write_reg(sc, DME_EPAR, (phy << 6) | reg); + dme_write_reg(sc, DME_EPDRL, data & 0xFF); + dme_write_reg(sc, DME_EPDRH, (data >> 8) & 0xFF); + /* Start the write */ + dme_write_reg(sc, DME_EPCR, EPCR_EPOS | EPCR_ERPRW); + + /* Wait for the data to be written */ + for (i = 0; i < DME_TIMEOUT; i++) { + if ((dme_read_reg(sc, DME_EPCR) & EPCR_ERRE) == 0) + break; + DELAY(1); + } + + /* Clear the comand */ + dme_write_reg(sc, DME_EPCR, 0); + + return (0); +} + +static device_method_t dme_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, dme_probe), + DEVMETHOD(device_attach, dme_attach), + DEVMETHOD(device_detach, dme_detach), + + /* bus interface, for miibus */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, dme_miibus_readreg), + DEVMETHOD(miibus_writereg, dme_miibus_writereg), + + { 0, 0 } +}; + +static driver_t dme_driver = { + "dme", + dme_methods, + sizeof(struct dme_softc) +}; + +static devclass_t dme_devclass; + +MODULE_DEPEND(dme, ether, 1, 1, 1); +MODULE_DEPEND(dme, miibus, 1, 1, 1); +DRIVER_MODULE(dme, simplebus, dme_driver, dme_devclass, 0, 0); +DRIVER_MODULE(miibus, dme, miibus_driver, miibus_devclass, 0, 0); + diff --git a/sys/dev/dme/if_dmereg.h b/sys/dev/dme/if_dmereg.h new file mode 100644 index 00000000000..9a5456f7d67 --- /dev/null +++ b/sys/dev/dme/if_dmereg.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2010 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __IF_DMEREG_H__ +#define __IF_DMEREG_H__ + +/* + * DM9000 register definitions + */ +#define DME_NCR 0x00 +#define NCR_EXT_PHY (1<<7) +#define NCR_WAKEEN (1<<6) +#define NCR_FCOL (1<<4) +#define NCR_FDX (1<<3) +#define NCR_LBK_NORMAL (0<<1) +#define NCR_LBK_MAC (1<<1) +#define NCR_LBK_PHY (2<<1) +#define NCR_RST (1<<0) +#define DME_NSR 0x01 +#define NSR_SPEED (1<<7) +#define NSR_LINKST (1<<6) +#define NSR_WAKEST (1<<5) +#define NSR_TX2END (1<<3) +#define NSR_TX1END (1<<2) +#define NSR_RXOV (1<<1) +#define DME_TCR 0x02 +#define TCR_TJDIS (1<<6) +#define TCR_EXCECM (1<<5) +#define TCR_PAD_DIS2 (1<<4) +#define TCR_PAD_CRC2 (1<<3) +#define TCR_PAD_DIS1 (1<<2) +#define TCR_PAD_CRC1 (1<<1) +#define TCR_TXREQ (1<<0) +#define DME_TSR1 0x03 +#define DME_TSR2 0x04 +#define DME_RCR 0x05 +#define RCR_WTDIS (1<<6) +#define RCR_DIS_LONG (1<<5) +#define RCR_DIS_CRC (1<<4) +#define RCR_ALL (1<<3) +#define RCR_RUNT (1<<2) +#define RCR_PRMSC (1<<1) +#define RCR_RXEN (1<<0) +#define DME_RSR 0x06 +#define DME_ROCR 0x07 +#define DME_BPTR 0x08 +#define BPTR_BPHW(v) (((v) & 0x0f) << 4) +#define BPTR_JPT(v) (((v) & 0x0f) << 0) +#define DME_FCTR 0x09 +#define FCTR_HWOT(v) (((v) & 0x0f) << 4) +#define FCTR_LWOT(v) (((v) & 0x0f) << 0) +#define DME_FCR 0x0A +#define DME_EPCR 0x0B +#define EPCR_REEP (1<<5) +#define EPCR_WEP (1<<4) +#define EPCR_EPOS (1<<3) +#define EPCR_ERPRR (1<<2) +#define EPCR_ERPRW (1<<1) +#define EPCR_ERRE (1<<0) +#define DME_EPAR 0x0C +#define DME_EPDRL 0x0D +#define DME_EPDRH 0x0E +#define DME_WCR 0x0F +#define DME_PAR_BASE 0x10 +#define DME_PAR(n) (DME_PAR_BASE + n) +#define DME_MAR_BASE 0x16 +#define DME_MAR(n) (DME_MAR_BASE + n) +#define DME_GPCR 0x1E +#define DME_GPR 0x1F +#define DME_TRPAL 0x22 +#define DME_TRPAH 0x23 +#define DME_RWPAL 0x24 +#define DME_RWPAH 0x25 +#define DME_VIDL 0x28 +#define DME_VIDH 0x29 +#define DME_PIDL 0x2A +#define DME_PIDH 0x2B +#define DME_CHIPR 0x2C +#define DME_SMCR 0x2F +#define DME_MRCMDX 0xF0 +#define DME_MRCMD 0xF2 +#define DME_MRRL 0xF4 +#define DME_MRRH 0xF5 +#define DME_MWCMDX 0xF6 +#define DME_MWCMD 0xF8 +#define DME_MWRL 0xFA +#define DME_MWRH 0xFB +#define DME_TXPLL 0xFC +#define DME_TXPLH 0xFD +#define DME_ISR 0xFE +#define ISR_LNKCHG (1<<5) +#define ISR_UDRUN (1<<4) +#define ISR_ROO (1<<3) +#define ISR_ROS (1<<2) +#define ISR_PT (1<<1) +#define ISR_PR (1<<0) + +#define DME_IMR 0xFF +#define IMR_PAR (1<<7) +#define IMR_LNKCHGI (1<<5) +#define IMR_UDRUNI (1<<4) +#define IMR_ROOI (1<<3) +#define IMR_ROI (1<<2) +#define IMR_PTI (1<<1) +#define IMR_PRI (1<<0) + +/* Extra PHY register from DM9000B */ +#define MII_DME_DSPCR 0x1B +#define DSPCR_INIT 0xE100 + +#endif /* __DMEREGS_H__ */ + diff --git a/sys/dev/dme/if_dmevar.h b/sys/dev/dme/if_dmevar.h new file mode 100644 index 00000000000..49fdcac4549 --- /dev/null +++ b/sys/dev/dme/if_dmevar.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 Andrew Turner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __IF_DMEVAR_H__ +#define __IF_DMEVAR_H__ + +#define DME_LOCK(cs) mtx_lock(&(sc)->dme_mtx) +#define DME_UNLOCK(cs) mtx_unlock(&(sc)->dme_mtx) +#define DME_ASSERT_LOCKED(sc) mtx_assert(&(sc)->dme_mtx, MA_OWNED); + +#define DME_TIMEOUT 1000 + +#endif /* __IF_DMEVAR_H__ */ + diff --git a/sys/dev/dpaa/bman_fdt.c b/sys/dev/dpaa/bman_fdt.c index c7950270e34..454af67ae6b 100644 --- a/sys/dev/dpaa/bman_fdt.c +++ b/sys/dev/dpaa/bman_fdt.c @@ -33,11 +33,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include -#include - #include #include #include @@ -107,7 +106,8 @@ static driver_t bm_portals_driver = { }; static devclass_t bm_portals_devclass; -DRIVER_MODULE(bman_portals, ofwbus, bm_portals_driver, bm_portals_devclass, 0, 0); +EARLY_DRIVER_MODULE(bman_portals, ofwbus, bm_portals_driver, + bm_portals_devclass, 0, 0, BUS_PASS_BUS); static void get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep) @@ -123,7 +123,7 @@ static int bman_portals_fdt_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "bman-portals")) + if (!ofw_bus_is_compatible(dev, "fsl,bman-portals")) return (ENXIO); device_set_desc(dev, BMAN_PORT_DEVSTR); @@ -131,6 +131,25 @@ bman_portals_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +static phandle_t +bman_portal_find_cpu(int cpu) +{ + phandle_t node; + pcell_t reg; + + node = OF_finddevice("/cpus"); + if (node == -1) + return (node); + + for (node = OF_child(node); node != 0; node = OF_peer(node)) { + if (OF_getprop(node, "reg", ®, sizeof(reg)) <= 0) + continue; + if (reg == cpu) + return (node); + } + return (-1); +} + static int bman_portals_fdt_attach(device_t dev) { @@ -154,13 +173,17 @@ bman_portals_fdt_attach(device_t dev) /* Find portals tied to CPUs */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { - if (!fdt_is_compatible(child, "fsl,bman-portal")) { + if (cpus >= mp_ncpus) + break; + if (!ofw_bus_node_is_compatible(child, "fsl,bman-portal")) { continue; } /* Checkout related cpu */ if (OF_getprop(child, "cpu-handle", (void *)&cpu, sizeof(cpu)) <= 0) { - continue; + cpu = bman_portal_find_cpu(cpus); + if (cpu <= 0) + continue; } /* Acquire cpu number */ cpu_node = OF_instance_to_package(cpu); @@ -171,9 +194,6 @@ bman_portals_fdt_attach(device_t dev) cpus++; - if (cpus > MAXCPU) - break; - if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) { device_printf(dev, "could not set up devinfo\n"); continue; diff --git a/sys/dev/dpaa/dpaa.c b/sys/dev/dpaa/dpaa.c deleted file mode 100644 index 95c04b4d596..00000000000 --- a/sys/dev/dpaa/dpaa.c +++ /dev/null @@ -1,184 +0,0 @@ -/*- - * Copyright (c) 2012 Semihalf. - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "opt_platform.h" - -static MALLOC_DEFINE(M_DPAA, "dpaa", "dpaa devices information"); - -static int dpaa_probe(device_t dev); -static int dpaa_attach(device_t dev); - -static const struct ofw_bus_devinfo *dpaa_get_devinfo(device_t bus, - device_t child); - -struct dpaa_softc { - -}; - -struct dpaa_devinfo { - struct ofw_bus_devinfo di_ofw; -}; - -static device_method_t dpaa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, dpaa_probe), - DEVMETHOD(device_attach, dpaa_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* OFW bus interface */ - DEVMETHOD(ofw_bus_get_devinfo, dpaa_get_devinfo), - DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), - DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), - DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), - DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), - DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), - - {0, 0} -}; - -static driver_t dpaa_driver = { - "dpaa", - dpaa_methods, - sizeof(struct dpaa_softc), -}; - -static devclass_t dpaa_devclass; -DRIVER_MODULE_ORDERED(dpaa, ofwbus, dpaa_driver, dpaa_devclass, 0, 0, - SI_ORDER_ANY); - -static int -dpaa_probe(device_t dev) -{ - - if (!ofw_bus_is_compatible(dev, "fsl,dpaa")) - return (ENXIO); - - device_set_desc(dev, "Freescale Data Path Acceleration Architecture"); - - return (BUS_PROBE_DEFAULT); -} - -static int -dpaa_attach(device_t dev) -{ - device_t dev_child; - phandle_t dt_node, dt_child, enet_node; - struct dpaa_devinfo *di; - pcell_t cell_index; - - cell_index = 0; - /* - * Walk dpaa and add direct subordinates as our children. - */ - dt_node = ofw_bus_get_node(dev); - dt_child = OF_child(dt_node); - - for (; dt_child != 0; dt_child = OF_peer(dt_child)) { - - /* Check and process 'status' property. */ - if (!(fdt_is_enabled(dt_child))) - continue; - - di = (struct dpaa_devinfo *)malloc(sizeof(*di), M_DPAA, - M_WAITOK | M_ZERO); - - if (ofw_bus_gen_setup_devinfo(&di->di_ofw, dt_child) != 0) { - free(di, M_DPAA); - device_printf(dev, "could not set up devinfo\n"); - continue; - } - - /* - * dTSEC number from SoC is equal to number get from - * dts file. - */ - if (OF_getprop(dt_child, "fsl,fman-mac", - (void *)&enet_node, sizeof(enet_node)) == -1) { - device_printf(dev, "Could not get fsl,fman-mac " - "from dts\n"); - continue; - } - - if ((enet_node = OF_instance_to_package(enet_node)) == -1) { - device_printf(dev, "Could not get enet node\n"); - continue; - } - - if (OF_getprop(enet_node, "cell-index", - (void *)&cell_index, sizeof(cell_index)) == -1) { - device_printf(dev, "Could not get cell-index from enet " - "node\n"); - continue; - } - - /* Add newbus device for this FDT node */ - dev_child = device_add_child(dev, "dtsec", (int)cell_index); - if (dev_child == NULL) { - device_printf(dev, "could not add child: %s\n", - di->di_ofw.obd_name); - ofw_bus_gen_destroy_devinfo(&di->di_ofw); - free(di, M_DPAA); - continue; - } - -#ifdef DEBUG - device_printf(dev, "added child: %s\n\n", di->di_ofw.obd_name); -#endif - - device_set_ivars(dev_child, di); - } - - return (bus_generic_attach(dev)); -} - -static const struct ofw_bus_devinfo * -dpaa_get_devinfo(device_t bus, device_t child) -{ - struct dpaa_devinfo *di; - - di = device_get_ivars(child); - return (&di->di_ofw); -} diff --git a/sys/dev/dpaa/fman.c b/sys/dev/dpaa/fman.c index ee1f0cd8bf2..4a90c10514a 100644 --- a/sys/dev/dpaa/fman.c +++ b/sys/dev/dpaa/fman.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -50,6 +49,8 @@ __FBSDID("$FreeBSD$"); #include "fman.h" +static MALLOC_DEFINE(M_FMAN, "fman", "fman devices information"); + /** * @group FMan private defines. * @{ @@ -259,6 +260,8 @@ fman_attach(device_t dev) { struct fman_softc *sc; struct fman_config cfg; + pcell_t qchan_range[2]; + phandle_t node; sc = device_get_softc(dev); sc->sc_base.dev = dev; @@ -270,8 +273,14 @@ fman_attach(device_t dev) return (ENXIO); } - XX_TrackInit(); - + node = ofw_bus_get_node(dev); + if (OF_getencprop(node, "fsl,qman-channel-range", qchan_range, + sizeof(qchan_range)) <= 0) { + device_printf(dev, "Missing QMan channel range property!\n"); + return (ENXIO); + } + sc->qman_chan_base = qchan_range[0]; + sc->qman_chan_count = qchan_range[1]; sc->mem_rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, RF_ACTIVE | RF_SHAREABLE); @@ -379,4 +388,21 @@ fman_shutdown(device_t dev) return (0); } +int +fman_qman_channel_id(device_t dev, int port) +{ + struct fman_softc *sc; + int qman_port_id[] = {0x31, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + int i; + + sc = device_get_softc(dev); + for (i = 0; i < sc->qman_chan_count; i++) { + if (qman_port_id[i] == port) + return (sc->qman_chan_base + i); + } + + return (0); +} + /** @} */ diff --git a/sys/dev/dpaa/fman.h b/sys/dev/dpaa/fman.h index 52bc61762c2..96cdd86b036 100644 --- a/sys/dev/dpaa/fman.h +++ b/sys/dev/dpaa/fman.h @@ -42,6 +42,8 @@ struct fman_softc { int mem_rid; int irq_rid; int err_irq_rid; + int qman_chan_base; + int qman_chan_count; t_Handle fm_handle; t_Handle muram_handle; @@ -59,6 +61,7 @@ int fman_resume(device_t dev); int fman_shutdown(device_t dev); int fman_read_ivar(device_t dev, device_t child, int index, uintptr_t *result); +int fman_qman_channel_id(device_t, int); /** @} */ uint32_t fman_get_clock(struct fman_softc *sc); diff --git a/sys/dev/dpaa/if_dtsec.c b/sys/dev/dpaa/if_dtsec.c index d5f771251e3..38f27fc847c 100644 --- a/sys/dev/dpaa/if_dtsec.c +++ b/sys/dev/dpaa/if_dtsec.c @@ -49,8 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include #include #include @@ -584,8 +582,6 @@ dtsec_attach(device_t dev) if (XX_MallocSmartInit() != E_OK) return (ENXIO); - XX_TrackInit(); - /* Init locks */ mtx_init(&sc->sc_lock, device_get_nameunit(dev), "DTSEC Global Lock", MTX_DEF); diff --git a/sys/dev/dpaa/if_dtsec_fdt.c b/sys/dev/dpaa/if_dtsec_fdt.c index 49666f155a1..b653fbd5f0c 100644 --- a/sys/dev/dpaa/if_dtsec_fdt.c +++ b/sys/dev/dpaa/if_dtsec_fdt.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -88,7 +87,7 @@ static driver_t dtsec_driver = { }; static devclass_t dtsec_devclass; -DRIVER_MODULE(dtsec, dpaa, dtsec_driver, dtsec_devclass, 0, 0); +DRIVER_MODULE(dtsec, fman, dtsec_driver, dtsec_devclass, 0, 0); DRIVER_MODULE(miibus, dtsec, miibus_driver, miibus_devclass, 0, 0); MODULE_DEPEND(dtsec, ether, 1, 1, 1); MODULE_DEPEND(dtsec, miibus, 1, 1, 1); @@ -97,7 +96,8 @@ static int dtsec_fdt_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "fsl,dpa-ethernet")) + if (!ofw_bus_is_compatible(dev, "fsl,fman-dtsec") && + !ofw_bus_is_compatible(dev, "fsl,fman-xgec")) return (ENXIO); device_set_desc(dev, "Freescale Data Path Triple Speed Ethernet " @@ -120,9 +120,7 @@ find_mdio(phandle_t phy_node, device_t mac, device_t *mdio_dev) if (phy_node <= 0) return (ENOENT); - if (fman_get_dev(&bus) < 0) - return (ENOENT); - + bus = device_get_parent(mac); *mdio_dev = ofw_bus_find_child_device_by_phandle(bus, phy_node); return (0); @@ -132,21 +130,13 @@ static int dtsec_fdt_attach(device_t dev) { struct dtsec_softc *sc; - phandle_t node, enet_node, phy_node; + phandle_t enet_node, phy_node; phandle_t fman_rxtx_node[2]; char phy_type[6]; + pcell_t fman_tx_cell; sc = device_get_softc(dev); - node = ofw_bus_get_node(dev); - - if (OF_getprop(node, "fsl,fman-mac", (void *)&enet_node, - sizeof(enet_node)) == -1) { - device_printf(dev, "Could not load fsl,fman-mac property " - "from DTS\n"); - return (ENXIO); - } - - enet_node = OF_instance_to_package(enet_node); + enet_node = ofw_bus_get_node(dev); if (OF_getprop(enet_node, "local-mac-address", (void *)sc->sc_mac_addr, 6) == -1) { @@ -156,9 +146,9 @@ dtsec_fdt_attach(device_t dev) } /* Get link speed */ - if (fdt_is_compatible(enet_node, "fsl,fman-1g-mac") != 0) + if (ofw_bus_is_compatible(dev, "fsl,fman-dtsec") != 0) sc->sc_eth_dev_type = ETH_DTSEC; - else if (fdt_is_compatible(enet_node, "fsl,fman-10g-mac") != 0) + else if (ofw_bus_is_compatible(dev, "fsl,fman-xgec") != 0) sc->sc_eth_dev_type = ETH_10GSEC; else return(ENXIO); @@ -198,7 +188,7 @@ dtsec_fdt_attach(device_t dev) return (ENXIO); /* Get RX/TX port handles */ - if (OF_getprop(enet_node, "fsl,port-handles", (void *)fman_rxtx_node, + if (OF_getprop(enet_node, "fsl,fman-ports", (void *)fman_rxtx_node, sizeof(fman_rxtx_node)) <= 0) return (ENXIO); @@ -211,10 +201,12 @@ dtsec_fdt_attach(device_t dev) fman_rxtx_node[0] = OF_instance_to_package(fman_rxtx_node[0]); fman_rxtx_node[1] = OF_instance_to_package(fman_rxtx_node[1]); - if (fdt_is_compatible(fman_rxtx_node[0], "fsl,fman-port-1g-rx") == 0) + if (ofw_bus_node_is_compatible(fman_rxtx_node[0], + "fsl,fman-v2-port-rx") == 0) return (ENXIO); - if (fdt_is_compatible(fman_rxtx_node[1], "fsl,fman-port-1g-tx") == 0) + if (ofw_bus_node_is_compatible(fman_rxtx_node[1], + "fsl,fman-v2-port-tx") == 0) return (ENXIO); /* Get RX port HW id */ @@ -227,11 +219,12 @@ dtsec_fdt_attach(device_t dev) sizeof(sc->sc_port_tx_hw_id)) <= 0) return (ENXIO); - /* Get QMan channel */ - if (OF_getprop(fman_rxtx_node[1], "fsl,qman-channel-id", - (void *)&sc->sc_port_tx_qman_chan, - sizeof(sc->sc_port_tx_qman_chan)) <= 0) + if (OF_getprop(fman_rxtx_node[1], "cell-index", &fman_tx_cell, + sizeof(fman_tx_cell)) <= 0) return (ENXIO); + /* Get QMan channel */ + sc->sc_port_tx_qman_chan = fman_qman_channel_id(device_get_parent(dev), + fman_tx_cell); return (dtsec_attach(dev)); } diff --git a/sys/dev/dpaa/if_dtsec_rm.c b/sys/dev/dpaa/if_dtsec_rm.c index 06e9f0165ed..66c20e3175a 100644 --- a/sys/dev/dpaa/if_dtsec_rm.c +++ b/sys/dev/dpaa/if_dtsec_rm.c @@ -136,7 +136,6 @@ static void dtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi) { - XX_UntrackAddress(fi); uma_zfree(sc->sc_fi_zone, fi); } /** @} */ @@ -323,6 +322,7 @@ dtsec_rm_pool_rx_init(struct dtsec_softc *sc) DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL, NULL); if (sc->sc_rx_pool == NULL) { + device_printf(sc->sc_dev, "NULL rx pool somehow\n"); dtsec_rm_pool_rx_free(sc); return (EIO); } diff --git a/sys/dev/dpaa/qman_fdt.c b/sys/dev/dpaa/qman_fdt.c index 69f128cf649..e37196d54aa 100644 --- a/sys/dev/dpaa/qman_fdt.c +++ b/sys/dev/dpaa/qman_fdt.c @@ -33,11 +33,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include -#include - #include #include #include @@ -107,7 +106,8 @@ static driver_t qm_portals_driver = { }; static devclass_t qm_portals_devclass; -DRIVER_MODULE(qman_portals, ofwbus, qm_portals_driver, qm_portals_devclass, 0, 0); +EARLY_DRIVER_MODULE(qman_portals, ofwbus, qm_portals_driver, + qm_portals_devclass, 0, 0, BUS_PASS_BUS); static void get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep) @@ -123,7 +123,7 @@ static int qman_portals_fdt_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "qman-portals")) + if (!ofw_bus_is_compatible(dev, "fsl,qman-portals")) return (ENXIO); device_set_desc(dev, BMAN_PORT_DEVSTR); @@ -131,36 +131,87 @@ qman_portals_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +static phandle_t +qman_portal_find_cpu(int cpu) +{ + phandle_t node; + pcell_t reg; + + node = OF_finddevice("/cpus"); + if (node == -1) + return (-1); + + for (node = OF_child(node); node != 0; node = OF_peer(node)) { + if (OF_getprop(node, "reg", ®, sizeof(reg)) <= 0) + continue; + if (reg == cpu) + return (node); + } + return (-1); +} + static int qman_portals_fdt_attach(device_t dev) { struct dpaa_portals_softc *sc; - struct resource_list_entry *rle; phandle_t node, child, cpu_node; - vm_paddr_t portal_pa; + vm_paddr_t portal_pa, portal_par_pa; vm_size_t portal_size; - uint32_t addr, size; + uint32_t addr, paddr, size; ihandle_t cpu; int cpu_num, cpus, intr_rid; struct dpaa_portals_devinfo di; struct ofw_bus_devinfo ofw_di = {}; + cell_t *range; + int nrange; + int i; cpus = 0; sc = device_get_softc(dev); sc->sc_dev = dev; node = ofw_bus_get_node(dev); + + /* Get this node's range */ + get_addr_props(ofw_bus_get_node(device_get_parent(dev)), &paddr, &size); get_addr_props(node, &addr, &size); + nrange = OF_getencprop_alloc(node, "ranges", + sizeof(*range), (void **)&range); + if (nrange < addr + paddr + size) + return (ENXIO); + portal_pa = portal_par_pa = 0; + portal_size = 0; + for (i = 0; i < addr; i++) { + portal_pa <<= 32; + portal_pa |= range[i]; + } + for (; i < paddr + addr; i++) { + portal_par_pa <<= 32; + portal_par_pa |= range[i]; + } + portal_pa += portal_par_pa; + for (; i < size + paddr + addr; i++) { + portal_size = (uintmax_t)portal_size << 32; + portal_size |= range[i]; + } + OF_prop_free(range); + sc->sc_dp_size = portal_size; + sc->sc_dp_pa = portal_pa; + /* Find portals tied to CPUs */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { - if (!fdt_is_compatible(child, "fsl,qman-portal")) { + if (cpus >= mp_ncpus) + break; + if (!ofw_bus_node_is_compatible(child, "fsl,qman-portal")) { continue; } /* Checkout related cpu */ if (OF_getprop(child, "cpu-handle", (void *)&cpu, sizeof(cpu)) <= 0) { - continue; + cpu = qman_portal_find_cpu(cpus); + if (cpu <= 0) + continue; } /* Acquire cpu number */ cpu_node = OF_instance_to_package(cpu); @@ -171,9 +222,6 @@ qman_portals_fdt_attach(device_t dev) cpus++; - if (cpus > MAXCPU) - break; - if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) { device_printf(dev, "could not set up devinfo\n"); continue; @@ -194,17 +242,6 @@ qman_portals_fdt_attach(device_t dev) continue; } di.di_intr_rid = intr_rid; - - ofw_reg_to_paddr(child, 0, &portal_pa, &portal_size, NULL); - rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 0); - - if (sc->sc_dp_pa == 0) - sc->sc_dp_pa = portal_pa - rle->start; - - portal_size = rle->end + 1; - rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 1); - portal_size = ulmax(rle->end + 1, portal_size); - sc->sc_dp_size = ulmax(sc->sc_dp_size, portal_size); if (dpaa_portal_alloc_res(dev, &di, cpu_num)) goto err; diff --git a/sys/dev/drm2/drmP.h b/sys/dev/drm2/drmP.h index 508fc309917..51f407c14a9 100644 --- a/sys/dev/drm2/drmP.h +++ b/sys/dev/drm2/drmP.h @@ -1204,17 +1204,6 @@ int drm_mmap_single(struct cdev *kdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj_res, int nprot); d_poll_t drm_poll; - /* Memory management support (drm_memory.h) */ -extern void drm_free_agp(DRM_AGP_MEM * handle, int pages); -extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start); -#ifdef FREEBSD_NOTYET -extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, - struct page **pages, - unsigned long num_pages, - uint32_t gtt_offset, - uint32_t type); -#endif /* FREEBSD_NOTYET */ -extern int drm_unbind_agp(DRM_AGP_MEM * handle); /* Misc. IOCTL support (drm_ioctl.h) */ extern int drm_irq_by_busid(struct drm_device *dev, void *data, @@ -1363,32 +1352,6 @@ extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); extern int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv); - /* AGP/GART support (drm_agpsupport.h) */ -extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); -extern int drm_agp_acquire(struct drm_device *dev); -extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_agp_release(struct drm_device *dev); -extern int drm_agp_release_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode); -extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info); -extern int drm_agp_info_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request); -extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request); -extern int drm_agp_free_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request); -extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); -extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); /* Stub support (drm_stub.h) */ extern int drm_setmaster_ioctl(struct drm_device *dev, void *data, @@ -1814,5 +1777,175 @@ int ttm_bo_mmap_single(struct ttm_bo_device *bdev, vm_ooffset_t *offset, struct ttm_buffer_object; void ttm_bo_release_mmap(struct ttm_buffer_object *bo); +#if __OS_HAS_AGP + /* Memory management support (drm_memory.h) */ +extern void drm_free_agp(DRM_AGP_MEM * handle, int pages); +extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start); +#ifdef FREEBSD_NOTYET +extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, + struct page **pages, + unsigned long num_pages, + uint32_t gtt_offset, + uint32_t type); +#endif /* FREEBSD_NOTYET */ +extern int drm_unbind_agp(DRM_AGP_MEM * handle); + + /* AGP/GART support (drm_agpsupport.h) */ +extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); +extern int drm_agp_acquire(struct drm_device *dev); +extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_release(struct drm_device *dev); +extern int drm_agp_release_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode); +extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info); +extern int drm_agp_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request); +extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request); +extern int drm_agp_free_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request); +extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); +extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +#else + +static inline void drm_free_agp(DRM_AGP_MEM * handle, int pages) +{ +} + +static inline int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) +{ + return -ENODEV; +} + +static inline int drm_unbind_agp(DRM_AGP_MEM * handle) +{ + return -ENODEV; +} +#ifdef FREEBSD_NOTYET +static inline struct agp_memory *drm_agp_bind_pages(struct drm_device *dev, + struct page **pages, + unsigned long num_pages, + uint32_t gtt_offset, + uint32_t type) +{ + return NULL; +} +#endif +static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev) +{ + return NULL; +} + +static inline void drm_agp_clear(struct drm_device *dev) +{ +} + +static inline int drm_agp_acquire(struct drm_device *dev) +{ + return -ENODEV; +} + +static inline int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +static inline int drm_agp_release(struct drm_device *dev) +{ + return -ENODEV; +} + +static inline int drm_agp_release_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +static inline int drm_agp_enable(struct drm_device *dev, + struct drm_agp_mode mode) +{ + return -ENODEV; +} + +static inline int drm_agp_enable_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +static inline int drm_agp_info(struct drm_device *dev, + struct drm_agp_info *info) +{ + return -ENODEV; +} + +static inline int drm_agp_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +static inline int drm_agp_alloc(struct drm_device *dev, + struct drm_agp_buffer *request) +{ + return -ENODEV; +} + +static inline int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +static inline int drm_agp_free(struct drm_device *dev, + struct drm_agp_buffer *request) +{ + return -ENODEV; +} + +static inline int drm_agp_free_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +static inline int drm_agp_unbind(struct drm_device *dev, + struct drm_agp_binding *request) +{ + return -ENODEV; +} + +static inline int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +static inline int drm_agp_bind(struct drm_device *dev, + struct drm_agp_binding *request) +{ + return -ENODEV; +} + +static inline int drm_agp_bind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENODEV; +} + +#endif /* __OS_HAS_AGP */ + #endif /* __KERNEL__ */ #endif diff --git a/sys/dev/drm2/drm_memory.c b/sys/dev/drm2/drm_memory.c index a25e5a288ee..226c2c15734 100644 --- a/sys/dev/drm2/drm_memory.c +++ b/sys/dev/drm2/drm_memory.c @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); #include +#define vunmap(handle) + #if __OS_HAS_AGP static void *agp_remap(unsigned long offset, unsigned long size, struct drm_device * dev) @@ -50,8 +52,6 @@ static void *agp_remap(unsigned long offset, unsigned long size, return NULL; } -#define vunmap(handle) - /** Wrapper around agp_free_memory() */ void drm_free_agp(DRM_AGP_MEM * handle, int pages) { diff --git a/sys/dev/drm2/drm_os_freebsd.c b/sys/dev/drm2/drm_os_freebsd.c index d8b45e8fb58..4ce8081887b 100644 --- a/sys/dev/drm2/drm_os_freebsd.c +++ b/sys/dev/drm2/drm_os_freebsd.c @@ -347,6 +347,7 @@ dmi_check_system(const struct dmi_system_id *sysid) return (res); } +#if __OS_HAS_MTRR int drm_mtrr_add(unsigned long offset, unsigned long size, unsigned int flags) { @@ -375,6 +376,7 @@ drm_mtrr_del(int handle __unused, unsigned long offset, unsigned long size, strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner)); return (-mem_range_attr_set(&mrdesc, &act)); } +#endif void drm_clflush_pages(vm_page_t *pages, unsigned long num_pages) diff --git a/sys/dev/drm2/drm_os_freebsd.h b/sys/dev/drm2/drm_os_freebsd.h index 3c9983838e1..dc01c6a6459 100644 --- a/sys/dev/drm2/drm_os_freebsd.h +++ b/sys/dev/drm2/drm_os_freebsd.h @@ -592,8 +592,10 @@ typedef struct drm_pci_id_list #define CONFIG_COMPAT #endif +#ifndef __arm__ #define CONFIG_AGP 1 #define CONFIG_MTRR 1 +#endif #define CONFIG_FB 1 extern const char *fb_mode_option; diff --git a/sys/dev/drm2/ttm/ttm_bo_util.c b/sys/dev/drm2/ttm/ttm_bo_util.c index fbbaaf2029f..c53bb21450d 100644 --- a/sys/dev/drm2/ttm/ttm_bo_util.c +++ b/sys/dev/drm2/ttm/ttm_bo_util.c @@ -439,7 +439,8 @@ ttm_buffer_object_transfer(struct ttm_buffer_object *bo, vm_memattr_t ttm_io_prot(uint32_t caching_flags) { -#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) +#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || \ + defined(__arm__) if (caching_flags & TTM_PL_FLAG_WC) return (VM_MEMATTR_WRITE_COMBINING); else diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index fd602bf482f..b1bf35b5e46 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -5274,6 +5274,8 @@ em_get_wakeup(device_t dev) case e1000_ich10lan: case e1000_pchlan: case e1000_pch2lan: + case e1000_pch_lpt: + case e1000_pch_spt: apme_mask = E1000_WUC_APME; adapter->has_amt = TRUE; eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC); @@ -5322,7 +5324,7 @@ em_enable_wakeup(device_t dev) { struct adapter *adapter = device_get_softc(dev); if_t ifp = adapter->ifp; - u32 pmc, ctrl, ctrl_ext, rctl; + u32 pmc, ctrl, ctrl_ext, rctl, wuc; u16 status; if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0)) @@ -5332,7 +5334,9 @@ em_enable_wakeup(device_t dev) ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); - E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); + wuc = E1000_READ_REG(&adapter->hw, E1000_WUC); + wuc |= E1000_WUC_PME_EN; + E1000_WRITE_REG(&adapter->hw, E1000_WUC, wuc); if ((adapter->hw.mac.type == e1000_ich8lan) || (adapter->hw.mac.type == e1000_pchlan) || @@ -5363,8 +5367,10 @@ em_enable_wakeup(device_t dev) E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); } - if ((adapter->hw.mac.type == e1000_pchlan) || - (adapter->hw.mac.type == e1000_pch2lan)) { + if ((adapter->hw.mac.type == e1000_pchlan) || + (adapter->hw.mac.type == e1000_pch2lan) || + (adapter->hw.mac.type == e1000_pch_lpt) || + (adapter->hw.mac.type == e1000_pch_spt)) { if (em_enable_phy_wakeup(adapter)) return; } else { diff --git a/sys/dev/etherswitch/e6000sw/e6060sw.c b/sys/dev/etherswitch/e6000sw/e6060sw.c new file mode 100644 index 00000000000..9e3d93b66d2 --- /dev/null +++ b/sys/dev/etherswitch/e6000sw/e6060sw.c @@ -0,0 +1,703 @@ +/*- + * Copyright (c) 2016 Hiroki Mori + * Copyright (c) 2013 Luiz Otavio O Souza. + * Copyright (c) 2011-2012 Stefan Bethke. + * Copyright (c) 2012 Adrian Chadd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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$ + */ + +/* + * This code is Marvell 88E6060 ethernet switch support code on etherswitch + * framework. + * Current code is only support port base vlan. Not support ingress/egress + * trailer. This switch chip can't work vlan(4) support. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "mdio_if.h" +#include "miibus_if.h" +#include "etherswitch_if.h" + +#define SMI_OFFSET 0x10 +#define CORE_REGISTER (SMI_OFFSET + 8) + +#define SWITCH_ID 3 +#define PORT_VLAN_MAP 6 + +MALLOC_DECLARE(M_E6060SW); +MALLOC_DEFINE(M_E6060SW, "e6060sw", "e6060sw data structures"); + +struct e6060sw_softc { + struct mtx sc_mtx; /* serialize access to softc */ + device_t sc_dev; + int vlan_mode; + int media; /* cpu port media */ + int cpuport; /* which PHY is connected to the CPU */ + int phymask; /* PHYs we manage */ + int numports; /* number of ports */ + int ifpport[MII_NPHY]; + int *portphy; + char **ifname; + device_t **miibus; + struct ifnet **ifp; + struct callout callout_tick; + etherswitch_info_t info; +}; + +#define E6060SW_LOCK(_sc) \ + mtx_lock(&(_sc)->sc_mtx) +#define E6060SW_UNLOCK(_sc) \ + mtx_unlock(&(_sc)->sc_mtx) +#define E6060SW_LOCK_ASSERT(_sc, _what) \ + mtx_assert(&(_sc)->sc_mtx, (_what)) +#define E6060SW_TRYLOCK(_sc) \ + mtx_trylock(&(_sc)->sc_mtx) + +#if defined(DEBUG) +#define DPRINTF(dev, args...) device_printf(dev, args) +#else +#define DPRINTF(dev, args...) +#endif + +static inline int e6060sw_portforphy(struct e6060sw_softc *, int); +static void e6060sw_tick(void *); +static int e6060sw_ifmedia_upd(struct ifnet *); +static void e6060sw_ifmedia_sts(struct ifnet *, struct ifmediareq *); + +static int +e6060sw_probe(device_t dev) +{ + int data; + struct e6060sw_softc *sc; + + sc = device_get_softc(dev); + bzero(sc, sizeof(*sc)); + + data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER, SWITCH_ID); + if (bootverbose) + device_printf(dev,"Switch Identifier Register %x\n", data); + + if ((data >> 4) != 0x060) { + return (ENXIO); + } + + device_set_desc_copy(dev, "Marvell 88E6060 MDIO switch driver"); + return (BUS_PROBE_DEFAULT); +} + +static int +e6060sw_attach_phys(struct e6060sw_softc *sc) +{ + int phy, port, err; + char name[IFNAMSIZ]; + + port = 0; + err = 0; + /* PHYs need an interface, so we generate a dummy one */ + snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev)); + for (phy = 0; phy < sc->numports; phy++) { + if (((1 << phy) & sc->phymask) == 0) + continue; + sc->ifpport[phy] = port; + sc->portphy[port] = phy; + sc->ifp[port] = if_alloc(IFT_ETHER); + sc->ifp[port]->if_softc = sc; + sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST | + IFF_DRV_RUNNING | IFF_SIMPLEX; + if_initname(sc->ifp[port], name, port); + sc->miibus[port] = malloc(sizeof(device_t), M_E6060SW, + M_WAITOK | M_ZERO); + err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port], + e6060sw_ifmedia_upd, e6060sw_ifmedia_sts, \ + BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); + DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n", + device_get_nameunit(*sc->miibus[port]), + sc->ifp[port]->if_xname); + if (err != 0) { + device_printf(sc->sc_dev, + "attaching PHY %d failed\n", + phy); + break; + } + ++port; + } + sc->info.es_nports = port; + if (sc->cpuport != -1) { + /* assume cpuport is last one */ + sc->ifpport[sc->cpuport] = port; + sc->portphy[port] = sc->cpuport; + ++sc->info.es_nports; + } + return (err); +} + +static int +e6060sw_attach(device_t dev) +{ + struct e6060sw_softc *sc; + int err; + + sc = device_get_softc(dev); + err = 0; + + sc->sc_dev = dev; + mtx_init(&sc->sc_mtx, "e6060sw", NULL, MTX_DEF); + strlcpy(sc->info.es_name, device_get_desc(dev), + sizeof(sc->info.es_name)); + + /* XXX Defaults */ + sc->numports = 6; + sc->phymask = 0x1f; + sc->cpuport = 5; + sc->media = 100; + + (void) resource_int_value(device_get_name(dev), device_get_unit(dev), + "numports", &sc->numports); + (void) resource_int_value(device_get_name(dev), device_get_unit(dev), + "phymask", &sc->phymask); + (void) resource_int_value(device_get_name(dev), device_get_unit(dev), + "cpuport", &sc->cpuport); + (void) resource_int_value(device_get_name(dev), device_get_unit(dev), + "media", &sc->media); + + sc->info.es_nvlangroups = sc->numports; + sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT; + + sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_E6060SW, + M_WAITOK | M_ZERO); + sc->ifname = malloc(sizeof(char *) * sc->numports, M_E6060SW, + M_WAITOK | M_ZERO); + sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_E6060SW, + M_WAITOK | M_ZERO); + sc->portphy = malloc(sizeof(int) * sc->numports, M_E6060SW, + M_WAITOK | M_ZERO); + + /* + * Attach the PHYs and complete the bus enumeration. + */ + err = e6060sw_attach_phys(sc); + if (err != 0) + return (err); + + bus_generic_probe(dev); + bus_enumerate_hinted_children(dev); + err = bus_generic_attach(dev); + if (err != 0) + return (err); + + callout_init(&sc->callout_tick, 0); + + e6060sw_tick(sc); + + return (err); +} + +static int +e6060sw_detach(device_t dev) +{ + struct e6060sw_softc *sc; + int i, port; + + sc = device_get_softc(dev); + + callout_drain(&sc->callout_tick); + + for (i = 0; i < MII_NPHY; i++) { + if (((1 << i) & sc->phymask) == 0) + continue; + port = e6060sw_portforphy(sc, i); + if (sc->miibus[port] != NULL) + device_delete_child(dev, (*sc->miibus[port])); + if (sc->ifp[port] != NULL) + if_free(sc->ifp[port]); + free(sc->ifname[port], M_E6060SW); + free(sc->miibus[port], M_E6060SW); + } + + free(sc->portphy, M_E6060SW); + free(sc->miibus, M_E6060SW); + free(sc->ifname, M_E6060SW); + free(sc->ifp, M_E6060SW); + + bus_generic_detach(dev); + mtx_destroy(&sc->sc_mtx); + + return (0); +} + +/* + * Convert PHY number to port number. + */ +static inline int +e6060sw_portforphy(struct e6060sw_softc *sc, int phy) +{ + + return (sc->ifpport[phy]); +} + +static inline struct mii_data * +e6060sw_miiforport(struct e6060sw_softc *sc, int port) +{ + + if (port < 0 || port > sc->numports) + return (NULL); + if (port == sc->cpuport) + return (NULL); + return (device_get_softc(*sc->miibus[port])); +} + +static inline struct ifnet * +e6060sw_ifpforport(struct e6060sw_softc *sc, int port) +{ + + if (port < 0 || port > sc->numports) + return (NULL); + return (sc->ifp[port]); +} + +/* + * Poll the status for all PHYs. + */ +static void +e6060sw_miipollstat(struct e6060sw_softc *sc) +{ + int i, port; + struct mii_data *mii; + struct mii_softc *miisc; + + E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); + + for (i = 0; i < MII_NPHY; i++) { + if (((1 << i) & sc->phymask) == 0) + continue; + port = e6060sw_portforphy(sc, i); + if ((*sc->miibus[port]) == NULL) + continue; + mii = device_get_softc(*sc->miibus[port]); + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { + if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != + miisc->mii_inst) + continue; + ukphy_status(miisc); + mii_phy_update(miisc, MII_POLLSTAT); + } + } +} + +static void +e6060sw_tick(void *arg) +{ + struct e6060sw_softc *sc; + + sc = arg; + + e6060sw_miipollstat(sc); + callout_reset(&sc->callout_tick, hz, e6060sw_tick, sc); +} + +static void +e6060sw_lock(device_t dev) +{ + struct e6060sw_softc *sc; + + sc = device_get_softc(dev); + + E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); + E6060SW_LOCK(sc); +} + +static void +e6060sw_unlock(device_t dev) +{ + struct e6060sw_softc *sc; + + sc = device_get_softc(dev); + + E6060SW_LOCK_ASSERT(sc, MA_OWNED); + E6060SW_UNLOCK(sc); +} + +static etherswitch_info_t * +e6060sw_getinfo(device_t dev) +{ + struct e6060sw_softc *sc; + + sc = device_get_softc(dev); + + return (&sc->info); +} + +static int +e6060sw_getport(device_t dev, etherswitch_port_t *p) +{ + struct e6060sw_softc *sc; + struct mii_data *mii; + struct ifmediareq *ifmr; + int err, phy; + + sc = device_get_softc(dev); + ifmr = &p->es_ifmr; + + if (p->es_port < 0 || p->es_port >= sc->numports) + return (ENXIO); + p->es_pvid = 0; + + phy = sc->portphy[p->es_port]; + mii = e6060sw_miiforport(sc, p->es_port); + if (sc->cpuport != -1 && phy == sc->cpuport) { + /* fill in fixed values for CPU port */ + p->es_flags |= ETHERSWITCH_PORT_CPU; + ifmr->ifm_count = 0; + if (sc->media == 100) + ifmr->ifm_current = ifmr->ifm_active = + IFM_ETHER | IFM_100_TX | IFM_FDX; + else + ifmr->ifm_current = ifmr->ifm_active = + IFM_ETHER | IFM_1000_T | IFM_FDX; + ifmr->ifm_mask = 0; + ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; + } else if (mii != NULL) { + err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, + &mii->mii_media, SIOCGIFMEDIA); + if (err) + return (err); + } else { + return (ENXIO); + } + return (0); +} + +static int +e6060sw_setport(device_t dev, etherswitch_port_t *p) +{ + struct e6060sw_softc *sc; + struct ifmedia *ifm; + struct mii_data *mii; + struct ifnet *ifp; + int err; + + sc = device_get_softc(dev); + + if (p->es_port < 0 || p->es_port >= sc->numports) + return (ENXIO); + + if (sc->portphy[p->es_port] == sc->cpuport) + return (ENXIO); + + mii = e6060sw_miiforport(sc, p->es_port); + if (mii == NULL) + return (ENXIO); + + ifp = e6060sw_ifpforport(sc, p->es_port); + + ifm = &mii->mii_media; + err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA); + return (err); +} + +static int +e6060sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) +{ + struct e6060sw_softc *sc; + int data; + + sc = device_get_softc(dev); + + if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { + vg->es_vid = ETHERSWITCH_VID_VALID; + vg->es_vid |= vg->es_vlangroup; + data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP); + vg->es_member_ports = data & 0x3f; + vg->es_untagged_ports = vg->es_member_ports; + vg->es_fid = 0; + } else { + vg->es_vid = 0; + } + return (0); +} + +static int +e6060sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) +{ + struct e6060sw_softc *sc; + int data; + + sc = device_get_softc(dev); + + if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { + data = MDIO_READREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP); + data &= ~0x3f; + data |= vg->es_member_ports; + MDIO_WRITEREG(device_get_parent(dev), CORE_REGISTER + vg->es_vlangroup, PORT_VLAN_MAP, data); + } + + return (0); +} + +static void +e6060sw_reset_vlans(device_t dev) +{ + struct e6060sw_softc *sc; + uint32_t ports; + int i; + int data; + + sc = device_get_softc(dev); + + for (i = 0; i <= sc->numports; i++) { + ports = (1 << (sc->numports + 1)) - 1; + ports &= ~(1 << i); + if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { + data = i << 12; + } else { + data = 0; + } + data |= ports; + MDIO_WRITEREG(device_get_parent(dev), CORE_REGISTER + i, PORT_VLAN_MAP, data); + } +} + +static int +e6060sw_getconf(device_t dev, etherswitch_conf_t *conf) +{ + struct e6060sw_softc *sc; + + sc = device_get_softc(dev); + + /* Return the VLAN mode. */ + conf->cmd = ETHERSWITCH_CONF_VLAN_MODE; + conf->vlan_mode = sc->vlan_mode; + + return (0); +} + +static int +e6060sw_setconf(device_t dev, etherswitch_conf_t *conf) +{ + struct e6060sw_softc *sc; + + sc = device_get_softc(dev); + + /* Set the VLAN mode. */ + if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) { + if (conf->vlan_mode == ETHERSWITCH_VLAN_PORT) { + sc->vlan_mode = ETHERSWITCH_VLAN_PORT; + } else { + sc->vlan_mode = 0; + } + + /* Reset VLANs. */ + e6060sw_reset_vlans(dev); + } + + return (0); +} + +static void +e6060sw_statchg(device_t dev) +{ + + DPRINTF(dev, "%s\n", __func__); +} + +static int +e6060sw_ifmedia_upd(struct ifnet *ifp) +{ + struct e6060sw_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = e6060sw_miiforport(sc, ifp->if_dunit); + + DPRINTF(sc->sc_dev, "%s\n", __func__); + if (mii == NULL) + return (ENXIO); + mii_mediachg(mii); + return (0); +} + +static void +e6060sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct e6060sw_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = e6060sw_miiforport(sc, ifp->if_dunit); + + DPRINTF(sc->sc_dev, "%s\n", __func__); + + if (mii == NULL) + return; + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; +} + +static int +e6060sw_readphy(device_t dev, int phy, int reg) +{ + struct e6060sw_softc *sc; + int data; + + phy += SMI_OFFSET; + + sc = device_get_softc(dev); + E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); + + if (phy < 0 || phy >= 32) + return (ENXIO); + if (reg < 0 || reg >= 32) + return (ENXIO); + + E6060SW_LOCK(sc); + data = MDIO_READREG(device_get_parent(dev), phy, reg); + E6060SW_UNLOCK(sc); + + return (data); +} + +static int +e6060sw_writephy(device_t dev, int phy, int reg, int data) +{ + struct e6060sw_softc *sc; + int err; + + phy += SMI_OFFSET; + + sc = device_get_softc(dev); + E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); + + if (phy < 0 || phy >= 32) + return (ENXIO); + if (reg < 0 || reg >= 32) + return (ENXIO); + + E6060SW_LOCK(sc); + err = MDIO_WRITEREG(device_get_parent(dev), phy, reg, data); + E6060SW_UNLOCK(sc); + + return (err); +} + +/* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */ + +static int +e6060sw_readreg(device_t dev, int addr) +{ + int devaddr, regaddr; + + devaddr = (addr >> 5) & 0xf; + regaddr = addr & 0x1f; + + return MDIO_READREG(device_get_parent(dev), devaddr+SMI_OFFSET, regaddr); +} + +/* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */ + +static int +e6060sw_writereg(device_t dev, int addr, int value) +{ + int devaddr, regaddr; + + devaddr = (addr >> 5) & 0xf; + regaddr = addr & 0x1f; + + return (MDIO_WRITEREG(device_get_parent(dev), devaddr+SMI_OFFSET, regaddr, value)); +} + +static device_method_t e6060sw_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, e6060sw_probe), + DEVMETHOD(device_attach, e6060sw_attach), + DEVMETHOD(device_detach, e6060sw_detach), + + /* bus interface */ + DEVMETHOD(bus_add_child, device_add_child_ordered), + + /* MII interface */ + DEVMETHOD(miibus_readreg, e6060sw_readphy), + DEVMETHOD(miibus_writereg, e6060sw_writephy), + DEVMETHOD(miibus_statchg, e6060sw_statchg), + + /* MDIO interface */ + DEVMETHOD(mdio_readreg, e6060sw_readphy), + DEVMETHOD(mdio_writereg, e6060sw_writephy), + + /* etherswitch interface */ + DEVMETHOD(etherswitch_lock, e6060sw_lock), + DEVMETHOD(etherswitch_unlock, e6060sw_unlock), + DEVMETHOD(etherswitch_getinfo, e6060sw_getinfo), + DEVMETHOD(etherswitch_readreg, e6060sw_readreg), + DEVMETHOD(etherswitch_writereg, e6060sw_writereg), + DEVMETHOD(etherswitch_readphyreg, e6060sw_readphy), + DEVMETHOD(etherswitch_writephyreg, e6060sw_writephy), + DEVMETHOD(etherswitch_getport, e6060sw_getport), + DEVMETHOD(etherswitch_setport, e6060sw_setport), + DEVMETHOD(etherswitch_getvgroup, e6060sw_getvgroup), + DEVMETHOD(etherswitch_setvgroup, e6060sw_setvgroup), + DEVMETHOD(etherswitch_setconf, e6060sw_setconf), + DEVMETHOD(etherswitch_getconf, e6060sw_getconf), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(e6060sw, e6060sw_driver, e6060sw_methods, + sizeof(struct e6060sw_softc)); +static devclass_t e6060sw_devclass; + +DRIVER_MODULE(e6060sw, mdio, e6060sw_driver, e6060sw_devclass, 0, 0); +DRIVER_MODULE(miibus, e6060sw, miibus_driver, miibus_devclass, 0, 0); +DRIVER_MODULE(mdio, e6060sw, mdio_driver, mdio_devclass, 0, 0); +DRIVER_MODULE(etherswitch, e6060sw, etherswitch_driver, etherswitch_devclass, 0, 0); +MODULE_VERSION(e6060sw, 1); +MODULE_DEPEND(e6060sw, miibus, 1, 1, 1); /* XXX which versions? */ +MODULE_DEPEND(e6060sw, etherswitch, 1, 1, 1); /* XXX which versions? */ diff --git a/sys/dev/etherswitch/infineon/adm6996fc.c b/sys/dev/etherswitch/infineon/adm6996fc.c new file mode 100644 index 00000000000..da31b7a964d --- /dev/null +++ b/sys/dev/etherswitch/infineon/adm6996fc.c @@ -0,0 +1,858 @@ +/*- + * Copyright (c) 2016 Hiroki Mori + * Copyright (c) 2013 Luiz Otavio O Souza. + * Copyright (c) 2011-2012 Stefan Bethke. + * Copyright (c) 2012 Adrian Chadd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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$ + */ + +/* + * This is Infineon ADM6996FC/M/MX driver code on etherswitch framework. + * Support PORT and DOT1Q VLAN. + * This code suppose ADM6996FC SDC/SDIO connect to SOC network interface + * MDC/MDIO. + * This code development on Netgear WGR614Cv7. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "mdio_if.h" +#include "miibus_if.h" +#include "etherswitch_if.h" + +#define ADM6996FC_PRODUCT_CODE 0x7102 + +#define ADM6996FC_SC3 0x11 +#define ADM6996FC_VF0L 0x40 +#define ADM6996FC_VF0H 0x41 +#define ADM6996FC_CI0 0xa0 +#define ADM6996FC_CI1 0xa1 +#define ADM6996FC_PHY_C0 0x200 + +#define ADM6996FC_PC_SHIFT 4 +#define ADM6996FC_TBV_SHIFT 5 +#define ADM6996FC_PVID_SHIFT 10 +#define ADM6996FC_OPTE_SHIFT 4 +#define ADM6996FC_VV_SHIFT 15 + +#define ADM6996FC_PHY_SIZE 0x20 + +MALLOC_DECLARE(M_ADM6996FC); +MALLOC_DEFINE(M_ADM6996FC, "adm6996fc", "adm6996fc data structures"); + +struct adm6996fc_softc { + struct mtx sc_mtx; /* serialize access to softc */ + device_t sc_dev; + int vlan_mode; + int media; /* cpu port media */ + int cpuport; /* which PHY is connected to the CPU */ + int phymask; /* PHYs we manage */ + int numports; /* number of ports */ + int ifpport[MII_NPHY]; + int *portphy; + char **ifname; + device_t **miibus; + struct ifnet **ifp; + struct callout callout_tick; + etherswitch_info_t info; +}; + +#define ADM6996FC_LOCK(_sc) \ + mtx_lock(&(_sc)->sc_mtx) +#define ADM6996FC_UNLOCK(_sc) \ + mtx_unlock(&(_sc)->sc_mtx) +#define ADM6996FC_LOCK_ASSERT(_sc, _what) \ + mtx_assert(&(_sc)->sc_mtx, (_what)) +#define ADM6996FC_TRYLOCK(_sc) \ + mtx_trylock(&(_sc)->sc_mtx) + +#if defined(DEBUG) +#define DPRINTF(dev, args...) device_printf(dev, args) +#else +#define DPRINTF(dev, args...) +#endif + +static inline int adm6996fc_portforphy(struct adm6996fc_softc *, int); +static void adm6996fc_tick(void *); +static int adm6996fc_ifmedia_upd(struct ifnet *); +static void adm6996fc_ifmedia_sts(struct ifnet *, struct ifmediareq *); + +#define ADM6996FC_READREG(dev, x) \ + MDIO_READREG(dev, ((x) >> 5), ((x) & 0x1f)); +#define ADM6996FC_WRITEREG(dev, x, v) \ + MDIO_WRITEREG(dev, ((x) >> 5), ((x) & 0x1f), v); + +#define ADM6996FC_PVIDBYDATA(data1, data2) \ + ((((data1) >> ADM6996FC_PVID_SHIFT) & 0x0f) | ((data2) << 4)) + +static int +adm6996fc_probe(device_t dev) +{ + int data1, data2; + int pc; + struct adm6996fc_softc *sc; + + sc = device_get_softc(dev); + bzero(sc, sizeof(*sc)); + + data1 = ADM6996FC_READREG(device_get_parent(dev), ADM6996FC_CI0); + data2 = ADM6996FC_READREG(device_get_parent(dev), ADM6996FC_CI1); + pc = ((data2 << 16) | data1) >> ADM6996FC_PC_SHIFT; + if (bootverbose) + device_printf(dev,"Chip Identifier Register %x %x\n", data1, + data2); + + /* check Product Code */ + if (pc != ADM6996FC_PRODUCT_CODE) { + return (ENXIO); + } + + device_set_desc_copy(dev, "Infineon ADM6996FC/M/MX MDIO switch driver"); + return (BUS_PROBE_DEFAULT); +} + +static int +adm6996fc_attach_phys(struct adm6996fc_softc *sc) +{ + int phy, port, err; + char name[IFNAMSIZ]; + + port = 0; + err = 0; + /* PHYs need an interface, so we generate a dummy one */ + snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev)); + for (phy = 0; phy < sc->numports; phy++) { + if (((1 << phy) & sc->phymask) == 0) + continue; + sc->ifpport[phy] = port; + sc->portphy[port] = phy; + sc->ifp[port] = if_alloc(IFT_ETHER); + sc->ifp[port]->if_softc = sc; + sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST | + IFF_DRV_RUNNING | IFF_SIMPLEX; + if_initname(sc->ifp[port], name, port); + sc->miibus[port] = malloc(sizeof(device_t), M_ADM6996FC, + M_WAITOK | M_ZERO); + if (sc->miibus[port] == NULL) { + err = ENOMEM; + goto failed; + } + err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port], + adm6996fc_ifmedia_upd, adm6996fc_ifmedia_sts, \ + BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); + DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n", + device_get_nameunit(*sc->miibus[port]), + sc->ifp[port]->if_xname); + if (err != 0) { + device_printf(sc->sc_dev, + "attaching PHY %d failed\n", + phy); + goto failed; + } + ++port; + } + sc->info.es_nports = port; + if (sc->cpuport != -1) { + /* assume cpuport is last one */ + sc->ifpport[sc->cpuport] = port; + sc->portphy[port] = sc->cpuport; + ++sc->info.es_nports; + } + return (0); + +failed: + for (phy = 0; phy < sc->numports; phy++) { + if (((1 << phy) & sc->phymask) == 0) + continue; + port = adm6996fc_portforphy(sc, phy); + if (sc->miibus[port] != NULL) + device_delete_child(sc->sc_dev, (*sc->miibus[port])); + if (sc->ifp[port] != NULL) + if_free(sc->ifp[port]); + if (sc->ifname[port] != NULL) + free(sc->ifname[port], M_ADM6996FC); + if (sc->miibus[port] != NULL) + free(sc->miibus[port], M_ADM6996FC); + } + return (err); +} + +static int +adm6996fc_attach(device_t dev) +{ + struct adm6996fc_softc *sc; + int err; + + err = 0; + sc = device_get_softc(dev); + + sc->sc_dev = dev; + mtx_init(&sc->sc_mtx, "adm6996fc", NULL, MTX_DEF); + strlcpy(sc->info.es_name, device_get_desc(dev), + sizeof(sc->info.es_name)); + + /* ADM6996FC Defaults */ + sc->numports = 6; + sc->phymask = 0x1f; + sc->cpuport = 5; + sc->media = 100; + + sc->info.es_nvlangroups = 16; + sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOT1Q; + + sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_ADM6996FC, + M_WAITOK | M_ZERO); + sc->ifname = malloc(sizeof(char *) * sc->numports, M_ADM6996FC, + M_WAITOK | M_ZERO); + sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_ADM6996FC, + M_WAITOK | M_ZERO); + sc->portphy = malloc(sizeof(int) * sc->numports, M_ADM6996FC, + M_WAITOK | M_ZERO); + + if (sc->ifp == NULL || sc->ifname == NULL || sc->miibus == NULL || + sc->portphy == NULL) { + err = ENOMEM; + goto failed; + } + + /* + * Attach the PHYs and complete the bus enumeration. + */ + err = adm6996fc_attach_phys(sc); + if (err != 0) + goto failed; + + bus_generic_probe(dev); + bus_enumerate_hinted_children(dev); + err = bus_generic_attach(dev); + if (err != 0) + goto failed; + + callout_init(&sc->callout_tick, 0); + + adm6996fc_tick(sc); + + return (0); + +failed: + if (sc->portphy != NULL) + free(sc->portphy, M_ADM6996FC); + if (sc->miibus != NULL) + free(sc->miibus, M_ADM6996FC); + if (sc->ifname != NULL) + free(sc->ifname, M_ADM6996FC); + if (sc->ifp != NULL) + free(sc->ifp, M_ADM6996FC); + + return (err); +} + +static int +adm6996fc_detach(device_t dev) +{ + struct adm6996fc_softc *sc; + int i, port; + + sc = device_get_softc(dev); + + callout_drain(&sc->callout_tick); + + for (i = 0; i < MII_NPHY; i++) { + if (((1 << i) & sc->phymask) == 0) + continue; + port = adm6996fc_portforphy(sc, i); + if (sc->miibus[port] != NULL) + device_delete_child(dev, (*sc->miibus[port])); + if (sc->ifp[port] != NULL) + if_free(sc->ifp[port]); + free(sc->ifname[port], M_ADM6996FC); + free(sc->miibus[port], M_ADM6996FC); + } + + free(sc->portphy, M_ADM6996FC); + free(sc->miibus, M_ADM6996FC); + free(sc->ifname, M_ADM6996FC); + free(sc->ifp, M_ADM6996FC); + + bus_generic_detach(dev); + mtx_destroy(&sc->sc_mtx); + + return (0); +} + +/* + * Convert PHY number to port number. + */ +static inline int +adm6996fc_portforphy(struct adm6996fc_softc *sc, int phy) +{ + + return (sc->ifpport[phy]); +} + +static inline struct mii_data * +adm6996fc_miiforport(struct adm6996fc_softc *sc, int port) +{ + + if (port < 0 || port > sc->numports) + return (NULL); + if (port == sc->cpuport) + return (NULL); + return (device_get_softc(*sc->miibus[port])); +} + +static inline struct ifnet * +adm6996fc_ifpforport(struct adm6996fc_softc *sc, int port) +{ + + if (port < 0 || port > sc->numports) + return (NULL); + return (sc->ifp[port]); +} + +/* + * Poll the status for all PHYs. + */ +static void +adm6996fc_miipollstat(struct adm6996fc_softc *sc) +{ + int i, port; + struct mii_data *mii; + struct mii_softc *miisc; + + ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED); + + for (i = 0; i < MII_NPHY; i++) { + if (((1 << i) & sc->phymask) == 0) + continue; + port = adm6996fc_portforphy(sc, i); + if ((*sc->miibus[port]) == NULL) + continue; + mii = device_get_softc(*sc->miibus[port]); + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { + if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != + miisc->mii_inst) + continue; + ukphy_status(miisc); + mii_phy_update(miisc, MII_POLLSTAT); + } + } +} + +static void +adm6996fc_tick(void *arg) +{ + struct adm6996fc_softc *sc; + + sc = arg; + + adm6996fc_miipollstat(sc); + callout_reset(&sc->callout_tick, hz, adm6996fc_tick, sc); +} + +static void +adm6996fc_lock(device_t dev) +{ + struct adm6996fc_softc *sc; + + sc = device_get_softc(dev); + + ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED); + ADM6996FC_LOCK(sc); +} + +static void +adm6996fc_unlock(device_t dev) +{ + struct adm6996fc_softc *sc; + + sc = device_get_softc(dev); + + ADM6996FC_LOCK_ASSERT(sc, MA_OWNED); + ADM6996FC_UNLOCK(sc); +} + +static etherswitch_info_t * +adm6996fc_getinfo(device_t dev) +{ + struct adm6996fc_softc *sc; + + sc = device_get_softc(dev); + + return (&sc->info); +} + +static int +adm6996fc_getport(device_t dev, etherswitch_port_t *p) +{ + struct adm6996fc_softc *sc; + struct mii_data *mii; + struct ifmediareq *ifmr; + device_t parent; + int err, phy; + int data1, data2; + + int bcaddr[6] = {0x01, 0x03, 0x05, 0x07, 0x08, 0x09}; + int vidaddr[6] = {0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c}; + + sc = device_get_softc(dev); + ifmr = &p->es_ifmr; + + if (p->es_port < 0 || p->es_port >= sc->numports) + return (ENXIO); + + parent = device_get_parent(dev); + + if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { + data1 = ADM6996FC_READREG(parent, bcaddr[p->es_port]); + data2 = ADM6996FC_READREG(parent, vidaddr[p->es_port]); + /* only port 4 is hi bit */ + if (p->es_port == 4) + data2 = (data2 >> 8) & 0xff; + else + data2 = data2 & 0xff; + + p->es_pvid = ADM6996FC_PVIDBYDATA(data1, data2); + if (((data1 >> ADM6996FC_OPTE_SHIFT) & 0x01) == 1) + p->es_flags |= ETHERSWITCH_PORT_ADDTAG; + else + p->es_flags |= ETHERSWITCH_PORT_STRIPTAG; + } else { + p->es_pvid = 0; + } + + phy = sc->portphy[p->es_port]; + mii = adm6996fc_miiforport(sc, p->es_port); + if (sc->cpuport != -1 && phy == sc->cpuport) { + /* fill in fixed values for CPU port */ + p->es_flags |= ETHERSWITCH_PORT_CPU; + ifmr->ifm_count = 0; + if (sc->media == 100) + ifmr->ifm_current = ifmr->ifm_active = + IFM_ETHER | IFM_100_TX | IFM_FDX; + else + ifmr->ifm_current = ifmr->ifm_active = + IFM_ETHER | IFM_1000_T | IFM_FDX; + ifmr->ifm_mask = 0; + ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; + } else if (mii != NULL) { + err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, + &mii->mii_media, SIOCGIFMEDIA); + if (err) + return (err); + } else { + return (ENXIO); + } + return (0); +} + +static int +adm6996fc_setport(device_t dev, etherswitch_port_t *p) +{ + struct adm6996fc_softc *sc; + struct ifmedia *ifm; + struct mii_data *mii; + struct ifnet *ifp; + device_t parent; + int err; + int data; + + int bcaddr[6] = {0x01, 0x03, 0x05, 0x07, 0x08, 0x09}; + int vidaddr[6] = {0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c}; + + sc = device_get_softc(dev); + parent = device_get_parent(dev); + + if (p->es_port < 0 || p->es_port >= sc->numports) + return (ENXIO); + + if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { + data = ADM6996FC_READREG(parent, bcaddr[p->es_port]); + data &= ~(0xf << 10); + data |= (p->es_pvid & 0xf) << ADM6996FC_PVID_SHIFT; + ADM6996FC_WRITEREG(parent, bcaddr[p->es_port], data); + data = ADM6996FC_READREG(parent, vidaddr[p->es_port]); + /* only port 4 is hi bit */ + if (p->es_port == 4) { + data &= ~(0xff << 8); + data = data | (((p->es_pvid >> 4) & 0xff) << 8); + } else { + data &= ~0xff; + data = data | ((p->es_pvid >> 4) & 0xff); + } + ADM6996FC_WRITEREG(parent, vidaddr[p->es_port], data); + err = 0; + } else { + if (sc->portphy[p->es_port] == sc->cpuport) + return (ENXIO); + } + + if (sc->portphy[p->es_port] != sc->cpuport) { + mii = adm6996fc_miiforport(sc, p->es_port); + if (mii == NULL) + return (ENXIO); + + ifp = adm6996fc_ifpforport(sc, p->es_port); + + ifm = &mii->mii_media; + err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA); + } + return (err); +} + +static int +adm6996fc_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) +{ + struct adm6996fc_softc *sc; + device_t parent; + int datahi, datalo; + + sc = device_get_softc(dev); + parent = device_get_parent(dev); + + if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { + if (vg->es_vlangroup <= 5) { + vg->es_vid = ETHERSWITCH_VID_VALID; + vg->es_vid |= vg->es_vlangroup; + datalo = ADM6996FC_READREG(parent, + ADM6996FC_VF0L + 2 * vg->es_vlangroup); + datahi = ADM6996FC_READREG(parent, + ADM6996FC_VF0H + 2 * vg->es_vlangroup); + + vg->es_member_ports = datalo & 0x3f; + vg->es_untagged_ports = vg->es_member_ports; + vg->es_fid = 0; + } else { + vg->es_vid = 0; + } + } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { + datalo = ADM6996FC_READREG(parent, + ADM6996FC_VF0L + 2 * vg->es_vlangroup); + datahi = ADM6996FC_READREG(parent, + ADM6996FC_VF0H + 2 * vg->es_vlangroup); + + if (datahi & (1 << ADM6996FC_VV_SHIFT)) { + vg->es_vid = ETHERSWITCH_VID_VALID; + vg->es_vid |= datahi & 0xfff; + vg->es_member_ports = datalo & 0x3f; + vg->es_untagged_ports = (~datalo >> 6) & 0x3f; + vg->es_fid = 0; + } else { + vg->es_fid = 0; + } + } else { + vg->es_fid = 0; + } + + return (0); +} + +static int +adm6996fc_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) +{ + struct adm6996fc_softc *sc; + device_t parent; + + sc = device_get_softc(dev); + parent = device_get_parent(dev); + + if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2 * vg->es_vlangroup, + vg->es_member_ports); + } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2 * vg->es_vlangroup, + vg->es_member_ports | ((~vg->es_untagged_ports & 0x3f)<< 6)); + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2 * vg->es_vlangroup, + (1 << ADM6996FC_VV_SHIFT) | vg->es_vid); + } + + return (0); +} + +static int +adm6996fc_getconf(device_t dev, etherswitch_conf_t *conf) +{ + struct adm6996fc_softc *sc; + + sc = device_get_softc(dev); + + /* Return the VLAN mode. */ + conf->cmd = ETHERSWITCH_CONF_VLAN_MODE; + conf->vlan_mode = sc->vlan_mode; + + return (0); +} + +static int +adm6996fc_setconf(device_t dev, etherswitch_conf_t *conf) +{ + struct adm6996fc_softc *sc; + device_t parent; + int i; + int data; + int bcaddr[6] = {0x01, 0x03, 0x05, 0x07, 0x08, 0x09}; + + sc = device_get_softc(dev); + parent = device_get_parent(dev); + + if ((conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) == 0) + return (0); + + if (conf->vlan_mode == ETHERSWITCH_VLAN_PORT) { + sc->vlan_mode = ETHERSWITCH_VLAN_PORT; + data = ADM6996FC_READREG(parent, ADM6996FC_SC3); + data &= ~(1 << ADM6996FC_TBV_SHIFT); + ADM6996FC_WRITEREG(parent, ADM6996FC_SC3, data); + for (i = 0;i <= 5; ++i) { + data = ADM6996FC_READREG(parent, bcaddr[i]); + data &= ~(0xf << 10); + data |= (i << 10); + ADM6996FC_WRITEREG(parent, bcaddr[i], data); + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2 * i, + 0x003f); + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2 * i, + (1 << ADM6996FC_VV_SHIFT) | 1); + } + } else if (conf->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { + sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q; + data = ADM6996FC_READREG(parent, ADM6996FC_SC3); + data |= (1 << ADM6996FC_TBV_SHIFT); + ADM6996FC_WRITEREG(parent, ADM6996FC_SC3, data); + for (i = 0;i <= 5; ++i) { + data = ADM6996FC_READREG(parent, bcaddr[i]); + /* Private VID set 1 */ + data &= ~(0xf << 10); + data |= (1 << 10); + /* Output Packet Tagging Enable */ + if (i == 5) + data |= (1 << 4); + ADM6996FC_WRITEREG(parent, bcaddr[i], data); + } + for (i = 2;i <= 15; ++i) { + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2 * i, + 0x0000); + } + } else { + /* + ADM6996FC have no VLAN off. Then set Port base and + add all port to member. Use VLAN Filter 1 is reset + default. + */ + sc->vlan_mode = 0; + data = ADM6996FC_READREG(parent, ADM6996FC_SC3); + data &= ~(1 << ADM6996FC_TBV_SHIFT); + ADM6996FC_WRITEREG(parent, ADM6996FC_SC3, data); + for (i = 0;i <= 5; ++i) { + data = ADM6996FC_READREG(parent, bcaddr[i]); + data &= ~(0xf << 10); + data |= (1 << 10); + if (i == 5) + data &= ~(1 << 4); + ADM6996FC_WRITEREG(parent, bcaddr[i], data); + } + /* default setting */ + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0L + 2, 0x003f); + ADM6996FC_WRITEREG(parent, ADM6996FC_VF0H + 2, + (1 << ADM6996FC_VV_SHIFT) | 1); + } + + + return (0); +} + +static void +adm6996fc_statchg(device_t dev) +{ + + DPRINTF(dev, "%s\n", __func__); +} + +static int +adm6996fc_ifmedia_upd(struct ifnet *ifp) +{ + struct adm6996fc_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = adm6996fc_miiforport(sc, ifp->if_dunit); + + DPRINTF(sc->sc_dev, "%s\n", __func__); + if (mii == NULL) + return (ENXIO); + mii_mediachg(mii); + return (0); +} + +static void +adm6996fc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct adm6996fc_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = adm6996fc_miiforport(sc, ifp->if_dunit); + + DPRINTF(sc->sc_dev, "%s\n", __func__); + + if (mii == NULL) + return; + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; +} + +static int +adm6996fc_readphy(device_t dev, int phy, int reg) +{ + struct adm6996fc_softc *sc; + int data; + + sc = device_get_softc(dev); + ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED); + + if (phy < 0 || phy >= 32) + return (ENXIO); + if (reg < 0 || reg >= 32) + return (ENXIO); + + ADM6996FC_LOCK(sc); + data = ADM6996FC_READREG(device_get_parent(dev), + (ADM6996FC_PHY_C0 + ADM6996FC_PHY_SIZE * phy) + reg); + ADM6996FC_UNLOCK(sc); + + return (data); +} + +static int +adm6996fc_writephy(device_t dev, int phy, int reg, int data) +{ + struct adm6996fc_softc *sc; + int err; + + sc = device_get_softc(dev); + ADM6996FC_LOCK_ASSERT(sc, MA_NOTOWNED); + + if (phy < 0 || phy >= 32) + return (ENXIO); + if (reg < 0 || reg >= 32) + return (ENXIO); + + ADM6996FC_LOCK(sc); + err = ADM6996FC_WRITEREG(device_get_parent(dev), + (ADM6996FC_PHY_C0 + ADM6996FC_PHY_SIZE * phy) + reg, data); + ADM6996FC_UNLOCK(sc); + + return (err); +} + +static int +adm6996fc_readreg(device_t dev, int addr) +{ + + return ADM6996FC_READREG(device_get_parent(dev), addr); +} + +static int +adm6996fc_writereg(device_t dev, int addr, int value) +{ + int err; + + err = ADM6996FC_WRITEREG(device_get_parent(dev), addr, value); + return (err); +} + +static device_method_t adm6996fc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, adm6996fc_probe), + DEVMETHOD(device_attach, adm6996fc_attach), + DEVMETHOD(device_detach, adm6996fc_detach), + + /* bus interface */ + DEVMETHOD(bus_add_child, device_add_child_ordered), + + /* MII interface */ + DEVMETHOD(miibus_readreg, adm6996fc_readphy), + DEVMETHOD(miibus_writereg, adm6996fc_writephy), + DEVMETHOD(miibus_statchg, adm6996fc_statchg), + + /* MDIO interface */ + DEVMETHOD(mdio_readreg, adm6996fc_readphy), + DEVMETHOD(mdio_writereg, adm6996fc_writephy), + + /* etherswitch interface */ + DEVMETHOD(etherswitch_lock, adm6996fc_lock), + DEVMETHOD(etherswitch_unlock, adm6996fc_unlock), + DEVMETHOD(etherswitch_getinfo, adm6996fc_getinfo), + DEVMETHOD(etherswitch_readreg, adm6996fc_readreg), + DEVMETHOD(etherswitch_writereg, adm6996fc_writereg), + DEVMETHOD(etherswitch_readphyreg, adm6996fc_readphy), + DEVMETHOD(etherswitch_writephyreg, adm6996fc_writephy), + DEVMETHOD(etherswitch_getport, adm6996fc_getport), + DEVMETHOD(etherswitch_setport, adm6996fc_setport), + DEVMETHOD(etherswitch_getvgroup, adm6996fc_getvgroup), + DEVMETHOD(etherswitch_setvgroup, adm6996fc_setvgroup), + DEVMETHOD(etherswitch_setconf, adm6996fc_setconf), + DEVMETHOD(etherswitch_getconf, adm6996fc_getconf), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(adm6996fc, adm6996fc_driver, adm6996fc_methods, + sizeof(struct adm6996fc_softc)); +static devclass_t adm6996fc_devclass; + +DRIVER_MODULE(adm6996fc, mdio, adm6996fc_driver, adm6996fc_devclass, 0, 0); +DRIVER_MODULE(miibus, adm6996fc, miibus_driver, miibus_devclass, 0, 0); +DRIVER_MODULE(mdio, adm6996fc, mdio_driver, mdio_devclass, 0, 0); +DRIVER_MODULE(etherswitch, adm6996fc, etherswitch_driver, etherswitch_devclass, + 0, 0); +MODULE_VERSION(adm6996fc, 1); +MODULE_DEPEND(adm6996fc, miibus, 1, 1, 1); /* XXX which versions? */ +MODULE_DEPEND(adm6996fc, etherswitch, 1, 1, 1); /* XXX which versions? */ diff --git a/sys/dev/etherswitch/ip17x/ip175c.c b/sys/dev/etherswitch/ip17x/ip175c.c index 30614a42417..c87543bc5b1 100644 --- a/sys/dev/etherswitch/ip17x/ip175c.c +++ b/sys/dev/etherswitch/ip17x/ip175c.c @@ -234,6 +234,13 @@ ip175c_get_vlan_mode(struct ip17x_softc *sc) void ip175c_attach(struct ip17x_softc *sc) { + uint32_t data; + + data = ip17x_readphy(sc->sc_dev, IP175C_MII_PHY, IP175C_MII_CTL_REG); + device_printf(sc->sc_dev, "MII: %x\n", data); + /* check mii1 interface if disabled then phy4 and mac4 hold on switch */ + if((data & (1 << IP175C_MII_MII1_RMII_EN)) == 0) + sc->phymask |= 0x10; sc->hal.ip17x_reset = ip175c_reset; sc->hal.ip17x_hw_setup = ip175c_hw_setup; diff --git a/sys/dev/etherswitch/ip17x/ip175c.h b/sys/dev/etherswitch/ip17x/ip175c.h index 8abb4b69619..2b9e05665d2 100644 --- a/sys/dev/etherswitch/ip17x/ip175c.h +++ b/sys/dev/etherswitch/ip17x/ip175c.h @@ -35,6 +35,9 @@ #define IP175C_MODE_REG 31 #define IP175C_RESET_PHY 30 #define IP175C_RESET_REG 0 +#define IP175C_MII_PHY 31 +#define IP175C_MII_CTL_REG 5 +#define IP175C_MII_MII1_RMII_EN 8 #define IP175C_LAST_VLAN 15 diff --git a/sys/dev/etherswitch/rtl8366/rtl8366rb.c b/sys/dev/etherswitch/rtl8366/rtl8366rb.c index d14f4660130..6e990d97996 100644 --- a/sys/dev/etherswitch/rtl8366/rtl8366rb.c +++ b/sys/dev/etherswitch/rtl8366/rtl8366rb.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2015-2016 Hiroki Mori. * Copyright (c) 2011-2012 Stefan Bethke. * All rights reserved. * @@ -26,6 +27,8 @@ * $FreeBSD$ */ +#include "opt_etherswitch.h" + #include #include #include @@ -65,18 +68,13 @@ struct rtl8366rb_softc { int smi_acquired; /* serialize access to SMI/I2C bus */ struct mtx callout_mtx; /* serialize callout */ device_t dev; - int vid[RTL8366RB_NUM_VLANS]; - char *ifname[RTL8366RB_NUM_PHYS]; - device_t miibus[RTL8366RB_NUM_PHYS]; - struct ifnet *ifp[RTL8366RB_NUM_PHYS]; + int vid[RTL8366_NUM_VLANS]; + char *ifname[RTL8366_NUM_PHYS]; + device_t miibus[RTL8366_NUM_PHYS]; + struct ifnet *ifp[RTL8366_NUM_PHYS]; struct callout callout_tick; -}; - -static etherswitch_info_t etherswitch_info = { - .es_nports = RTL8366RB_NUM_PORTS, - .es_nvlangroups = RTL8366RB_NUM_VLANS, - .es_name = "Realtek RTL8366RB", - .es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q, + etherswitch_info_t info; + int chip_type; /* 0 = RTL8366RB, 1 = RTL8366SR */ }; #define RTL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) @@ -133,77 +131,101 @@ rtl8366rb_identify(driver_t *driver, device_t parent) if (device_find_child(parent, "rtl8366rb", -1) == NULL) { child = BUS_ADD_CHILD(parent, 0, "rtl8366rb", -1); devi = IICBUS_IVAR(child); - devi->addr = RTL8366RB_IIC_ADDR; + devi->addr = RTL8366_IIC_ADDR; } } static int rtl8366rb_probe(device_t dev) { + struct rtl8366rb_softc *sc; + + sc = device_get_softc(dev); + + bzero(sc, sizeof(*sc)); if (smi_probe(dev) != 0) return (ENXIO); - device_set_desc(dev, "RTL8366RB Ethernet Switch Controller"); + if(sc->chip_type == 0) + device_set_desc(dev, "RTL8366RB Ethernet Switch Controller"); + else + device_set_desc(dev, "RTL8366SR Ethernet Switch Controller"); return (BUS_PROBE_DEFAULT); } static void rtl8366rb_init(device_t dev) { - int i; struct rtl8366rb_softc *sc; + int i; + + sc = device_get_softc(dev); /* Initialisation for TL-WR1043ND */ - smi_rmw(dev, RTL8366RB_RCR, - RTL8366RB_RCR_HARD_RESET, - RTL8366RB_RCR_HARD_RESET, RTL_WAITOK); +#ifdef RTL8366_SOFT_RESET + smi_rmw(dev, RTL8366_RCR, + RTL8366_RCR_SOFT_RESET, + RTL8366_RCR_SOFT_RESET, RTL_WAITOK); +#else + smi_rmw(dev, RTL8366_RCR, + RTL8366_RCR_HARD_RESET, + RTL8366_RCR_HARD_RESET, RTL_WAITOK); +#endif + /* hard reset not return ack */ DELAY(100000); /* Enable 16 VLAN mode */ - smi_rmw(dev, RTL8366RB_SGCR, - RTL8366RB_SGCR_EN_VLAN | RTL8366RB_SGCR_EN_VLAN_4KTB, - RTL8366RB_SGCR_EN_VLAN, RTL_WAITOK); + smi_rmw(dev, RTL8366_SGCR, + RTL8366_SGCR_EN_VLAN | RTL8366_SGCR_EN_VLAN_4KTB, + RTL8366_SGCR_EN_VLAN, RTL_WAITOK); /* Initialize our vlan table. */ - sc = device_get_softc(dev); for (i = 0; i <= 1; i++) sc->vid[i] = (i + 1) | ETHERSWITCH_VID_VALID; /* Remove port 0 from VLAN 1. */ - smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 0), + smi_rmw(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, 0), (1 << 0), 0, RTL_WAITOK); /* Add port 0 untagged and port 5 tagged to VLAN 2. */ - smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 1), - ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT) - | ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT), - ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT - | ((1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT)), + smi_rmw(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, 1), + ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_MEMBER_SHIFT) + | ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_UNTAG_SHIFT), + ((1 << 5 | 1 << 0) << RTL8366_VMCR_MU_MEMBER_SHIFT + | ((1 << 0) << RTL8366_VMCR_MU_UNTAG_SHIFT)), RTL_WAITOK); /* Set PVID 2 for port 0. */ - smi_rmw(dev, RTL8366RB_PVCR_REG(0), - RTL8366RB_PVCR_VAL(0, RTL8366RB_PVCR_PORT_MASK), - RTL8366RB_PVCR_VAL(0, 1), RTL_WAITOK); + smi_rmw(dev, RTL8366_PVCR_REG(0), + RTL8366_PVCR_VAL(0, RTL8366_PVCR_PORT_MASK), + RTL8366_PVCR_VAL(0, 1), RTL_WAITOK); } static int rtl8366rb_attach(device_t dev) { - uint16_t rev = 0; struct rtl8366rb_softc *sc; + uint16_t rev = 0; char name[IFNAMSIZ]; int err = 0; int i; sc = device_get_softc(dev); - bzero(sc, sizeof(*sc)); + sc->dev = dev; mtx_init(&sc->sc_mtx, "rtl8366rb", NULL, MTX_DEF); sc->smi_acquired = 0; mtx_init(&sc->callout_mtx, "rtl8366rbcallout", NULL, MTX_DEF); rtl8366rb_init(dev); - smi_read(dev, RTL8366RB_CVCR, &rev, RTL_WAITOK); + smi_read(dev, RTL8366_CVCR, &rev, RTL_WAITOK); device_printf(dev, "rev. %d\n", rev & 0x000f); + sc->info.es_nports = RTL8366_NUM_PORTS; + sc->info.es_nvlangroups = RTL8366_NUM_VLANS; + sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q; + if(sc->chip_type == 0) + sprintf(sc->info.es_name, "Realtek RTL8366RB"); + else + sprintf(sc->info.es_name, "Realtek RTL8366SR"); + /* attach miibus and phys */ /* PHYs need an interface, so we generate a dummy one */ - for (i = 0; i < RTL8366RB_NUM_PHYS; i++) { + for (i = 0; i < RTL8366_NUM_PHYS; i++) { sc->ifp[i] = if_alloc(IFT_ETHER); sc->ifp[i]->if_softc = sc; sc->ifp[i]->if_flags |= IFF_UP | IFF_BROADCAST | IFF_DRV_RUNNING @@ -236,10 +258,12 @@ rtl8366rb_attach(device_t dev) static int rtl8366rb_detach(device_t dev) { - struct rtl8366rb_softc *sc = device_get_softc(dev); + struct rtl8366rb_softc *sc; int i; - for (i=0; i < RTL8366RB_NUM_PHYS; i++) { + sc = device_get_softc(dev); + + for (i=0; i < RTL8366_NUM_PHYS; i++) { if (sc->miibus[i]) device_delete_child(dev, sc->miibus[i]); if (sc->ifp[i] != NULL) @@ -259,30 +283,30 @@ rtl8366rb_update_ifmedia(int portstatus, u_int *media_status, u_int *media_activ { *media_active = IFM_ETHER; *media_status = IFM_AVALID; - if ((portstatus & RTL8366RB_PLSR_LINK) != 0) + if ((portstatus & RTL8366_PLSR_LINK) != 0) *media_status |= IFM_ACTIVE; else { *media_active |= IFM_NONE; return; } - switch (portstatus & RTL8366RB_PLSR_SPEED_MASK) { - case RTL8366RB_PLSR_SPEED_10: + switch (portstatus & RTL8366_PLSR_SPEED_MASK) { + case RTL8366_PLSR_SPEED_10: *media_active |= IFM_10_T; break; - case RTL8366RB_PLSR_SPEED_100: + case RTL8366_PLSR_SPEED_100: *media_active |= IFM_100_TX; break; - case RTL8366RB_PLSR_SPEED_1000: + case RTL8366_PLSR_SPEED_1000: *media_active |= IFM_1000_T; break; } - if ((portstatus & RTL8366RB_PLSR_FULLDUPLEX) != 0) + if ((portstatus & RTL8366_PLSR_FULLDUPLEX) != 0) *media_active |= IFM_FDX; else *media_active |= IFM_HDX; - if ((portstatus & RTL8366RB_PLSR_TXPAUSE) != 0) + if ((portstatus & RTL8366_PLSR_TXPAUSE) != 0) *media_active |= IFM_ETH_TXPAUSE; - if ((portstatus & RTL8366RB_PLSR_RXPAUSE) != 0) + if ((portstatus & RTL8366_PLSR_RXPAUSE) != 0) *media_active |= IFM_ETH_RXPAUSE; } @@ -295,10 +319,10 @@ rtl833rb_miipollstat(struct rtl8366rb_softc *sc) uint16_t value; int portstatus; - for (i = 0; i < RTL8366RB_NUM_PHYS; i++) { + for (i = 0; i < RTL8366_NUM_PHYS; i++) { mii = device_get_softc(sc->miibus[i]); if ((i % 2) == 0) { - if (smi_read(sc->dev, RTL8366RB_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) { + if (smi_read(sc->dev, RTL8366_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) { DEBUG_INCRVAR(callout_blocked); return; } @@ -318,7 +342,9 @@ rtl833rb_miipollstat(struct rtl8366rb_softc *sc) static void rtl8366rb_tick(void *arg) { - struct rtl8366rb_softc *sc = arg; + struct rtl8366rb_softc *sc; + + sc = arg; rtl833rb_miipollstat(sc); callout_reset(&sc->callout_tick, hz, rtl8366rb_tick, sc); @@ -327,39 +353,65 @@ rtl8366rb_tick(void *arg) static int smi_probe(device_t dev) { + struct rtl8366rb_softc *sc; device_t iicbus, iicha; - int err, i; + int err, i, j; uint16_t chipid; char bytes[2]; int xferd; - bytes[0] = RTL8366RB_CIR & 0xff; - bytes[1] = (RTL8366RB_CIR >> 8) & 0xff; + sc = device_get_softc(dev); + iicbus = device_get_parent(dev); iicha = device_get_parent(iicbus); - iicbus_reset(iicbus, IIC_FASTEST, RTL8366RB_IIC_ADDR, NULL); - for (i=3; i--; ) { - IICBUS_STOP(iicha); - /* - * we go directly to the host adapter because iicbus.c - * only issues a stop on a bus that was successfully started. - */ + + for(i = 0; i < 2; ++i) { + iicbus_reset(iicbus, IIC_FASTEST, RTL8366_IIC_ADDR, NULL); + for (j=3; j--; ) { + IICBUS_STOP(iicha); + /* + * we go directly to the host adapter because iicbus.c + * only issues a stop on a bus that was successfully started. + */ + } + err = iicbus_request_bus(iicbus, dev, IIC_WAIT); + if (err != 0) + goto out; + err = iicbus_start(iicbus, RTL8366_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT); + if (err != 0) + goto out; + if(i == 0) { + bytes[0] = RTL8366RB_CIR & 0xff; + bytes[1] = (RTL8366RB_CIR >> 8) & 0xff; + } else { + bytes[0] = RTL8366SR_CIR & 0xff; + bytes[1] = (RTL8366SR_CIR >> 8) & 0xff; + } + err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT); + if (err != 0) + goto out; + err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0); + if (err != 0) + goto out; + chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff); + if (i == 0 && chipid == RTL8366RB_CIR_ID8366RB) { + DPRINTF(dev, "chip id 0x%04x\n", chipid); + sc->chip_type = 0; + err = 0; + break; + } + if (i == 1 && chipid == RTL8366SR_CIR_ID8366SR) { + DPRINTF(dev, "chip id 0x%04x\n", chipid); + sc->chip_type = 1; + err = 0; + break; + } + if(i == 0) { + iicbus_stop(iicbus); + iicbus_release_bus(iicbus, dev); + } } - err = iicbus_request_bus(iicbus, dev, IIC_WAIT); - if (err != 0) - goto out; - err = iicbus_start(iicbus, RTL8366RB_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT); - if (err != 0) - goto out; - err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT); - if (err != 0) - goto out; - err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0); - if (err != 0) - goto out; - chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff); - DPRINTF(dev, "chip id 0x%04x\n", chipid); - if (chipid != RTL8366RB_CIR_ID8366RB) + if(i == 2) err = ENXIO; out: iicbus_stop(iicbus); @@ -406,12 +458,25 @@ smi_release(struct rtl8366rb_softc *sc, int sleep) static int smi_select(device_t dev, int op, int sleep) { + struct rtl8366rb_softc *sc; int err, i; - device_t iicbus = device_get_parent(dev); - struct iicbus_ivar *devi = IICBUS_IVAR(dev); - int slave = devi->addr; + device_t iicbus; + struct iicbus_ivar *devi; + int slave; + + sc = device_get_softc(dev); + + iicbus = device_get_parent(dev); + devi = IICBUS_IVAR(dev); + slave = devi->addr; RTL_SMI_ACQUIRED_ASSERT((struct rtl8366rb_softc *)device_get_softc(dev)); + + if(sc->chip_type == 1) { // RTL8366SR work around + // this is same work around at probe + for (int i=3; i--; ) + IICBUS_STOP(device_get_parent(device_get_parent(dev))); + } /* * The chip does not use clock stretching when it is busy, * instead ignoring the command. Retry a few times. @@ -433,10 +498,12 @@ static int smi_read_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t *data, int sleep) { int err; - device_t iicbus = device_get_parent(sc->dev); + device_t iicbus; char bytes[2]; int xferd; + iicbus = device_get_parent(sc->dev); + RTL_SMI_ACQUIRED_ASSERT(sc); bytes[0] = addr & 0xff; bytes[1] = (addr >> 8) & 0xff; @@ -460,10 +527,12 @@ static int smi_write_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t data, int sleep) { int err; - device_t iicbus = device_get_parent(sc->dev); + device_t iicbus; char bytes[4]; int xferd; + iicbus = device_get_parent(sc->dev); + RTL_SMI_ACQUIRED_ASSERT(sc); bytes[0] = addr & 0xff; bytes[1] = (addr >> 8) & 0xff; @@ -481,9 +550,11 @@ smi_write_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t data, int s static int smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep) { - struct rtl8366rb_softc *sc = device_get_softc(dev); + struct rtl8366rb_softc *sc; int err; + sc = device_get_softc(dev); + err = smi_acquire(sc, sleep); if (err != 0) return (EBUSY); @@ -496,9 +567,11 @@ smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep) static int smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep) { - struct rtl8366rb_softc *sc = device_get_softc(dev); + struct rtl8366rb_softc *sc; int err; + sc = device_get_softc(dev); + err = smi_acquire(sc, sleep); if (err != 0) return (EBUSY); @@ -511,10 +584,12 @@ smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep) static int smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep) { - struct rtl8366rb_softc *sc = device_get_softc(dev); + struct rtl8366rb_softc *sc; int err; uint16_t oldv, newv; + sc = device_get_softc(dev); + err = smi_acquire(sc, sleep); if (err != 0) return (EBUSY); @@ -535,13 +610,19 @@ smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep) static etherswitch_info_t * rtl_getinfo(device_t dev) { - return (ðerswitch_info); + struct rtl8366rb_softc *sc; + + sc = device_get_softc(dev); + + return (&sc->info); } static int rtl_readreg(device_t dev, int reg) { - uint16_t data = 0; + uint16_t data; + + data = 0; smi_read(dev, reg, &data, RTL_WAITOK); return (data); @@ -559,18 +640,21 @@ rtl_getport(device_t dev, etherswitch_port_t *p) struct rtl8366rb_softc *sc; struct ifmedia *ifm; struct mii_data *mii; - struct ifmediareq *ifmr = &p->es_ifmr; + struct ifmediareq *ifmr; uint16_t v; int err, vlangroup; - if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PORTS) - return (ENXIO); sc = device_get_softc(dev); - vlangroup = RTL8366RB_PVCR_GET(p->es_port, - rtl_readreg(dev, RTL8366RB_PVCR_REG(p->es_port))); + + ifmr = &p->es_ifmr; + + if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS) + return (ENXIO); + vlangroup = RTL8366_PVCR_GET(p->es_port, + rtl_readreg(dev, RTL8366_PVCR_REG(p->es_port))); p->es_pvid = sc->vid[vlangroup] & ETHERSWITCH_VID_MASK; - if (p->es_port < RTL8366RB_NUM_PHYS) { + if (p->es_port < RTL8366_NUM_PHYS) { mii = device_get_softc(sc->miibus[p->es_port]); ifm = &mii->mii_media; err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCGIFMEDIA); @@ -579,8 +663,8 @@ rtl_getport(device_t dev, etherswitch_port_t *p) } else { /* fill in fixed values for CPU port */ p->es_flags |= ETHERSWITCH_PORT_CPU; - smi_read(dev, RTL8366RB_PLSR_BASE + (RTL8366RB_NUM_PHYS)/2, &v, RTL_WAITOK); - v = v >> (8 * ((RTL8366RB_NUM_PHYS) % 2)); + smi_read(dev, RTL8366_PLSR_BASE + (RTL8366_NUM_PHYS)/2, &v, RTL_WAITOK); + v = v >> (8 * ((RTL8366_NUM_PHYS) % 2)); rtl8366rb_update_ifmedia(v, &ifmr->ifm_status, &ifmr->ifm_active); ifmr->ifm_current = ifmr->ifm_active; ifmr->ifm_mask = 0; @@ -599,16 +683,17 @@ rtl_getport(device_t dev, etherswitch_port_t *p) static int rtl_setport(device_t dev, etherswitch_port_t *p) { - int i, err, vlangroup; struct rtl8366rb_softc *sc; + int i, err, vlangroup; struct ifmedia *ifm; struct mii_data *mii; - if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PORTS) - return (ENXIO); sc = device_get_softc(dev); + + if (p->es_port < 0 || p->es_port >= RTL8366_NUM_PORTS) + return (ENXIO); vlangroup = -1; - for (i = 0; i < RTL8366RB_NUM_VLANS; i++) { + for (i = 0; i < RTL8366_NUM_VLANS; i++) { if ((sc->vid[i] & ETHERSWITCH_VID_MASK) == p->es_pvid) { vlangroup = i; break; @@ -616,12 +701,12 @@ rtl_setport(device_t dev, etherswitch_port_t *p) } if (vlangroup == -1) return (ENXIO); - err = smi_rmw(dev, RTL8366RB_PVCR_REG(p->es_port), - RTL8366RB_PVCR_VAL(p->es_port, RTL8366RB_PVCR_PORT_MASK), - RTL8366RB_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK); + err = smi_rmw(dev, RTL8366_PVCR_REG(p->es_port), + RTL8366_PVCR_VAL(p->es_port, RTL8366_PVCR_PORT_MASK), + RTL8366_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK); if (err) return (err); - if (p->es_port == RTL8366RB_CPU_PORT) + if (p->es_port == RTL8366_CPU_PORT) return (0); mii = device_get_softc(sc->miibus[p->es_port]); ifm = &mii->mii_media; @@ -636,14 +721,15 @@ rtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) uint16_t vmcr[3]; int i; - for (i=0; i<3; i++) - vmcr[i] = rtl_readreg(dev, RTL8366RB_VMCR(i, vg->es_vlangroup)); - sc = device_get_softc(dev); + + for (i=0; ies_vlangroup)); + vg->es_vid = sc->vid[vg->es_vlangroup]; - vg->es_member_ports = RTL8366RB_VMCR_MEMBER(vmcr); - vg->es_untagged_ports = RTL8366RB_VMCR_UNTAG(vmcr); - vg->es_fid = RTL8366RB_VMCR_FID(vmcr); + vg->es_member_ports = RTL8366_VMCR_MEMBER(vmcr); + vg->es_untagged_ports = RTL8366_VMCR_UNTAG(vmcr); + vg->es_fid = RTL8366_VMCR_FID(vmcr); return (0); } @@ -651,21 +737,31 @@ static int rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) { struct rtl8366rb_softc *sc; - int g = vg->es_vlangroup; + int g; sc = device_get_softc(dev); + + g = vg->es_vlangroup; + sc->vid[g] = vg->es_vid; /* VLAN group disabled ? */ if (vg->es_member_ports == 0 && vg->es_untagged_ports == 0 && vg->es_vid == 0) return (0); sc->vid[g] |= ETHERSWITCH_VID_VALID; - rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_DOT1Q_REG, g), - (vg->es_vid << RTL8366RB_VMCR_DOT1Q_VID_SHIFT) & RTL8366RB_VMCR_DOT1Q_VID_MASK); - rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, g), - ((vg->es_member_ports << RTL8366RB_VMCR_MU_MEMBER_SHIFT) & RTL8366RB_VMCR_MU_MEMBER_MASK) | - ((vg->es_untagged_ports << RTL8366RB_VMCR_MU_UNTAG_SHIFT) & RTL8366RB_VMCR_MU_UNTAG_MASK)); - rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_FID_REG, g), - vg->es_fid); + rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_DOT1Q_REG, g), + (vg->es_vid << RTL8366_VMCR_DOT1Q_VID_SHIFT) & RTL8366_VMCR_DOT1Q_VID_MASK); + if(sc->chip_type == 0) { + rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g), + ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | + ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK)); + rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_FID_REG, g), + vg->es_fid); + } else { + rtl_writereg(dev, RTL8366_VMCR(RTL8366_VMCR_MU_REG, g), + ((vg->es_member_ports << RTL8366_VMCR_MU_MEMBER_SHIFT) & RTL8366_VMCR_MU_MEMBER_MASK) | + ((vg->es_untagged_ports << RTL8366_VMCR_MU_UNTAG_SHIFT) & RTL8366_VMCR_MU_UNTAG_MASK) | + ((vg->es_fid << RTL8366_VMCR_FID_FID_SHIFT) & RTL8366_VMCR_FID_FID_MASK)); + } return (0); } @@ -683,24 +779,28 @@ rtl_getconf(device_t dev, etherswitch_conf_t *conf) static int rtl_readphy(device_t dev, int phy, int reg) { - struct rtl8366rb_softc *sc = device_get_softc(dev); - uint16_t data = 0; + struct rtl8366rb_softc *sc; + uint16_t data; int err, i, sleep; - if (phy < 0 || phy >= RTL8366RB_NUM_PHYS) + sc = device_get_softc(dev); + + data = 0; + + if (phy < 0 || phy >= RTL8366_NUM_PHYS) return (ENXIO); - if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG) + if (reg < 0 || reg >= RTL8366_NUM_PHY_REG) return (ENXIO); sleep = RTL_WAITOK; err = smi_acquire(sc, sleep); if (err != 0) return (EBUSY); for (i = RTL_IICBUS_RETRIES; i--; ) { - err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_READ, sleep); + err = smi_write_locked(sc, RTL8366_PACR, RTL8366_PACR_READ, sleep); if (err == 0) - err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), 0, sleep); + err = smi_write_locked(sc, RTL8366_PHYREG(phy, 0, reg), 0, sleep); if (err == 0) { - err = smi_read_locked(sc, RTL8366RB_PADR, &data, sleep); + err = smi_read_locked(sc, RTL8366_PADR, &data, sleep); break; } DEBUG_INCRVAR(phy_access_retries); @@ -715,21 +815,23 @@ rtl_readphy(device_t dev, int phy, int reg) static int rtl_writephy(device_t dev, int phy, int reg, int data) { - struct rtl8366rb_softc *sc = device_get_softc(dev); + struct rtl8366rb_softc *sc; int err, i, sleep; - if (phy < 0 || phy >= RTL8366RB_NUM_PHYS) + sc = device_get_softc(dev); + + if (phy < 0 || phy >= RTL8366_NUM_PHYS) return (ENXIO); - if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG) + if (reg < 0 || reg >= RTL8366_NUM_PHY_REG) return (ENXIO); sleep = RTL_WAITOK; err = smi_acquire(sc, sleep); if (err != 0) return (EBUSY); for (i = RTL_IICBUS_RETRIES; i--; ) { - err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_WRITE, sleep); + err = smi_write_locked(sc, RTL8366_PACR, RTL8366_PACR_WRITE, sleep); if (err == 0) - err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), data, sleep); + err = smi_write_locked(sc, RTL8366_PHYREG(phy, 0, reg), data, sleep); if (err == 0) { break; } @@ -745,8 +847,11 @@ rtl_writephy(device_t dev, int phy, int reg, int data) static int rtl8366rb_ifmedia_upd(struct ifnet *ifp) { - struct rtl8366rb_softc *sc = ifp->if_softc; - struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]); + struct rtl8366rb_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = device_get_softc(sc->miibus[ifp->if_dunit]); mii_mediachg(mii); return (0); @@ -755,8 +860,11 @@ rtl8366rb_ifmedia_upd(struct ifnet *ifp) static void rtl8366rb_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) { - struct rtl8366rb_softc *sc = ifp->if_softc; - struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]); + struct rtl8366rb_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = device_get_softc(sc->miibus[ifp->if_dunit]); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; diff --git a/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h b/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h index 09037059264..66ca0ad245e 100644 --- a/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h +++ b/sys/dev/etherswitch/rtl8366/rtl8366rbvar.h @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2015-2016 Hiroki Mori. * Copyright (c) 2011-2012 Stefan Bethke. * All rights reserved. * @@ -29,7 +30,7 @@ #ifndef _DEV_ETHERSWITCH_RTL8366RBVAR_H_ #define _DEV_ETHERSWITCH_RTL8366RBVAR_H_ -#define RTL8366RB_IIC_ADDR 0xa8 +#define RTL8366_IIC_ADDR 0xa8 #define RTL_IICBUS_TIMEOUT 100 /* us */ #define RTL_IICBUS_READ 1 #define RTL_IICBUS_WRITE 0 @@ -40,138 +41,142 @@ /* Register definitions */ /* Switch Global Configuration */ -#define RTL8366RB_SGCR 0x0000 -#define RTL8366RB_SGCR_EN_BC_STORM_CTRL 0x0001 -#define RTL8366RB_SGCR_MAX_LENGTH_MASK 0x0030 -#define RTL8366RB_SGCR_MAX_LENGTH_1522 0x0000 -#define RTL8366RB_SGCR_MAX_LENGTH_1536 0x0010 -#define RTL8366RB_SGCR_MAX_LENGTH_1552 0x0020 -#define RTL8366RB_SGCR_MAX_LENGTH_9216 0x0030 -#define RTL8366RB_SGCR_EN_VLAN 0x2000 -#define RTL8366RB_SGCR_EN_VLAN_4KTB 0x4000 -#define RTL8366RB_SGCR_EN_QOS 0x8000 +#define RTL8366_SGCR 0x0000 +#define RTL8366_SGCR_EN_BC_STORM_CTRL 0x0001 +#define RTL8366_SGCR_MAX_LENGTH_MASK 0x0030 +#define RTL8366_SGCR_MAX_LENGTH_1522 0x0000 +#define RTL8366_SGCR_MAX_LENGTH_1536 0x0010 +#define RTL8366_SGCR_MAX_LENGTH_1552 0x0020 +#define RTL8366_SGCR_MAX_LENGTH_9216 0x0030 +#define RTL8366_SGCR_EN_VLAN 0x2000 +#define RTL8366_SGCR_EN_VLAN_4KTB 0x4000 +#define RTL8366_SGCR_EN_QOS 0x8000 /* Port Enable Control: DISABLE_PORT[5:0] */ -#define RTL8366RB_PECR 0x0001 +#define RTL8366_PECR 0x0001 /* Switch Security Control 0: DIS_LEARN[5:0] */ -#define RTL8366RB_SSCR0 0x0002 +#define RTL8366_SSCR0 0x0002 /* Switch Security Control 1: DIS_AGE[5:0] */ -#define RTL8366RB_SSCR1 0x0003 +#define RTL8366_SSCR1 0x0003 /* Switch Security Control 2 */ -#define RTL8366RB_SSCR2 0x0004 -#define RTL8366RB_SSCR2_DROP_UNKNOWN_DA 0x0001 +#define RTL8366_SSCR2 0x0004 +#define RTL8366_SSCR2_DROP_UNKNOWN_DA 0x0001 /* Port Link Status: two ports per register */ -#define RTL8366RB_PLSR_BASE 0x0014 -#define RTL8366RB_PLSR_SPEED_MASK 0x03 -#define RTL8366RB_PLSR_SPEED_10 0x00 -#define RTL8366RB_PLSR_SPEED_100 0x01 -#define RTL8366RB_PLSR_SPEED_1000 0x02 -#define RTL8366RB_PLSR_FULLDUPLEX 0x04 -#define RTL8366RB_PLSR_LINK 0x10 -#define RTL8366RB_PLSR_TXPAUSE 0x20 -#define RTL8366RB_PLSR_RXPAUSE 0x40 -#define RTL8366RB_PLSR_NO_AUTO 0x80 +#define RTL8366_PLSR_BASE (sc->chip_type == 0 ? 0x0014 : 0x0060) +#define RTL8366_PLSR_SPEED_MASK 0x03 +#define RTL8366_PLSR_SPEED_10 0x00 +#define RTL8366_PLSR_SPEED_100 0x01 +#define RTL8366_PLSR_SPEED_1000 0x02 +#define RTL8366_PLSR_FULLDUPLEX 0x04 +#define RTL8366_PLSR_LINK 0x10 +#define RTL8366_PLSR_TXPAUSE 0x20 +#define RTL8366_PLSR_RXPAUSE 0x40 +#define RTL8366_PLSR_NO_AUTO 0x80 -/* VLAN Member Configuration, 3 registers per VLAN */ -#define RTL8366RB_VMCR_BASE 0x0020 -#define RTL8366RB_VMCR_MULT 3 -#define RTL8366RB_VMCR_DOT1Q_REG 0 -#define RTL8366RB_VMCR_DOT1Q_VID_SHIFT 0 -#define RTL8366RB_VMCR_DOT1Q_VID_MASK 0x0fff -#define RTL8366RB_VMCR_DOT1Q_PCP_SHIFT 12 -#define RTL8366RB_VMCR_DOT1Q_PCP_MASK 0x7000 -#define RTL8366RB_VMCR_MU_REG 1 -#define RTL8366RB_VMCR_MU_MEMBER_SHIFT 0 -#define RTL8366RB_VMCR_MU_MEMBER_MASK 0x00ff -#define RTL8366RB_VMCR_MU_UNTAG_SHIFT 8 -#define RTL8366RB_VMCR_MU_UNTAG_MASK 0xff00 -#define RTL8366RB_VMCR_FID_REG 2 -#define RTL8366RB_VMCR_FID_FID_SHIFT 0 -#define RTL8366RB_VMCR_FID_FID_MASK 0x0007 -#define RTL8366RB_VMCR(_reg, _vlan) \ - (RTL8366RB_VMCR_BASE + _reg + _vlan * RTL8366RB_VMCR_MULT) +/* VLAN Member Configuration, 3 or 2 registers per VLAN */ +#define RTL8366_VMCR_BASE (sc->chip_type == 0 ? 0x0020 : 0x0016) +#define RTL8366_VMCR_MULT (sc->chip_type == 0 ? 3 : 2) +#define RTL8366_VMCR_DOT1Q_REG 0 +#define RTL8366_VMCR_DOT1Q_VID_SHIFT 0 +#define RTL8366_VMCR_DOT1Q_VID_MASK 0x0fff +#define RTL8366_VMCR_DOT1Q_PCP_SHIFT 12 +#define RTL8366_VMCR_DOT1Q_PCP_MASK 0x7000 +#define RTL8366_VMCR_MU_REG 1 +#define RTL8366_VMCR_MU_MEMBER_SHIFT 0 +#define RTL8366_VMCR_MU_MEMBER_MASK (sc->chip_type == 0 ? 0x00ff : 0x003f) +#define RTL8366_VMCR_MU_UNTAG_SHIFT (sc->chip_type == 0 ? 8 : 6) +#define RTL8366_VMCR_MU_UNTAG_MASK (sc->chip_type == 0 ? 0xff00 : 0x0fc0) +#define RTL8366_VMCR_FID_REG (sc->chip_type == 0 ? 2 : 1) +#define RTL8366_VMCR_FID_FID_SHIFT (sc->chip_type == 0 ? 0 : 12) +#define RTL8366_VMCR_FID_FID_MASK (sc->chip_type == 0 ? 0x0007 : 0x7000) +#define RTL8366_VMCR(_reg, _vlan) \ + (RTL8366_VMCR_BASE + _reg + _vlan * RTL8366_VMCR_MULT) /* VLAN Identifier */ -#define RTL8366RB_VMCR_VID(_r) \ - (_r[RTL8366RB_VMCR_DOT1Q_REG] & RTL8366RB_VMCR_DOT1Q_VID_MASK) +#define RTL8366_VMCR_VID(_r) \ + (_r[RTL8366_VMCR_DOT1Q_REG] & RTL8366_VMCR_DOT1Q_VID_MASK) /* Priority Code Point */ -#define RTL8366RB_VMCR_PCP(_r) \ - ((_r[RTL8366RB_VMCR_DOT1Q_REG] & RTL8366RB_VMCR_DOT1Q_PCP_MASK) \ - >> RTL8366RB_VMCR_DOT1Q_PCP_SHIFT) +#define RTL8366_VMCR_PCP(_r) \ + ((_r[RTL8366_VMCR_DOT1Q_REG] & RTL8366_VMCR_DOT1Q_PCP_MASK) \ + >> RTL8366_VMCR_DOT1Q_PCP_SHIFT) /* Member ports */ -#define RTL8366RB_VMCR_MEMBER(_r) \ - (_r[RTL8366RB_VMCR_MU_REG] & RTL8366RB_VMCR_MU_MEMBER_MASK) +#define RTL8366_VMCR_MEMBER(_r) \ + (_r[RTL8366_VMCR_MU_REG] & RTL8366_VMCR_MU_MEMBER_MASK) /* Untagged ports */ -#define RTL8366RB_VMCR_UNTAG(_r) \ - ((_r[RTL8366RB_VMCR_MU_REG] & RTL8366RB_VMCR_MU_UNTAG_MASK) \ - >> RTL8366RB_VMCR_MU_UNTAG_SHIFT) +#define RTL8366_VMCR_UNTAG(_r) \ + ((_r[RTL8366_VMCR_MU_REG] & RTL8366_VMCR_MU_UNTAG_MASK) \ + >> RTL8366_VMCR_MU_UNTAG_SHIFT) /* Forwarding ID */ -#define RTL8366RB_VMCR_FID(_r) \ - (_r[RTL8366RB_VMCR_FID_REG] & RTL8366RB_VMCR_FID_FID_MASK) +#define RTL8366_VMCR_FID(_r) \ + (sc->chip_type == 0 ? (_r[RTL8366_VMCR_FID_REG] & RTL8366_VMCR_FID_FID_MASK) : \ + ((_r[RTL8366_VMCR_FID_REG] & RTL8366_VMCR_FID_FID_MASK) \ + >> RTL8366_VMCR_FID_FID_SHIFT)) /* * Port VLAN Control, 4 ports per register * Determines the VID for untagged ingress frames through * index into VMC. */ -#define RTL8366RB_PVCR_BASE 0x0063 -#define RTL8366RB_PVCR_PORT_SHIFT 4 -#define RTL8366RB_PVCR_PORT_PERREG (16 / RTL8366RB_PVCR_PORT_SHIFT) -#define RTL8366RB_PVCR_PORT_MASK 0x000f -#define RTL8366RB_PVCR_REG(_port) \ - (RTL8366RB_PVCR_BASE + _port / (RTL8366RB_PVCR_PORT_PERREG)) -#define RTL8366RB_PVCR_VAL(_port, _pvlan) \ - ((_pvlan & RTL8366RB_PVCR_PORT_MASK) << \ - ((_port % RTL8366RB_PVCR_PORT_PERREG) * RTL8366RB_PVCR_PORT_SHIFT)) -#define RTL8366RB_PVCR_GET(_port, _val) \ - (((_val) >> ((_port % RTL8366RB_PVCR_PORT_PERREG) * RTL8366RB_PVCR_PORT_SHIFT)) & RTL8366RB_PVCR_PORT_MASK) +#define RTL8366_PVCR_BASE (sc->chip_type == 0 ? 0x0063 : 0x0058) +#define RTL8366_PVCR_PORT_SHIFT 4 +#define RTL8366_PVCR_PORT_PERREG (16 / RTL8366_PVCR_PORT_SHIFT) +#define RTL8366_PVCR_PORT_MASK 0x000f +#define RTL8366_PVCR_REG(_port) \ + (RTL8366_PVCR_BASE + _port / (RTL8366_PVCR_PORT_PERREG)) +#define RTL8366_PVCR_VAL(_port, _pvlan) \ + ((_pvlan & RTL8366_PVCR_PORT_MASK) << \ + ((_port % RTL8366_PVCR_PORT_PERREG) * RTL8366_PVCR_PORT_SHIFT)) +#define RTL8366_PVCR_GET(_port, _val) \ + (((_val) >> ((_port % RTL8366_PVCR_PORT_PERREG) * RTL8366_PVCR_PORT_SHIFT)) & RTL8366_PVCR_PORT_MASK) /* Reset Control */ -#define RTL8366RB_RCR 0x0100 -#define RTL8366RB_RCR_HARD_RESET 0x0001 -#define RTL8366RB_RCR_SOFT_RESET 0x0002 +#define RTL8366_RCR 0x0100 +#define RTL8366_RCR_HARD_RESET 0x0001 +#define RTL8366_RCR_SOFT_RESET 0x0002 /* Chip Version Control: CHIP_VER[3:0] */ -#define RTL8366RB_CVCR 0x050A +#define RTL8366_CVCR (sc->chip_type == 0 ? 0x050A : 0x0104) /* Chip Identifier */ #define RTL8366RB_CIR 0x0509 #define RTL8366RB_CIR_ID8366RB 0x5937 +#define RTL8366SR_CIR 0x0105 +#define RTL8366SR_CIR_ID8366SR 0x8366 /* VLAN Ingress Control 2: [5:0] */ -#define RTL8366RB_VIC2R 0x037f +#define RTL8366_VIC2R 0x037f /* MIB registers */ -#define RTL8366RB_MCNT_BASE 0x1000 -#define RTL8366RB_MCTLR 0x13f0 -#define RTL8366RB_MCTLR_BUSY 0x0001 -#define RTL8366RB_MCTLR_RESET 0x0002 -#define RTL8366RB_MCTLR_RESET_PORT_MASK 0x00fc -#define RTL8366RB_MCTLR_RESET_ALL 0x0800 +#define RTL8366_MCNT_BASE 0x1000 +#define RTL8366_MCTLR (sc->chip_type == 0 ? 0x13f0 : 0x11F0) +#define RTL8366_MCTLR_BUSY 0x0001 +#define RTL8366_MCTLR_RESET 0x0002 +#define RTL8366_MCTLR_RESET_PORT_MASK 0x00fc +#define RTL8366_MCTLR_RESET_ALL 0x0800 -#define RTL8366RB_MCNT(_port, _r) \ - (RTL8366RB_MCNT_BASE + 0x50 * (_port) + (_r)) -#define RTL8366RB_MCTLR_RESET_PORT(_p) \ +#define RTL8366_MCNT(_port, _r) \ + (RTL8366_MCNT_BASE + 0x50 * (_port) + (_r)) +#define RTL8366_MCTLR_RESET_PORT(_p) \ (1 << ((_p) + 2)) /* PHY Access Control */ -#define RTL8366RB_PACR 0x8000 -#define RTL8366RB_PACR_WRITE 0x0000 -#define RTL8366RB_PACR_READ 0x0001 +#define RTL8366_PACR (sc->chip_type == 0 ? 0x8000 : 0x8028) +#define RTL8366_PACR_WRITE 0x0000 +#define RTL8366_PACR_READ 0x0001 /* PHY Access Data */ -#define RTL8366RB_PADR 0x8002 +#define RTL8366_PADR (sc->chip_type == 0 ? 0x8002 : 0x8029) -#define RTL8366RB_PHYREG(phy, page, reg) \ - (RTL8366RB_PACR | (1 << (((phy) & 0x1f) + 9)) | (((page) & 0xf) << 5) | ((reg) & 0x1f)) +#define RTL8366_PHYREG(phy, page, reg) \ + (0x8000 | (1 << (((phy) & 0x1f) + 9)) | (((page) & (sc->chip_type == 0 ? 0xf : 0x7)) << 5) | ((reg) & 0x1f)) /* general characteristics of the chip */ -#define RTL8366RB_CPU_PORT 5 -#define RTL8366RB_NUM_PORTS 6 -#define RTL8366RB_NUM_PHYS (RTL8366RB_NUM_PORTS-1) -#define RTL8366RB_NUM_VLANS 16 -#define RTL8366RB_NUM_PHY_REG 32 +#define RTL8366_CPU_PORT 5 +#define RTL8366_NUM_PORTS 6 +#define RTL8366_NUM_PHYS (RTL8366_NUM_PORTS-1) +#define RTL8366_NUM_VLANS 16 +#define RTL8366_NUM_PHY_REG 32 #endif diff --git a/sys/dev/fdt/fdt_arm_platform.c b/sys/dev/fdt/fdt_arm_platform.c index 22e935b146f..fe1f4046168 100644 --- a/sys/dev/fdt/fdt_arm_platform.c +++ b/sys/dev/fdt/fdt_arm_platform.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include "platform_if.h" @@ -58,7 +59,7 @@ fdt_platform_probe(platform_t plat) /* Is the device is compatible? */ root = OF_finddevice("/"); compat = FDT_PLATFORM(plat)->fdt_compatible; - if (fdt_is_compatible(root, compat) != 0) + if (ofw_bus_node_is_compatible(root, compat) != 0) return 0; /* Not compatible, return an error */ diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c index 2f4555f81a4..3e59fb97707 100644 --- a/sys/dev/fdt/fdt_common.c +++ b/sys/dev/fdt/fdt_common.c @@ -69,6 +69,8 @@ vm_offset_t fdt_immr_size; struct fdt_ic_list fdt_ic_list_head = SLIST_HEAD_INITIALIZER(fdt_ic_list_head); +static int fdt_is_compatible(phandle_t, const char *); + static int fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base, u_long *size) @@ -242,7 +244,7 @@ moveon: * Note the buffer has to be on the stack since malloc() is usually not * available in such cases either. */ -int +static int fdt_is_compatible(phandle_t node, const char *compatstr) { char buf[FDT_COMPAT_LEN]; @@ -419,13 +421,13 @@ fdt_addrsize_cells(phandle_t node, int *addr_cells, int *size_cells) * Retrieve #{address,size}-cells. */ cell_size = sizeof(cell); - if (OF_getprop(node, "#address-cells", &cell, cell_size) < cell_size) - cell = 2; - *addr_cells = fdt32_to_cpu((int)cell); + if (OF_getencprop(node, "#address-cells", &cell, cell_size) < cell_size) + *addr_cells = 2; + *addr_cells = (int)cell; - if (OF_getprop(node, "#size-cells", &cell, cell_size) < cell_size) + if (OF_getencprop(node, "#size-cells", &cell, cell_size) < cell_size) cell = 1; - *size_cells = fdt32_to_cpu((int)cell); + *size_cells = (int)cell; if (*addr_cells > 3 || *size_cells > 2) return (ERANGE); @@ -540,11 +542,11 @@ fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc) phy_node = OF_node_from_xref(phy_handle); - if (OF_getprop(phy_node, "reg", (void *)&phy_reg, + if (OF_getencprop(phy_node, "reg", (void *)&phy_reg, sizeof(phy_reg)) <= 0) return (ENXIO); - *phy_addr = fdt32_to_cpu(phy_reg); + *phy_addr = phy_reg; /* * Search for softc used to communicate with phy. diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h index afddc310c12..81ce4bfae2e 100644 --- a/sys/dev/fdt/fdt_common.h +++ b/sys/dev/fdt/fdt_common.h @@ -94,7 +94,6 @@ int fdt_get_phyaddr(phandle_t, device_t, int *, void **); int fdt_get_range(phandle_t, int, u_long *, u_long *); int fdt_immr_addr(vm_offset_t); int fdt_regsize(phandle_t, u_long *, u_long *); -int fdt_is_compatible(phandle_t, const char *); int fdt_is_compatible_strict(phandle_t, const char *); int fdt_is_enabled(phandle_t); int fdt_pm_is_enabled(phandle_t); diff --git a/sys/dev/fdt/fdt_powerpc.c b/sys/dev/fdt/fdt_powerpc.c index 80cfa4b3a93..3c3dccef0f3 100644 --- a/sys/dev/fdt/fdt_powerpc.c +++ b/sys/dev/fdt/fdt_powerpc.c @@ -112,7 +112,7 @@ fdt_fixup_fman(phandle_t root) * That frequency is equal to /soc node bus-frequency. */ for (node = OF_child(node); node != 0; node = OF_peer(node)) { - if (fdt_is_compatible(node, "fsl,fman") == 0) + if (ofw_bus_node_is_compatible(node, "fsl,fman") == 0) continue; if (OF_setprop(node, "clock-frequency", (void *)&freq, diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index 421af9d659d..056dd3193d4 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -855,5 +855,6 @@ driver_t gpiobus_driver = { devclass_t gpiobus_devclass; -DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0); +EARLY_DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0, + BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(gpiobus, 1); diff --git a/sys/dev/gpio/gpiopower.c b/sys/dev/gpio/gpiopower.c new file mode 100644 index 00000000000..98b635e3fd2 --- /dev/null +++ b/sys/dev/gpio/gpiopower.c @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2016 Justin Hibbits + * 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. + */ + +#include + +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +struct gpiopower_softc { + gpio_pin_t sc_pin; + int sc_rbmask; +}; + +static void gpiopower_assert(device_t dev, int howto); + +static int +gpiopower_probe(device_t dev) +{ + + if (ofw_bus_is_compatible(dev, "gpio-poweroff")) { + device_set_desc(dev, "GPIO poweroff control"); + return (0); + } else if (ofw_bus_is_compatible(dev, "gpio-restart")) { + device_set_desc(dev, "GPIO restart control"); + return (0); + } + + return (ENXIO); +} + +static int +gpiopower_attach(device_t dev) +{ + struct gpiopower_softc *sc; + phandle_t node; + + sc = device_get_softc(dev); + + if ((node = ofw_bus_get_node(dev)) == -1) + return (ENXIO); + + ofw_gpiobus_parse_gpios(dev, "gpios", &sc->sc_pin); + if (sc->sc_pin == NULL) { + device_printf(dev, "failed to map GPIO pin\n"); + return (ENXIO); + } + + if (ofw_bus_is_compatible(dev, "gpio-poweroff")) + sc->sc_rbmask = RB_HALT | RB_POWEROFF; + else + sc->sc_rbmask = 0; + EVENTHANDLER_REGISTER(shutdown_final, gpiopower_assert, dev, + SHUTDOWN_PRI_LAST); + gpio_pin_setflags(sc->sc_pin, GPIO_PIN_OUTPUT); + + return (0); +} + +static void +gpiopower_assert(device_t dev, int howto) +{ + struct gpiopower_softc *sc; + int do_assert; + + sc = device_get_softc(dev); + do_assert = sc->sc_rbmask ? (sc->sc_rbmask & howto) : + ((howto & RB_HALT) == 0); + + if (!do_assert) + return; + + if (howto & RB_POWEROFF) + device_printf(dev, "powering system off\n"); + else if ((howto & RB_HALT) == 0) + device_printf(dev, "resetting system\n"); + else + return; + + gpio_pin_set_active(sc->sc_pin, true); + + /* Wait a second for it to trip */ + DELAY(10000000); +} + +static devclass_t gpiopower_devclass; + +static device_method_t gpiopower_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, gpiopower_probe), + DEVMETHOD(device_attach, gpiopower_attach), + + DEVMETHOD_END +}; + +static driver_t gpiopower_driver = { + "gpiopower", + gpiopower_methods, + sizeof(struct gpiopower_softc) +}; + +DRIVER_MODULE(gpiopower, simplebus, gpiopower_driver, gpiopower_devclass, 0, 0); +MODULE_DEPEND(gpiopower, gpiobus, 1, 1, 1); diff --git a/sys/dev/hyperv/pcib/vmbus_pcib.c b/sys/dev/hyperv/pcib/vmbus_pcib.c new file mode 100644 index 00000000000..2fb2c0259d5 --- /dev/null +++ b/sys/dev/hyperv/pcib/vmbus_pcib.c @@ -0,0 +1,1791 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "pcib_if.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "vmbus_if.h" + +#if __FreeBSD_version < 1100000 +typedef u_long rman_res_t; +#define RM_MAX_END (~(rman_res_t)0) +#endif + +struct completion { + unsigned int done; + struct mtx lock; +}; + +static void +init_completion(struct completion *c) +{ + memset(c, 0, sizeof(*c)); + mtx_init(&c->lock, "hvcmpl", NULL, MTX_DEF); + c->done = 0; +} + +static void +free_completion(struct completion *c) +{ + mtx_destroy(&c->lock); +} + +static void +complete(struct completion *c) +{ + mtx_lock(&c->lock); + c->done++; + mtx_unlock(&c->lock); + wakeup(c); +} + +static void +wait_for_completion(struct completion *c) +{ + mtx_lock(&c->lock); + while (c->done == 0) + mtx_sleep(c, &c->lock, 0, "hvwfc", 0); + c->done--; + mtx_unlock(&c->lock); +} + +#define PCI_MAKE_VERSION(major, minor) ((uint32_t)(((major) << 16) | (major))) + +enum { + PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1), + PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1 +}; + +#define PCI_CONFIG_MMIO_LENGTH 0x2000 +#define CFG_PAGE_OFFSET 0x1000 +#define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET) + +/* + * Message Types + */ + +enum pci_message_type { + /* + * Version 1.1 + */ + PCI_MESSAGE_BASE = 0x42490000, + PCI_BUS_RELATIONS = PCI_MESSAGE_BASE + 0, + PCI_QUERY_BUS_RELATIONS = PCI_MESSAGE_BASE + 1, + PCI_POWER_STATE_CHANGE = PCI_MESSAGE_BASE + 4, + PCI_QUERY_RESOURCE_REQUIREMENTS = PCI_MESSAGE_BASE + 5, + PCI_QUERY_RESOURCE_RESOURCES = PCI_MESSAGE_BASE + 6, + PCI_BUS_D0ENTRY = PCI_MESSAGE_BASE + 7, + PCI_BUS_D0EXIT = PCI_MESSAGE_BASE + 8, + PCI_READ_BLOCK = PCI_MESSAGE_BASE + 9, + PCI_WRITE_BLOCK = PCI_MESSAGE_BASE + 0xA, + PCI_EJECT = PCI_MESSAGE_BASE + 0xB, + PCI_QUERY_STOP = PCI_MESSAGE_BASE + 0xC, + PCI_REENABLE = PCI_MESSAGE_BASE + 0xD, + PCI_QUERY_STOP_FAILED = PCI_MESSAGE_BASE + 0xE, + PCI_EJECTION_COMPLETE = PCI_MESSAGE_BASE + 0xF, + PCI_RESOURCES_ASSIGNED = PCI_MESSAGE_BASE + 0x10, + PCI_RESOURCES_RELEASED = PCI_MESSAGE_BASE + 0x11, + PCI_INVALIDATE_BLOCK = PCI_MESSAGE_BASE + 0x12, + PCI_QUERY_PROTOCOL_VERSION = PCI_MESSAGE_BASE + 0x13, + PCI_CREATE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x14, + PCI_DELETE_INTERRUPT_MESSAGE = PCI_MESSAGE_BASE + 0x15, + PCI_MESSAGE_MAXIMUM +}; + +/* + * Structures defining the virtual PCI Express protocol. + */ + +union pci_version { + struct { + uint16_t minor_version; + uint16_t major_version; + } parts; + uint32_t version; +} __packed; + +/* + * This representation is the one used in Windows, which is + * what is expected when sending this back and forth with + * the Hyper-V parent partition. + */ +union win_slot_encoding { + struct { + uint32_t slot:5; + uint32_t func:3; + uint32_t reserved:24; + } bits; + uint32_t val; +} __packed; + +struct pci_func_desc { + uint16_t v_id; /* vendor ID */ + uint16_t d_id; /* device ID */ + uint8_t rev; + uint8_t prog_intf; + uint8_t subclass; + uint8_t base_class; + uint32_t subsystem_id; + union win_slot_encoding wslot; + uint32_t ser; /* serial number */ +} __packed; + +struct hv_msi_desc { + uint8_t vector; + uint8_t delivery_mode; + uint16_t vector_count; + uint32_t reserved; + uint64_t cpu_mask; +} __packed; + +struct tran_int_desc { + uint16_t reserved; + uint16_t vector_count; + uint32_t data; + uint64_t address; +} __packed; + +struct pci_message { + uint32_t type; +} __packed; + +struct pci_child_message { + struct pci_message message_type; + union win_slot_encoding wslot; +} __packed; + +struct pci_incoming_message { + struct vmbus_chanpkt_hdr hdr; + struct pci_message message_type; +} __packed; + +struct pci_response { + struct vmbus_chanpkt_hdr hdr; + int32_t status; /* negative values are failures */ +} __packed; + +struct pci_packet { + void (*completion_func)(void *context, struct pci_response *resp, + int resp_packet_size); + void *compl_ctxt; + + struct pci_message message[0]; +}; + +/* + * Specific message types supporting the PCI protocol. + */ + +struct pci_version_request { + struct pci_message message_type; + uint32_t protocol_version; + uint32_t is_last_attempt:1; + uint32_t reservedz:31; +} __packed; + +struct pci_bus_d0_entry { + struct pci_message message_type; + uint32_t reserved; + uint64_t mmio_base; +} __packed; + +struct pci_bus_relations { + struct pci_incoming_message incoming; + uint32_t device_count; + struct pci_func_desc func[0]; +} __packed; + +#define MAX_NUM_BARS (PCIR_MAX_BAR_0 + 1) +struct pci_q_res_req_response { + struct vmbus_chanpkt_hdr hdr; + int32_t status; /* negative values are failures */ + uint32_t probed_bar[MAX_NUM_BARS]; +} __packed; + +struct pci_resources_assigned { + struct pci_message message_type; + union win_slot_encoding wslot; + uint8_t memory_range[0x14][MAX_NUM_BARS]; /* unused here */ + uint32_t msi_descriptors; + uint32_t reserved[4]; +} __packed; + +struct pci_create_interrupt { + struct pci_message message_type; + union win_slot_encoding wslot; + struct hv_msi_desc int_desc; +} __packed; + +struct pci_create_int_response { + struct pci_response response; + uint32_t reserved; + struct tran_int_desc int_desc; +} __packed; + +struct pci_delete_interrupt { + struct pci_message message_type; + union win_slot_encoding wslot; + struct tran_int_desc int_desc; +} __packed; + +struct pci_dev_incoming { + struct pci_incoming_message incoming; + union win_slot_encoding wslot; +} __packed; + +struct pci_eject_response { + struct pci_message message_type; + union win_slot_encoding wslot; + uint32_t status; +} __packed; + +/* + * Driver specific state. + */ + +enum hv_pcibus_state { + hv_pcibus_init = 0, + hv_pcibus_installed, +}; + +struct hv_pcibus { + device_t pcib; + device_t pci_bus; + struct vmbus_pcib_softc *sc; + + uint16_t pci_domain; + + enum hv_pcibus_state state; + + struct resource *cfg_res; + + struct completion query_completion, *query_comp; + + struct mtx config_lock; /* Avoid two threads writing index page */ + struct mtx device_list_lock; /* Protect lists below */ + TAILQ_HEAD(, hv_pci_dev) children; + TAILQ_HEAD(, hv_dr_state) dr_list; + + volatile int detaching; +}; + +struct hv_pci_dev { + TAILQ_ENTRY(hv_pci_dev) link; + + struct pci_func_desc desc; + + bool reported_missing; + + struct hv_pcibus *hbus; + struct task eject_task; + + TAILQ_HEAD(, hv_irq_desc) irq_desc_list; + + /* + * What would be observed if one wrote 0xFFFFFFFF to a BAR and then + * read it back, for each of the BAR offsets within config space. + */ + uint32_t probed_bar[MAX_NUM_BARS]; +}; + +/* + * Tracks "Device Relations" messages from the host, which must be both + * processed in order. + */ +struct hv_dr_work { + struct task task; + struct hv_pcibus *bus; +}; + +struct hv_dr_state { + TAILQ_ENTRY(hv_dr_state) link; + uint32_t device_count; + struct pci_func_desc func[0]; +}; + +struct hv_irq_desc { + TAILQ_ENTRY(hv_irq_desc) link; + struct tran_int_desc desc; + int irq; +}; + +#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) +#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define PCI_FUNC(devfn) ((devfn) & 0x07) + +static uint32_t +devfn_to_wslot(unsigned int devfn) +{ + union win_slot_encoding wslot; + + wslot.val = 0; + wslot.bits.slot = PCI_SLOT(devfn); + wslot.bits.func = PCI_FUNC(devfn); + + return (wslot.val); +} + +static unsigned int +wslot_to_devfn(uint32_t wslot) +{ + union win_slot_encoding encoding; + unsigned int slot; + unsigned int func; + + encoding.val = wslot; + + slot = encoding.bits.slot; + func = encoding.bits.func; + + return (PCI_DEVFN(slot, func)); +} + +struct vmbus_pcib_softc { + struct vmbus_channel *chan; + void *rx_buf; + + struct taskqueue *taskq; + + struct hv_pcibus *hbus; +}; + +/* {44C4F61D-4444-4400-9D52-802E27EDE19F} */ +static const struct hyperv_guid g_pass_through_dev_type = { + .hv_guid = {0x1D, 0xF6, 0xC4, 0x44, 0x44, 0x44, 0x00, 0x44, + 0x9D, 0x52, 0x80, 0x2E, 0x27, 0xED, 0xE1, 0x9F} +}; + +struct hv_pci_compl { + struct completion host_event; + int32_t completion_status; +}; + +struct q_res_req_compl { + struct completion host_event; + struct hv_pci_dev *hpdev; +}; + +struct compose_comp_ctxt { + struct hv_pci_compl comp_pkt; + struct tran_int_desc int_desc; +}; + +static void +hv_pci_generic_compl(void *context, struct pci_response *resp, + int resp_packet_size) +{ + struct hv_pci_compl *comp_pkt = context; + + if (resp_packet_size >= sizeof(struct pci_response)) + comp_pkt->completion_status = resp->status; + else + comp_pkt->completion_status = -1; + + complete(&comp_pkt->host_event); +} + +static void +q_resource_requirements(void *context, struct pci_response *resp, + int resp_packet_size) +{ + struct q_res_req_compl *completion = context; + struct pci_q_res_req_response *q_res_req = + (struct pci_q_res_req_response *)resp; + int i; + + if (resp->status < 0) { + printf("vmbus_pcib: failed to query resource requirements\n"); + } else { + for (i = 0; i < MAX_NUM_BARS; i++) + completion->hpdev->probed_bar[i] = + q_res_req->probed_bar[i]; + } + + complete(&completion->host_event); +} + +static void +hv_pci_compose_compl(void *context, struct pci_response *resp, + int resp_packet_size) +{ + struct compose_comp_ctxt *comp_pkt = context; + struct pci_create_int_response *int_resp = + (struct pci_create_int_response *)resp; + + comp_pkt->comp_pkt.completion_status = resp->status; + comp_pkt->int_desc = int_resp->int_desc; + complete(&comp_pkt->comp_pkt.host_event); +} + +static void +hv_int_desc_free(struct hv_pci_dev *hpdev, struct hv_irq_desc *hid) +{ + struct pci_delete_interrupt *int_pkt; + struct { + struct pci_packet pkt; + uint8_t buffer[sizeof(struct pci_delete_interrupt)]; + } ctxt; + + memset(&ctxt, 0, sizeof(ctxt)); + int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message; + int_pkt->message_type.type = PCI_DELETE_INTERRUPT_MESSAGE; + int_pkt->wslot.val = hpdev->desc.wslot.val; + int_pkt->int_desc = hid->desc; + + vmbus_chan_send(hpdev->hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0, + int_pkt, sizeof(*int_pkt), 0); + + free(hid, M_DEVBUF); +} + +static void +hv_pci_delete_device(struct hv_pci_dev *hpdev) +{ + struct hv_pcibus *hbus = hpdev->hbus; + struct hv_irq_desc *hid, *tmp_hid; + device_t pci_dev; + int devfn; + + devfn = wslot_to_devfn(hpdev->desc.wslot.val); + + mtx_lock(&Giant); + + pci_dev = pci_find_dbsf(hbus->pci_domain, + 0, PCI_SLOT(devfn), PCI_FUNC(devfn)); + if (pci_dev) + device_delete_child(hbus->pci_bus, pci_dev); + + mtx_unlock(&Giant); + + mtx_lock(&hbus->device_list_lock); + TAILQ_REMOVE(&hbus->children, hpdev, link); + mtx_unlock(&hbus->device_list_lock); + + TAILQ_FOREACH_SAFE(hid, &hpdev->irq_desc_list, link, tmp_hid) + hv_int_desc_free(hpdev, hid); + + free(hpdev, M_DEVBUF); +} + +static struct hv_pci_dev * +new_pcichild_device(struct hv_pcibus *hbus, struct pci_func_desc *desc) +{ + struct hv_pci_dev *hpdev; + struct pci_child_message *res_req; + struct q_res_req_compl comp_pkt; + struct { + struct pci_packet pkt; + uint8_t buffer[sizeof(struct pci_child_message)]; + } ctxt; + int ret; + + hpdev = malloc(sizeof(*hpdev), M_DEVBUF, M_WAITOK | M_ZERO); + hpdev->hbus = hbus; + + TAILQ_INIT(&hpdev->irq_desc_list); + + init_completion(&comp_pkt.host_event); + comp_pkt.hpdev = hpdev; + + ctxt.pkt.compl_ctxt = &comp_pkt; + ctxt.pkt.completion_func = q_resource_requirements; + + res_req = (struct pci_child_message *)&ctxt.pkt.message; + res_req->message_type.type = PCI_QUERY_RESOURCE_REQUIREMENTS; + res_req->wslot.val = desc->wslot.val; + + ret = vmbus_chan_send(hbus->sc->chan, + VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, + res_req, sizeof(*res_req), (uint64_t)&ctxt.pkt); + if (ret) + goto err; + + wait_for_completion(&comp_pkt.host_event); + free_completion(&comp_pkt.host_event); + + hpdev->desc = *desc; + + mtx_lock(&hbus->device_list_lock); + TAILQ_INSERT_TAIL(&hbus->children, hpdev, link); + mtx_unlock(&hbus->device_list_lock); + return (hpdev); +err: + free_completion(&comp_pkt.host_event); + free(hpdev, M_DEVBUF); + return (NULL); +} + +#if __FreeBSD_version < 1100000 + +/* Old versions don't have BUS_RESCAN(). Let's copy it from FreeBSD 11. */ + +static struct pci_devinfo * +pci_identify_function(device_t pcib, device_t dev, int domain, int busno, + int slot, int func, size_t dinfo_size) +{ + struct pci_devinfo *dinfo; + + dinfo = pci_read_device(pcib, domain, busno, slot, func, dinfo_size); + if (dinfo != NULL) + pci_add_child(dev, dinfo); + + return (dinfo); +} + +static int +pci_rescan(device_t dev) +{ +#define REG(n, w) PCIB_READ_CONFIG(pcib, busno, s, f, n, w) + device_t pcib = device_get_parent(dev); + struct pci_softc *sc; + device_t child, *devlist, *unchanged; + int devcount, error, i, j, maxslots, oldcount; + int busno, domain, s, f, pcifunchigh; + uint8_t hdrtype; + + /* No need to check for ARI on a rescan. */ + error = device_get_children(dev, &devlist, &devcount); + if (error) + return (error); + if (devcount != 0) { + unchanged = malloc(devcount * sizeof(device_t), M_TEMP, + M_NOWAIT | M_ZERO); + if (unchanged == NULL) { + free(devlist, M_TEMP); + return (ENOMEM); + } + } else + unchanged = NULL; + + sc = device_get_softc(dev); + domain = pcib_get_domain(dev); + busno = pcib_get_bus(dev); + maxslots = PCIB_MAXSLOTS(pcib); + for (s = 0; s <= maxslots; s++) { + /* If function 0 is not present, skip to the next slot. */ + f = 0; + if (REG(PCIR_VENDOR, 2) == 0xffff) + continue; + pcifunchigh = 0; + hdrtype = REG(PCIR_HDRTYPE, 1); + if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) + continue; + if (hdrtype & PCIM_MFDEV) + pcifunchigh = PCIB_MAXFUNCS(pcib); + for (f = 0; f <= pcifunchigh; f++) { + if (REG(PCIR_VENDOR, 2) == 0xffff) + continue; + + /* + * Found a valid function. Check if a + * device_t for this device already exists. + */ + for (i = 0; i < devcount; i++) { + child = devlist[i]; + if (child == NULL) + continue; + if (pci_get_slot(child) == s && + pci_get_function(child) == f) { + unchanged[i] = child; + goto next_func; + } + } + + pci_identify_function(pcib, dev, domain, busno, s, f, + sizeof(struct pci_devinfo)); + next_func:; + } + } + + /* Remove devices that are no longer present. */ + for (i = 0; i < devcount; i++) { + if (unchanged[i] != NULL) + continue; + device_delete_child(dev, devlist[i]); + } + + free(devlist, M_TEMP); + oldcount = devcount; + + /* Try to attach the devices just added. */ + error = device_get_children(dev, &devlist, &devcount); + if (error) { + free(unchanged, M_TEMP); + return (error); + } + + for (i = 0; i < devcount; i++) { + for (j = 0; j < oldcount; j++) { + if (devlist[i] == unchanged[j]) + goto next_device; + } + + device_probe_and_attach(devlist[i]); + next_device:; + } + + free(unchanged, M_TEMP); + free(devlist, M_TEMP); + return (0); +#undef REG +} + +#else + +static int +pci_rescan(device_t dev) +{ + return (BUS_RESCAN(dev)); +} + +#endif + +static void +pci_devices_present_work(void *arg, int pending __unused) +{ + struct hv_dr_work *dr_wrk = arg; + struct hv_dr_state *dr = NULL; + struct hv_pcibus *hbus; + uint32_t child_no; + bool found; + struct pci_func_desc *new_desc; + struct hv_pci_dev *hpdev, *tmp_hpdev; + struct completion *query_comp; + bool need_rescan = false; + + hbus = dr_wrk->bus; + free(dr_wrk, M_DEVBUF); + + /* Pull this off the queue and process it if it was the last one. */ + mtx_lock(&hbus->device_list_lock); + while (!TAILQ_EMPTY(&hbus->dr_list)) { + dr = TAILQ_FIRST(&hbus->dr_list); + TAILQ_REMOVE(&hbus->dr_list, dr, link); + + /* Throw this away if the list still has stuff in it. */ + if (!TAILQ_EMPTY(&hbus->dr_list)) { + free(dr, M_DEVBUF); + continue; + } + } + mtx_unlock(&hbus->device_list_lock); + + if (!dr) + return; + + /* First, mark all existing children as reported missing. */ + mtx_lock(&hbus->device_list_lock); + TAILQ_FOREACH(hpdev, &hbus->children, link) + hpdev->reported_missing = true; + mtx_unlock(&hbus->device_list_lock); + + /* Next, add back any reported devices. */ + for (child_no = 0; child_no < dr->device_count; child_no++) { + found = false; + new_desc = &dr->func[child_no]; + + mtx_lock(&hbus->device_list_lock); + TAILQ_FOREACH(hpdev, &hbus->children, link) { + if ((hpdev->desc.wslot.val == + new_desc->wslot.val) && + (hpdev->desc.v_id == new_desc->v_id) && + (hpdev->desc.d_id == new_desc->d_id) && + (hpdev->desc.ser == new_desc->ser)) { + hpdev->reported_missing = false; + found = true; + break; + } + } + mtx_unlock(&hbus->device_list_lock); + + if (!found) { + if (!need_rescan) + need_rescan = true; + + hpdev = new_pcichild_device(hbus, new_desc); + if (!hpdev) + printf("vmbus_pcib: failed to add a child\n"); + } + } + + /* Remove missing device(s), if any */ + TAILQ_FOREACH_SAFE(hpdev, &hbus->children, link, tmp_hpdev) { + if (hpdev->reported_missing) + hv_pci_delete_device(hpdev); + } + + /* Rescan the bus to find any new device, if necessary. */ + if (hbus->state == hv_pcibus_installed && need_rescan) + pci_rescan(hbus->pci_bus); + + /* Wake up hv_pci_query_relations(), if it's waiting. */ + query_comp = hbus->query_comp; + if (query_comp) { + hbus->query_comp = NULL; + complete(query_comp); + } + + free(dr, M_DEVBUF); +} + +static struct hv_pci_dev * +get_pcichild_wslot(struct hv_pcibus *hbus, uint32_t wslot) +{ + struct hv_pci_dev *hpdev, *ret = NULL; + + mtx_lock(&hbus->device_list_lock); + TAILQ_FOREACH(hpdev, &hbus->children, link) { + if (hpdev->desc.wslot.val == wslot) { + ret = hpdev; + break; + } + } + mtx_unlock(&hbus->device_list_lock); + + return (ret); +} + +static void +hv_pci_devices_present(struct hv_pcibus *hbus, + struct pci_bus_relations *relations) +{ + struct hv_dr_state *dr; + struct hv_dr_work *dr_wrk; + unsigned long dr_size; + + if (hbus->detaching && relations->device_count > 0) + return; + + dr_size = offsetof(struct hv_dr_state, func) + + (sizeof(struct pci_func_desc) * relations->device_count); + dr = malloc(dr_size, M_DEVBUF, M_WAITOK | M_ZERO); + + dr->device_count = relations->device_count; + if (dr->device_count != 0) + memcpy(dr->func, relations->func, + sizeof(struct pci_func_desc) * dr->device_count); + + mtx_lock(&hbus->device_list_lock); + TAILQ_INSERT_TAIL(&hbus->dr_list, dr, link); + mtx_unlock(&hbus->device_list_lock); + + dr_wrk = malloc(sizeof(*dr_wrk), M_DEVBUF, M_WAITOK | M_ZERO); + dr_wrk->bus = hbus; + TASK_INIT(&dr_wrk->task, 0, pci_devices_present_work, dr_wrk); + taskqueue_enqueue(hbus->sc->taskq, &dr_wrk->task); +} + +static void +hv_eject_device_work(void *arg, int pending __unused) +{ + struct hv_pci_dev *hpdev = arg; + union win_slot_encoding wslot = hpdev->desc.wslot; + struct hv_pcibus *hbus = hpdev->hbus; + struct pci_eject_response *eject_pkt; + struct { + struct pci_packet pkt; + uint8_t buffer[sizeof(struct pci_eject_response)]; + } ctxt; + + hv_pci_delete_device(hpdev); + + memset(&ctxt, 0, sizeof(ctxt)); + eject_pkt = (struct pci_eject_response *)&ctxt.pkt.message; + eject_pkt->message_type.type = PCI_EJECTION_COMPLETE; + eject_pkt->wslot.val = wslot.val; + vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0, + eject_pkt, sizeof(*eject_pkt), 0); +} + +static void +hv_pci_eject_device(struct hv_pci_dev *hpdev) +{ + struct hv_pcibus *hbus = hpdev->hbus; + struct taskqueue *taskq; + + if (hbus->detaching) + return; + + /* + * Push this task into the same taskqueue on which + * vmbus_pcib_attach() runs, so we're sure this task can't run + * concurrently with vmbus_pcib_attach(). + */ + TASK_INIT(&hpdev->eject_task, 0, hv_eject_device_work, hpdev); + taskq = vmbus_chan_mgmt_tq(hbus->sc->chan); + taskqueue_enqueue(taskq, &hpdev->eject_task); +} + +#define PCIB_PACKET_SIZE 0x100 + +static void +vmbus_pcib_on_channel_callback(struct vmbus_channel *chan, void *arg) +{ + struct vmbus_pcib_softc *sc = arg; + struct hv_pcibus *hbus = sc->hbus; + + void *buffer; + int bufferlen = PCIB_PACKET_SIZE; + + struct pci_packet *comp_packet; + struct pci_response *response; + struct pci_incoming_message *new_msg; + struct pci_bus_relations *bus_rel; + struct pci_dev_incoming *dev_msg; + struct hv_pci_dev *hpdev; + + buffer = sc->rx_buf; + do { + struct vmbus_chanpkt_hdr *pkt = buffer; + uint32_t bytes_rxed; + int ret; + + bytes_rxed = bufferlen; + ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed); + + if (ret == ENOBUFS) { + /* Handle large packet */ + if (bufferlen > PCIB_PACKET_SIZE) { + free(buffer, M_DEVBUF); + buffer = NULL; + } + + /* alloc new buffer */ + buffer = malloc(bytes_rxed, M_DEVBUF, M_WAITOK | M_ZERO); + bufferlen = bytes_rxed; + + continue; + } + + if (ret != 0) { + /* ignore EIO or EAGAIN */ + break; + } + + if (bytes_rxed <= sizeof(struct pci_response)) + continue; + + switch (pkt->cph_type) { + case VMBUS_CHANPKT_TYPE_COMP: + comp_packet = (struct pci_packet *)pkt->cph_xactid; + response = (struct pci_response *)pkt; + comp_packet->completion_func(comp_packet->compl_ctxt, + response, bytes_rxed); + break; + case VMBUS_CHANPKT_TYPE_INBAND: + new_msg = (struct pci_incoming_message *)buffer; + + switch (new_msg->message_type.type) { + case PCI_BUS_RELATIONS: + bus_rel = (struct pci_bus_relations *)buffer; + + if (bus_rel->device_count == 0) + break; + + if (bytes_rxed < + offsetof(struct pci_bus_relations, func) + + (sizeof(struct pci_func_desc) * + (bus_rel->device_count))) + break; + + hv_pci_devices_present(hbus, bus_rel); + break; + + case PCI_EJECT: + dev_msg = (struct pci_dev_incoming *)buffer; + hpdev = get_pcichild_wslot(hbus, + dev_msg->wslot.val); + + if (hpdev) + hv_pci_eject_device(hpdev); + + break; + default: + printf("vmbus_pcib: Unknown msg type 0x%x\n", + new_msg->message_type.type); + break; + } + break; + default: + printf("vmbus_pcib: Unknown VMBus msg type %hd\n", + pkt->cph_type); + break; + } + } while (1); + + if (bufferlen > PCIB_PACKET_SIZE) + free(buffer, M_DEVBUF); +} + +static int +hv_pci_protocol_negotiation(struct hv_pcibus *hbus) +{ + struct pci_version_request *version_req; + struct hv_pci_compl comp_pkt; + struct { + struct pci_packet pkt; + uint8_t buffer[sizeof(struct pci_version_request)]; + } ctxt; + int ret; + + init_completion(&comp_pkt.host_event); + + ctxt.pkt.completion_func = hv_pci_generic_compl; + ctxt.pkt.compl_ctxt = &comp_pkt; + version_req = (struct pci_version_request *)&ctxt.pkt.message; + version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION; + version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT; + version_req->is_last_attempt = 1; + + ret = vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC, version_req, sizeof(*version_req), + (uint64_t)&ctxt.pkt); + if (ret) + goto out; + + wait_for_completion(&comp_pkt.host_event); + + if (comp_pkt.completion_status < 0) { + device_printf(hbus->pcib, + "vmbus_pcib version negotiation failed: %x\n", + comp_pkt.completion_status); + ret = EPROTO; + } else { + ret = 0; + } +out: + free_completion(&comp_pkt.host_event); + return (ret); +} + +/* Ask the host to send along the list of child devices */ +static int +hv_pci_query_relations(struct hv_pcibus *hbus) +{ + struct pci_message message; + int ret; + + message.type = PCI_QUERY_BUS_RELATIONS; + ret = vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0, + &message, sizeof(message), 0); + return (ret); +} + +static int +hv_pci_enter_d0(struct hv_pcibus *hbus) +{ + struct pci_bus_d0_entry *d0_entry; + struct hv_pci_compl comp_pkt; + struct { + struct pci_packet pkt; + uint8_t buffer[sizeof(struct pci_bus_d0_entry)]; + } ctxt; + int ret; + + /* + * Tell the host that the bus is ready to use, and moved into the + * powered-on state. This includes telling the host which region + * of memory-mapped I/O space has been chosen for configuration space + * access. + */ + init_completion(&comp_pkt.host_event); + + ctxt.pkt.completion_func = hv_pci_generic_compl; + ctxt.pkt.compl_ctxt = &comp_pkt; + + d0_entry = (struct pci_bus_d0_entry *)&ctxt.pkt.message; + memset(d0_entry, 0, sizeof(*d0_entry)); + d0_entry->message_type.type = PCI_BUS_D0ENTRY; + d0_entry->mmio_base = rman_get_start(hbus->cfg_res); + + ret = vmbus_chan_send(hbus->sc->chan, VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC, d0_entry, sizeof(*d0_entry), + (uint64_t)&ctxt.pkt); + if (ret) + goto out; + + wait_for_completion(&comp_pkt.host_event); + + if (comp_pkt.completion_status < 0) { + device_printf(hbus->pcib, "vmbus_pcib failed to enable D0\n"); + ret = EPROTO; + } else { + ret = 0; + } + +out: + free_completion(&comp_pkt.host_event); + return (ret); +} + +/* + * It looks this is only needed by Windows VM, but let's send the message too + * just to make the host happy. + */ +static int +hv_send_resources_allocated(struct hv_pcibus *hbus) +{ + struct pci_resources_assigned *res_assigned; + struct hv_pci_compl comp_pkt; + struct hv_pci_dev *hpdev; + struct pci_packet *pkt; + uint32_t wslot; + int ret = 0; + + pkt = malloc(sizeof(*pkt) + sizeof(*res_assigned), + M_DEVBUF, M_WAITOK | M_ZERO); + + for (wslot = 0; wslot < 256; wslot++) { + hpdev = get_pcichild_wslot(hbus, wslot); + if (!hpdev) + continue; + + init_completion(&comp_pkt.host_event); + + memset(pkt, 0, sizeof(*pkt) + sizeof(*res_assigned)); + pkt->completion_func = hv_pci_generic_compl; + pkt->compl_ctxt = &comp_pkt; + + res_assigned = (struct pci_resources_assigned *)&pkt->message; + res_assigned->message_type.type = PCI_RESOURCES_ASSIGNED; + res_assigned->wslot.val = hpdev->desc.wslot.val; + + ret = vmbus_chan_send(hbus->sc->chan, + VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC, + &pkt->message, sizeof(*res_assigned), (uint64_t)pkt); + if (ret) { + free_completion(&comp_pkt.host_event); + break; + } + + wait_for_completion(&comp_pkt.host_event); + free_completion(&comp_pkt.host_event); + + if (comp_pkt.completion_status < 0) { + ret = EPROTO; + device_printf(hbus->pcib, + "failed to send PCI_RESOURCES_ASSIGNED\n"); + break; + } + } + + free(pkt, M_DEVBUF); + return (ret); +} + +static int +hv_send_resources_released(struct hv_pcibus *hbus) +{ + struct pci_child_message pkt; + struct hv_pci_dev *hpdev; + uint32_t wslot; + int ret; + + for (wslot = 0; wslot < 256; wslot++) { + hpdev = get_pcichild_wslot(hbus, wslot); + if (!hpdev) + continue; + + pkt.message_type.type = PCI_RESOURCES_RELEASED; + pkt.wslot.val = hpdev->desc.wslot.val; + + ret = vmbus_chan_send(hbus->sc->chan, + VMBUS_CHANPKT_TYPE_INBAND, 0, &pkt, sizeof(pkt), 0); + if (ret) + return (ret); + } + + return (0); +} + +#define hv_cfg_read(x, s) \ +static inline uint##x##_t hv_cfg_read_##s(struct hv_pcibus *bus, \ + bus_size_t offset) \ +{ \ + return (bus_read_##s(bus->cfg_res, offset)); \ +} + +#define hv_cfg_write(x, s) \ +static inline void hv_cfg_write_##s(struct hv_pcibus *bus, \ + bus_size_t offset, uint##x##_t val) \ +{ \ + return (bus_write_##s(bus->cfg_res, offset, val)); \ +} + +hv_cfg_read(8, 1) +hv_cfg_read(16, 2) +hv_cfg_read(32, 4) + +hv_cfg_write(8, 1) +hv_cfg_write(16, 2) +hv_cfg_write(32, 4) + +static void +_hv_pcifront_read_config(struct hv_pci_dev *hpdev, int where, int size, + uint32_t *val) +{ + struct hv_pcibus *hbus = hpdev->hbus; + bus_size_t addr = CFG_PAGE_OFFSET + where; + + /* + * If the attempt is to read the IDs or the ROM BAR, simulate that. + */ + if (where + size <= PCIR_COMMAND) { + memcpy(val, ((uint8_t *)&hpdev->desc.v_id) + where, size); + } else if (where >= PCIR_REVID && where + size <= + PCIR_CACHELNSZ) { + memcpy(val, ((uint8_t *)&hpdev->desc.rev) + where - + PCIR_REVID, size); + } else if (where >= PCIR_SUBVEND_0 && where + size <= + PCIR_BIOS) { + memcpy(val, (uint8_t *)&hpdev->desc.subsystem_id + where - + PCIR_SUBVEND_0, size); + } else if (where >= PCIR_BIOS && where + size <= + PCIR_CAP_PTR) { + /* ROM BARs are unimplemented */ + *val = 0; + } else if ((where >= PCIR_INTLINE && where + size <= + PCIR_INTPIN) ||(where == PCIR_INTPIN && size == 1)) { + /* + * Interrupt Line and Interrupt PIN are hard-wired to zero + * because this front-end only supports message-signaled + * interrupts. + */ + *val = 0; + } else if (where + size <= CFG_PAGE_SIZE) { + mtx_lock(&hbus->config_lock); + + /* Choose the function to be read. */ + hv_cfg_write_4(hbus, 0, hpdev->desc.wslot.val); + + /* Make sure the function was chosen before we start reading.*/ + mb(); + + /* Read from that function's config space. */ + switch (size) { + case 1: + *((uint8_t *)val) = hv_cfg_read_1(hbus, addr); + break; + case 2: + *((uint16_t *)val) = hv_cfg_read_2(hbus, addr); + break; + default: + *((uint32_t *)val) = hv_cfg_read_4(hbus, addr); + break; + } + /* + * Make sure the write was done before we release the lock, + * allowing consecutive reads/writes. + */ + mb(); + + mtx_unlock(&hbus->config_lock); + } else { + /* Invalid config read: it's unlikely to reach here. */ + memset(val, 0, size); + } +} + +static void +_hv_pcifront_write_config(struct hv_pci_dev *hpdev, int where, int size, + uint32_t val) +{ + struct hv_pcibus *hbus = hpdev->hbus; + bus_size_t addr = CFG_PAGE_OFFSET + where; + + /* SSIDs and ROM BARs are read-only */ + if (where >= PCIR_SUBVEND_0 && where + size <= PCIR_CAP_PTR) + return; + + if (where >= PCIR_COMMAND && where + size <= CFG_PAGE_SIZE) { + mtx_lock(&hbus->config_lock); + + /* Choose the function to be written. */ + hv_cfg_write_4(hbus, 0, hpdev->desc.wslot.val); + + /* Make sure the function was chosen before we start writing.*/ + wmb(); + + /* Write to that function's config space. */ + switch (size) { + case 1: + hv_cfg_write_1(hbus, addr, (uint8_t)val); + break; + case 2: + hv_cfg_write_2(hbus, addr, (uint16_t)val); + break; + default: + hv_cfg_write_4(hbus, addr, (uint32_t)val); + break; + } + + /* + * Make sure the write was done before we release the lock, + * allowing consecutive reads/writes. + */ + mb(); + + mtx_unlock(&hbus->config_lock); + } else { + /* Invalid config write: it's unlikely to reach here. */ + return; + } +} + +static void +vmbus_pcib_set_detaching(void *arg, int pending __unused) +{ + struct hv_pcibus *hbus = arg; + + atomic_set_int(&hbus->detaching, 1); +} + +static void +vmbus_pcib_pre_detach(struct hv_pcibus *hbus) +{ + struct task task; + + TASK_INIT(&task, 0, vmbus_pcib_set_detaching, hbus); + + /* + * Make sure the channel callback won't push any possible new + * PCI_BUS_RELATIONS and PCI_EJECT tasks to sc->taskq. + */ + vmbus_chan_run_task(hbus->sc->chan, &task); + + taskqueue_drain_all(hbus->sc->taskq); +} + + +/* + * Standard probe entry point. + * + */ +static int +vmbus_pcib_probe(device_t dev) +{ + if (VMBUS_PROBE_GUID(device_get_parent(dev), dev, + &g_pass_through_dev_type) == 0) { + device_set_desc(dev, "Hyper-V PCI Express Pass Through"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +/* + * Standard attach entry point. + * + */ +static int +vmbus_pcib_attach(device_t dev) +{ + const int pci_ring_size = (4 * PAGE_SIZE); + const struct hyperv_guid *inst_guid; + struct vmbus_channel *channel; + struct vmbus_pcib_softc *sc; + struct hv_pcibus *hbus; + int rid = 0; + int ret; + + hbus = malloc(sizeof(*hbus), M_DEVBUF, M_WAITOK | M_ZERO); + hbus->pcib = dev; + + channel = vmbus_get_channel(dev); + inst_guid = vmbus_chan_guid_inst(channel); + hbus->pci_domain = inst_guid->hv_guid[9] | + (inst_guid->hv_guid[8] << 8); + + mtx_init(&hbus->config_lock, "hbcfg", NULL, MTX_DEF); + mtx_init(&hbus->device_list_lock, "hbdl", NULL, MTX_DEF); + TAILQ_INIT(&hbus->children); + TAILQ_INIT(&hbus->dr_list); + + hbus->cfg_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + 0, RM_MAX_END, PCI_CONFIG_MMIO_LENGTH, + RF_ACTIVE | rman_make_alignment_flags(PAGE_SIZE)); + + if (!hbus->cfg_res) { + device_printf(dev, "failed to get resource for cfg window\n"); + ret = ENXIO; + goto free_bus; + } + + sc = device_get_softc(dev); + sc->chan = channel; + sc->rx_buf = malloc(PCIB_PACKET_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); + sc->hbus = hbus; + + /* + * The taskq is used to handle PCI_BUS_RELATIONS and PCI_EJECT + * messages. NB: we can't handle the messages in the channel callback + * directly, because the message handlers need to send new messages + * to the host and waits for the host's completion messages, which + * must also be handled by the channel callback. + */ + sc->taskq = taskqueue_create("vmbus_pcib_tq", M_WAITOK, + taskqueue_thread_enqueue, &sc->taskq); + taskqueue_start_threads(&sc->taskq, 1, PI_NET, "vmbus_pcib_tq"); + + hbus->sc = sc; + + init_completion(&hbus->query_completion); + hbus->query_comp = &hbus->query_completion; + + ret = vmbus_chan_open(sc->chan, pci_ring_size, pci_ring_size, + NULL, 0, vmbus_pcib_on_channel_callback, sc); + if (ret) + goto free_res; + + ret = hv_pci_protocol_negotiation(hbus); + if (ret) + goto vmbus_close; + + ret = hv_pci_query_relations(hbus); + if (ret) + goto vmbus_close; + wait_for_completion(hbus->query_comp); + + ret = hv_pci_enter_d0(hbus); + if (ret) + goto vmbus_close; + + ret = hv_send_resources_allocated(hbus); + if (ret) + goto vmbus_close; + + hbus->pci_bus = device_add_child(dev, "pci", -1); + if (!hbus->pci_bus) { + device_printf(dev, "failed to create pci bus\n"); + ret = ENXIO; + goto vmbus_close; + } + + bus_generic_attach(dev); + + hbus->state = hv_pcibus_installed; + + return (0); + +vmbus_close: + vmbus_pcib_pre_detach(hbus); + vmbus_chan_close(sc->chan); +free_res: + taskqueue_free(sc->taskq); + free_completion(&hbus->query_completion); + free(sc->rx_buf, M_DEVBUF); + bus_release_resource(dev, SYS_RES_MEMORY, 0, hbus->cfg_res); +free_bus: + mtx_destroy(&hbus->device_list_lock); + mtx_destroy(&hbus->config_lock); + free(hbus, M_DEVBUF); + return (ret); +} + +/* + * Standard detach entry point + */ +static int +vmbus_pcib_detach(device_t dev) +{ + struct vmbus_pcib_softc *sc = device_get_softc(dev); + struct hv_pcibus *hbus = sc->hbus; + struct pci_message teardown_packet; + struct pci_bus_relations relations; + int ret; + + vmbus_pcib_pre_detach(hbus); + + if (hbus->state == hv_pcibus_installed) + bus_generic_detach(dev); + + /* Delete any children which might still exist. */ + memset(&relations, 0, sizeof(relations)); + hv_pci_devices_present(hbus, &relations); + + ret = hv_send_resources_released(hbus); + if (ret) + device_printf(dev, "failed to send PCI_RESOURCES_RELEASED\n"); + + teardown_packet.type = PCI_BUS_D0EXIT; + ret = vmbus_chan_send(sc->chan, VMBUS_CHANPKT_TYPE_INBAND, 0, + &teardown_packet, sizeof(struct pci_message), 0); + if (ret) + device_printf(dev, "failed to send PCI_BUS_D0EXIT\n"); + + taskqueue_drain_all(hbus->sc->taskq); + vmbus_chan_close(sc->chan); + taskqueue_free(sc->taskq); + + free_completion(&hbus->query_completion); + free(sc->rx_buf, M_DEVBUF); + bus_release_resource(dev, SYS_RES_MEMORY, 0, hbus->cfg_res); + + mtx_destroy(&hbus->device_list_lock); + mtx_destroy(&hbus->config_lock); + free(hbus, M_DEVBUF); + + return (0); +} + +static int +vmbus_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *val) +{ + struct vmbus_pcib_softc *sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_DOMAIN: + *val = sc->hbus->pci_domain; + return (0); + + case PCIB_IVAR_BUS: + /* There is only bus 0. */ + *val = 0; + return (0); + } + return (ENOENT); +} + +static int +vmbus_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t val) +{ + return (ENOENT); +} + +static struct resource * +vmbus_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + unsigned int bar_no; + struct hv_pci_dev *hpdev; + struct vmbus_pcib_softc *sc = device_get_softc(dev); + struct resource *res; + unsigned int devfn; + + if (type == PCI_RES_BUS) + return (pci_domain_alloc_bus(sc->hbus->pci_domain, child, rid, + start, end, count, flags)); + + /* Devices with port I/O BAR are not supported. */ + if (type == SYS_RES_IOPORT) + return (NULL); + + if (type == SYS_RES_MEMORY) { + devfn = PCI_DEVFN(pci_get_slot(child), + pci_get_function(child)); + hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn)); + if (!hpdev) + return (NULL); + + bar_no = PCI_RID2BAR(*rid); + if (bar_no >= MAX_NUM_BARS) + return (NULL); + + /* Make sure a 32-bit BAR gets a 32-bit address */ + if (!(hpdev->probed_bar[bar_no] & PCIM_BAR_MEM_64)) + end = ulmin(end, 0xFFFFFFFF); + } + + res = bus_generic_alloc_resource(dev, child, type, rid, + start, end, count, flags); + /* + * If this is a request for a specific range, assume it is + * correct and pass it up to the parent. + */ + if (res == NULL && start + count - 1 == end) + res = bus_generic_alloc_resource(dev, child, type, rid, + start, end, count, flags); + return (res); +} + +static int +vmbus_pcib_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + struct vmbus_pcib_softc *sc = device_get_softc(dev); + + if (type == PCI_RES_BUS) + return (pci_domain_release_bus(sc->hbus->pci_domain, child, + rid, r)); + + if (type == SYS_RES_IOPORT) + return (EINVAL); + + return (bus_generic_release_resource(dev, child, type, rid, r)); +} + +#if __FreeBSD_version >= 1100000 +static int +vmbus_pcib_get_cpus(device_t pcib, device_t dev, enum cpu_sets op, + size_t setsize, cpuset_t *cpuset) +{ + return (bus_get_cpus(pcib, op, setsize, cpuset)); +} +#endif + +static uint32_t +vmbus_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, int bytes) +{ + struct vmbus_pcib_softc *sc = device_get_softc(dev); + struct hv_pci_dev *hpdev; + unsigned int devfn = PCI_DEVFN(slot, func); + uint32_t data = 0; + + KASSERT(bus == 0, ("bus should be 0, but is %u", bus)); + + hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn)); + if (!hpdev) + return (~0); + + _hv_pcifront_read_config(hpdev, reg, bytes, &data); + + return (data); +} + +static void +vmbus_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, uint32_t data, int bytes) +{ + struct vmbus_pcib_softc *sc = device_get_softc(dev); + struct hv_pci_dev *hpdev; + unsigned int devfn = PCI_DEVFN(slot, func); + + KASSERT(bus == 0, ("bus should be 0, but is %u", bus)); + + hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn)); + if (!hpdev) + return; + + _hv_pcifront_write_config(hpdev, reg, bytes, data); +} + +static int +vmbus_pcib_route_intr(device_t pcib, device_t dev, int pin) +{ + /* We only support MSI/MSI-X and don't support INTx interrupt. */ + return (PCI_INVALID_IRQ); +} + +static int +vmbus_pcib_alloc_msi(device_t pcib, device_t dev, int count, + int maxcount, int *irqs) +{ + return (PCIB_ALLOC_MSI(device_get_parent(pcib), dev, count, maxcount, + irqs)); +} + +static int +vmbus_pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs) +{ + return (PCIB_RELEASE_MSI(device_get_parent(pcib), dev, count, irqs)); +} + +static int +vmbus_pcib_alloc_msix(device_t pcib, device_t dev, int *irq) +{ + return (PCIB_ALLOC_MSIX(device_get_parent(pcib), dev, irq)); +} + +static int +vmbus_pcib_release_msix(device_t pcib, device_t dev, int irq) +{ + return (PCIB_RELEASE_MSIX(device_get_parent(pcib), dev, irq)); +} + +#define MSI_INTEL_ADDR_DEST 0x000ff000 +#define MSI_INTEL_DATA_INTVEC IOART_INTVEC /* Interrupt vector. */ +#define MSI_INTEL_DATA_DELFIXED IOART_DELFIXED + +static int +vmbus_pcib_map_msi(device_t pcib, device_t child, int irq, + uint64_t *addr, uint32_t *data) +{ + unsigned int devfn; + struct hv_pci_dev *hpdev; + + uint64_t v_addr; + uint32_t v_data; + struct hv_irq_desc *hid, *tmp_hid; + unsigned int cpu, vcpu_id; + unsigned int vector; + + struct vmbus_pcib_softc *sc = device_get_softc(pcib); + struct pci_create_interrupt *int_pkt; + struct compose_comp_ctxt comp; + struct { + struct pci_packet pkt; + uint8_t buffer[sizeof(struct pci_create_interrupt)]; + } ctxt; + + int ret; + + devfn = PCI_DEVFN(pci_get_slot(child), pci_get_function(child)); + hpdev = get_pcichild_wslot(sc->hbus, devfn_to_wslot(devfn)); + if (!hpdev) + return (ENOENT); + + ret = PCIB_MAP_MSI(device_get_parent(pcib), child, irq, + &v_addr, &v_data); + if (ret) + return (ret); + + TAILQ_FOREACH_SAFE(hid, &hpdev->irq_desc_list, link, tmp_hid) { + if (hid->irq == irq) { + TAILQ_REMOVE(&hpdev->irq_desc_list, hid, link); + hv_int_desc_free(hpdev, hid); + break; + } + } + + cpu = (v_addr & MSI_INTEL_ADDR_DEST) >> 12; + vcpu_id = VMBUS_GET_VCPU_ID(device_get_parent(pcib), pcib, cpu); + vector = v_data & MSI_INTEL_DATA_INTVEC; + + init_completion(&comp.comp_pkt.host_event); + + memset(&ctxt, 0, sizeof(ctxt)); + ctxt.pkt.completion_func = hv_pci_compose_compl; + ctxt.pkt.compl_ctxt = ∁ + + int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message; + int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE; + int_pkt->wslot.val = hpdev->desc.wslot.val; + int_pkt->int_desc.vector = vector; + int_pkt->int_desc.vector_count = 1; + int_pkt->int_desc.delivery_mode = MSI_INTEL_DATA_DELFIXED; + int_pkt->int_desc.cpu_mask = 1ULL << vcpu_id; + + ret = vmbus_chan_send(sc->chan, VMBUS_CHANPKT_TYPE_INBAND, + VMBUS_CHANPKT_FLAG_RC, int_pkt, sizeof(*int_pkt), + (uint64_t)&ctxt.pkt); + if (ret) { + free_completion(&comp.comp_pkt.host_event); + return (ret); + } + + wait_for_completion(&comp.comp_pkt.host_event); + free_completion(&comp.comp_pkt.host_event); + + if (comp.comp_pkt.completion_status < 0) + return (EPROTO); + + *addr = comp.int_desc.address; + *data = comp.int_desc.data; + + hid = malloc(sizeof(struct hv_irq_desc), M_DEVBUF, M_WAITOK | M_ZERO); + hid->irq = irq; + hid->desc = comp.int_desc; + TAILQ_INSERT_TAIL(&hpdev->irq_desc_list, hid, link); + + return (0); +} + +static device_method_t vmbus_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, vmbus_pcib_probe), + DEVMETHOD(device_attach, vmbus_pcib_attach), + DEVMETHOD(device_detach, vmbus_pcib_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_read_ivar, vmbus_pcib_read_ivar), + DEVMETHOD(bus_write_ivar, vmbus_pcib_write_ivar), + DEVMETHOD(bus_alloc_resource, vmbus_pcib_alloc_resource), + DEVMETHOD(bus_release_resource, vmbus_pcib_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), +#if __FreeBSD_version >= 1100000 + DEVMETHOD(bus_get_cpus, vmbus_pcib_get_cpus), +#endif + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, pcib_maxslots), + DEVMETHOD(pcib_read_config, vmbus_pcib_read_config), + DEVMETHOD(pcib_write_config, vmbus_pcib_write_config), + DEVMETHOD(pcib_route_interrupt, vmbus_pcib_route_intr), + DEVMETHOD(pcib_alloc_msi, vmbus_pcib_alloc_msi), + DEVMETHOD(pcib_release_msi, vmbus_pcib_release_msi), + DEVMETHOD(pcib_alloc_msix, vmbus_pcib_alloc_msix), + DEVMETHOD(pcib_release_msix, vmbus_pcib_release_msix), + DEVMETHOD(pcib_map_msi, vmbus_pcib_map_msi), + + DEVMETHOD_END +}; + +static devclass_t pcib_devclass; + +DEFINE_CLASS_0(pcib, vmbus_pcib_driver, vmbus_pcib_methods, + sizeof(struct vmbus_pcib_softc)); +DRIVER_MODULE(vmbus_pcib, vmbus, vmbus_pcib_driver, pcib_devclass, 0, 0); +MODULE_DEPEND(vmbus_pcib, vmbus, 1, 1, 1); +MODULE_DEPEND(vmbus_pcib, pci, 1, 1, 1); diff --git a/sys/dev/hyperv/utilities/hv_snapshot.c b/sys/dev/hyperv/utilities/hv_snapshot.c new file mode 100644 index 00000000000..23162973f2c --- /dev/null +++ b/sys/dev/hyperv/utilities/hv_snapshot.c @@ -0,0 +1,1061 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * 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 ``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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "hv_util.h" +#include "hv_snapshot.h" +#include "vmbus_if.h" + +#define VSS_MAJOR 5 +#define VSS_MINOR 0 +#define VSS_MSGVER VMBUS_IC_VERSION(VSS_MAJOR, VSS_MINOR) + +#define VSS_FWVER_MAJOR 3 +#define VSS_FWVER VMBUS_IC_VERSION(VSS_FWVER_MAJOR, 0) + +#define TIMEOUT_LIMIT (15) // seconds +enum hv_vss_op { + VSS_OP_CREATE = 0, + VSS_OP_DELETE, + VSS_OP_HOT_BACKUP, + VSS_OP_GET_DM_INFO, + VSS_OP_BU_COMPLETE, + /* + * Following operations are only supported with IC version >= 5.0 + */ + VSS_OP_FREEZE, /* Freeze the file systems in the VM */ + VSS_OP_THAW, /* Unfreeze the file systems */ + VSS_OP_AUTO_RECOVER, + VSS_OP_COUNT /* Number of operations, must be last */ +}; + +/* + * Header for all VSS messages. + */ +struct hv_vss_hdr { + struct vmbus_icmsg_hdr ic_hdr; + uint8_t operation; + uint8_t reserved[7]; +} __packed; + + +/* + * Flag values for the hv_vss_check_feature. Here supports only + * one value. + */ +#define VSS_HBU_NO_AUTO_RECOVERY 0x00000005 + +struct hv_vss_check_feature { + uint32_t flags; +} __packed; + +struct hv_vss_check_dm_info { + uint32_t flags; +} __packed; + +struct hv_vss_msg { + union { + struct hv_vss_hdr vss_hdr; + } hdr; + union { + struct hv_vss_check_feature vss_cf; + struct hv_vss_check_dm_info dm_info; + } body; +} __packed; + +struct hv_vss_req { + struct hv_vss_opt_msg opt_msg; /* used to communicate with daemon */ + struct hv_vss_msg msg; /* used to communicate with host */ +} __packed; + +/* hv_vss debug control */ +static int hv_vss_log = 0; + +#define hv_vss_log_error(...) do { \ + if (hv_vss_log > 0) \ + log(LOG_ERR, "hv_vss: " __VA_ARGS__); \ +} while (0) + +#define hv_vss_log_info(...) do { \ + if (hv_vss_log > 1) \ + log(LOG_INFO, "hv_vss: " __VA_ARGS__); \ +} while (0) + +static const struct vmbus_ic_desc vmbus_vss_descs[] = { + { + .ic_guid = { .hv_guid = { + 0x29, 0x2e, 0xfa, 0x35, 0x23, 0xea, 0x36, 0x42, + 0x96, 0xae, 0x3a, 0x6e, 0xba, 0xcb, 0xa4, 0x40} }, + .ic_desc = "Hyper-V VSS" + }, + VMBUS_IC_DESC_END +}; + +static const char * vss_opt_name[] = {"None", "VSSCheck", "Freeze", "Thaw"}; + +/* character device prototypes */ +static d_open_t hv_vss_dev_open; +static d_close_t hv_vss_dev_close; +static d_poll_t hv_vss_dev_daemon_poll; +static d_ioctl_t hv_vss_dev_daemon_ioctl; + +static d_open_t hv_appvss_dev_open; +static d_close_t hv_appvss_dev_close; +static d_poll_t hv_appvss_dev_poll; +static d_ioctl_t hv_appvss_dev_ioctl; + +/* hv_vss character device structure */ +static struct cdevsw hv_vss_cdevsw = +{ + .d_version = D_VERSION, + .d_open = hv_vss_dev_open, + .d_close = hv_vss_dev_close, + .d_poll = hv_vss_dev_daemon_poll, + .d_ioctl = hv_vss_dev_daemon_ioctl, + .d_name = FS_VSS_DEV_NAME, +}; + +static struct cdevsw hv_appvss_cdevsw = +{ + .d_version = D_VERSION, + .d_open = hv_appvss_dev_open, + .d_close = hv_appvss_dev_close, + .d_poll = hv_appvss_dev_poll, + .d_ioctl = hv_appvss_dev_ioctl, + .d_name = APP_VSS_DEV_NAME, +}; + +struct hv_vss_sc; +/* + * Global state to track cdev + */ +struct hv_vss_dev_sc { + /* + * msg was transferred from host to notify queue, and + * ack queue. Finally, it was recyled to free list. + */ + STAILQ_HEAD(, hv_vss_req_internal) to_notify_queue; + STAILQ_HEAD(, hv_vss_req_internal) to_ack_queue; + struct hv_vss_sc *sc; + struct proc *proc_task; + struct selinfo hv_vss_selinfo; +}; +/* + * Global state to track and synchronize the transaction requests from the host. + * The VSS allows user to register their function to do freeze/thaw for application. + * VSS kernel will notify both vss daemon and user application if it is registered. + * The implementation state transition is illustrated by: + * https://clovertrail.github.io/assets/vssdot.png + */ +typedef struct hv_vss_sc { + struct hv_util_sc util_sc; + device_t dev; + + struct task task; + + /* + * mutex is used to protect access of list/queue, + * callout in request is also used this mutex. + */ + struct mtx pending_mutex; + /* + * req_free_list contains all free items + */ + LIST_HEAD(, hv_vss_req_internal) req_free_list; + + /* Indicates if daemon registered with driver */ + boolean_t register_done; + + boolean_t app_register_done; + + /* cdev for file system freeze/thaw */ + struct cdev *hv_vss_dev; + /* cdev for application freeze/thaw */ + struct cdev *hv_appvss_dev; + + /* sc for app */ + struct hv_vss_dev_sc app_sc; + /* sc for deamon */ + struct hv_vss_dev_sc daemon_sc; +} hv_vss_sc; + +typedef struct hv_vss_req_internal { + LIST_ENTRY(hv_vss_req_internal) link; + STAILQ_ENTRY(hv_vss_req_internal) slink; + struct hv_vss_req vss_req; + + /* Rcv buffer for communicating with the host*/ + uint8_t *rcv_buf; + /* Length of host message */ + uint32_t host_msg_len; + /* Host message id */ + uint64_t host_msg_id; + + hv_vss_sc *sc; + + struct callout callout; +} hv_vss_req_internal; + +#define SEARCH_REMOVE_REQ_LOCKED(reqp, queue, link, tmp, id) \ + do { \ + STAILQ_FOREACH_SAFE(reqp, queue, link, tmp) { \ + if (reqp->vss_req.opt_msg.msgid == id) { \ + STAILQ_REMOVE(queue, \ + reqp, hv_vss_req_internal, link); \ + break; \ + } \ + } \ + } while (0) + +static bool +hv_vss_is_daemon_killed_after_launch(hv_vss_sc *sc) +{ + return (!sc->register_done && sc->daemon_sc.proc_task); +} + +/* + * Callback routine that gets called whenever there is a message from host + */ +static void +hv_vss_callback(struct vmbus_channel *chan __unused, void *context) +{ + hv_vss_sc *sc = (hv_vss_sc*)context; + if (hv_vss_is_daemon_killed_after_launch(sc)) + hv_vss_log_info("%s: daemon was killed!\n", __func__); + if (sc->register_done || sc->daemon_sc.proc_task) { + hv_vss_log_info("%s: Queuing work item\n", __func__); + if (hv_vss_is_daemon_killed_after_launch(sc)) + hv_vss_log_info("%s: daemon was killed!\n", __func__); + taskqueue_enqueue(taskqueue_thread, &sc->task); + } else { + hv_vss_log_info("%s: daemon has never been registered\n", __func__); + } + hv_vss_log_info("%s: received msg from host\n", __func__); +} +/* + * Send the response back to the host. + */ +static void +hv_vss_respond_host(uint8_t *rcv_buf, struct vmbus_channel *ch, + uint32_t recvlen, uint64_t requestid, uint32_t error) +{ + struct vmbus_icmsg_hdr *hv_icmsg_hdrp; + + hv_icmsg_hdrp = (struct vmbus_icmsg_hdr *)rcv_buf; + + hv_icmsg_hdrp->ic_status = error; + hv_icmsg_hdrp->ic_flags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; + + error = vmbus_chan_send(ch, VMBUS_CHANPKT_TYPE_INBAND, 0, + rcv_buf, recvlen, requestid); + if (error) + hv_vss_log_info("%s: hv_vss_respond_host: sendpacket error:%d\n", + __func__, error); +} + +static void +hv_vss_notify_host_result_locked(struct hv_vss_req_internal *reqp, uint32_t status) +{ + struct hv_vss_msg* msg = (struct hv_vss_msg *)reqp->rcv_buf; + hv_vss_sc *sc = reqp->sc; + if (reqp->vss_req.opt_msg.opt == HV_VSS_CHECK) { + msg->body.vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY; + } + hv_vss_log_info("%s, %s response %s to host\n", __func__, + vss_opt_name[reqp->vss_req.opt_msg.opt], + status == HV_S_OK ? "Success" : "Fail"); + hv_vss_respond_host(reqp->rcv_buf, vmbus_get_channel(reqp->sc->dev), + reqp->host_msg_len, reqp->host_msg_id, status); + /* recycle the request */ + LIST_INSERT_HEAD(&sc->req_free_list, reqp, link); +} + +static void +hv_vss_notify_host_result(struct hv_vss_req_internal *reqp, uint32_t status) +{ + mtx_lock(&reqp->sc->pending_mutex); + hv_vss_notify_host_result_locked(reqp, status); + mtx_unlock(&reqp->sc->pending_mutex); +} + +static void +hv_vss_cp_vssreq_to_user(struct hv_vss_req_internal *reqp, + struct hv_vss_opt_msg *userdata) +{ + struct hv_vss_req *hv_vss_dev_buf; + hv_vss_dev_buf = &reqp->vss_req; + hv_vss_dev_buf->opt_msg.opt = HV_VSS_NONE; + switch (reqp->vss_req.msg.hdr.vss_hdr.operation) { + case VSS_OP_FREEZE: + hv_vss_dev_buf->opt_msg.opt = HV_VSS_FREEZE; + break; + case VSS_OP_THAW: + hv_vss_dev_buf->opt_msg.opt = HV_VSS_THAW; + break; + case VSS_OP_HOT_BACKUP: + hv_vss_dev_buf->opt_msg.opt = HV_VSS_CHECK; + break; + } + *userdata = hv_vss_dev_buf->opt_msg; + hv_vss_log_info("%s, read data from user for " + "%s (%ju) \n", __func__, vss_opt_name[userdata->opt], + (uintmax_t)userdata->msgid); +} + +/** + * Remove the request id from app notifiy or ack queue, + * and recyle the request by inserting it to free list. + * + * When app was notified but not yet sending ack, the request + * should locate in either notify queue or ack queue. + */ +static struct hv_vss_req_internal* +hv_vss_drain_req_queue_locked(hv_vss_sc *sc, uint64_t req_id) +{ + struct hv_vss_req_internal *reqp, *tmp; + SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->daemon_sc.to_notify_queue, + slink, tmp, req_id); + if (reqp == NULL) + SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->daemon_sc.to_ack_queue, + slink, tmp, req_id); + if (reqp == NULL) + SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->app_sc.to_notify_queue, + slink, tmp, req_id); + if (reqp == NULL) + SEARCH_REMOVE_REQ_LOCKED(reqp, &sc->app_sc.to_ack_queue, slink, + tmp, req_id); + return (reqp); +} +/** + * Actions for daemon who has been notified. + */ +static void +hv_vss_notified(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata) +{ + struct hv_vss_req_internal *reqp; + mtx_lock(&dev_sc->sc->pending_mutex); + if (!STAILQ_EMPTY(&dev_sc->to_notify_queue)) { + reqp = STAILQ_FIRST(&dev_sc->to_notify_queue); + hv_vss_cp_vssreq_to_user(reqp, userdata); + STAILQ_REMOVE_HEAD(&dev_sc->to_notify_queue, slink); + /* insert the msg to queue for write */ + STAILQ_INSERT_TAIL(&dev_sc->to_ack_queue, reqp, slink); + userdata->status = VSS_SUCCESS; + } else { + /* Timeout occur, thus request was removed from queue. */ + hv_vss_log_info("%s: notify queue is empty!\n", __func__); + userdata->status = VSS_FAIL; + } + mtx_unlock(&dev_sc->sc->pending_mutex); +} + +static void +hv_vss_notify(struct hv_vss_dev_sc *dev_sc, struct hv_vss_req_internal *reqp) +{ + uint32_t opt = reqp->vss_req.opt_msg.opt; + mtx_lock(&dev_sc->sc->pending_mutex); + STAILQ_INSERT_TAIL(&dev_sc->to_notify_queue, reqp, slink); + hv_vss_log_info("%s: issuing query %s (%ju) to %s\n", __func__, + vss_opt_name[opt], (uintmax_t)reqp->vss_req.opt_msg.msgid, + &dev_sc->sc->app_sc == dev_sc ? "app" : "daemon"); + mtx_unlock(&dev_sc->sc->pending_mutex); + selwakeup(&dev_sc->hv_vss_selinfo); +} + +/** + * Actions for daemon who has acknowledged. + */ +static void +hv_vss_daemon_acked(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata) +{ + struct hv_vss_req_internal *reqp, *tmp; + uint64_t req_id; + int opt; + uint32_t status; + + opt = userdata->opt; + req_id = userdata->msgid; + status = userdata->status; + /* make sure the reserved fields are all zeros. */ + memset(&userdata->reserved, 0, sizeof(struct hv_vss_opt_msg) - + __offsetof(struct hv_vss_opt_msg, reserved)); + mtx_lock(&dev_sc->sc->pending_mutex); + SEARCH_REMOVE_REQ_LOCKED(reqp, &dev_sc->to_ack_queue, slink, tmp, req_id); + mtx_unlock(&dev_sc->sc->pending_mutex); + if (reqp == NULL) { + hv_vss_log_info("%s Timeout: fail to find daemon ack request\n", + __func__); + userdata->status = VSS_FAIL; + return; + } + KASSERT(opt == reqp->vss_req.opt_msg.opt, ("Mismatched VSS operation!")); + hv_vss_log_info("%s, get response %d from daemon for %s (%ju) \n", __func__, + status, vss_opt_name[opt], (uintmax_t)req_id); + switch (opt) { + case HV_VSS_CHECK: + case HV_VSS_FREEZE: + callout_drain(&reqp->callout); + hv_vss_notify_host_result(reqp, + status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL); + break; + case HV_VSS_THAW: + if (dev_sc->sc->app_register_done) { + if (status == VSS_SUCCESS) { + hv_vss_notify(&dev_sc->sc->app_sc, reqp); + } else { + /* handle error */ + callout_drain(&reqp->callout); + hv_vss_notify_host_result(reqp, HV_E_FAIL); + } + } else { + callout_drain(&reqp->callout); + hv_vss_notify_host_result(reqp, + status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL); + } + break; + } +} + +/** + * Actions for app who has acknowledged. + */ +static void +hv_vss_app_acked(struct hv_vss_dev_sc *dev_sc, struct hv_vss_opt_msg *userdata) +{ + struct hv_vss_req_internal *reqp, *tmp; + uint64_t req_id; + int opt; + uint8_t status; + + opt = userdata->opt; + req_id = userdata->msgid; + status = userdata->status; + /* make sure the reserved fields are all zeros. */ + memset(&userdata->reserved, 0, sizeof(struct hv_vss_opt_msg) - + __offsetof(struct hv_vss_opt_msg, reserved)); + mtx_lock(&dev_sc->sc->pending_mutex); + SEARCH_REMOVE_REQ_LOCKED(reqp, &dev_sc->to_ack_queue, slink, tmp, req_id); + mtx_unlock(&dev_sc->sc->pending_mutex); + if (reqp == NULL) { + hv_vss_log_info("%s Timeout: fail to find app ack request\n", + __func__); + userdata->status = VSS_FAIL; + return; + } + KASSERT(opt == reqp->vss_req.opt_msg.opt, ("Mismatched VSS operation!")); + hv_vss_log_info("%s, get response %d from app for %s (%ju) \n", + __func__, status, vss_opt_name[opt], (uintmax_t)req_id); + if (dev_sc->sc->register_done) { + switch (opt) { + case HV_VSS_CHECK: + case HV_VSS_FREEZE: + if (status == VSS_SUCCESS) { + hv_vss_notify(&dev_sc->sc->daemon_sc, reqp); + } else { + /* handle error */ + callout_drain(&reqp->callout); + hv_vss_notify_host_result(reqp, HV_E_FAIL); + } + break; + case HV_VSS_THAW: + callout_drain(&reqp->callout); + hv_vss_notify_host_result(reqp, + status == VSS_SUCCESS ? HV_S_OK : HV_E_FAIL); + break; + } + } else { + hv_vss_log_info("%s, Fatal: vss daemon was killed\n", __func__); + } +} + +static int +hv_vss_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) +{ + struct proc *td_proc; + td_proc = td->td_proc; + + struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1; + hv_vss_log_info("%s: %s opens device \"%s\" successfully.\n", + __func__, td_proc->p_comm, FS_VSS_DEV_NAME); + + if (dev_sc->sc->register_done) + return (EBUSY); + + dev_sc->sc->register_done = true; + hv_vss_callback(vmbus_get_channel(dev_sc->sc->dev), dev_sc->sc); + + dev_sc->proc_task = curproc; + return (0); +} + +static int +hv_vss_dev_close(struct cdev *dev, int fflag __unused, int devtype __unused, + struct thread *td) +{ + struct proc *td_proc; + td_proc = td->td_proc; + + struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1; + + hv_vss_log_info("%s: %s closes device \"%s\"\n", + __func__, td_proc->p_comm, FS_VSS_DEV_NAME); + dev_sc->sc->register_done = false; + return (0); +} + +static int +hv_vss_dev_daemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, + struct thread *td) +{ + struct proc *td_proc; + struct hv_vss_dev_sc *sc; + + td_proc = td->td_proc; + sc = (struct hv_vss_dev_sc*)dev->si_drv1; + + hv_vss_log_info("%s: %s invoked vss ioctl\n", __func__, td_proc->p_comm); + + struct hv_vss_opt_msg* userdata = (struct hv_vss_opt_msg*)data; + switch(cmd) { + case IOCHVVSSREAD: + hv_vss_notified(sc, userdata); + break; + case IOCHVVSSWRITE: + hv_vss_daemon_acked(sc, userdata); + break; + } + return (0); +} + +/* + * hv_vss_daemon poll invokes this function to check if data is available + * for daemon to read. + */ +static int +hv_vss_dev_daemon_poll(struct cdev *dev, int events, struct thread *td) +{ + int revent = 0; + struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1; + + mtx_lock(&dev_sc->sc->pending_mutex); + /** + * if there is data ready, inform daemon's poll + */ + if (!STAILQ_EMPTY(&dev_sc->to_notify_queue)) + revent = POLLIN; + if (revent == 0) + selrecord(td, &dev_sc->hv_vss_selinfo); + hv_vss_log_info("%s return 0x%x\n", __func__, revent); + mtx_unlock(&dev_sc->sc->pending_mutex); + return (revent); +} + +static int +hv_appvss_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) +{ + struct proc *td_proc; + td_proc = td->td_proc; + + struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1; + hv_vss_log_info("%s: %s opens device \"%s\" successfully.\n", + __func__, td_proc->p_comm, APP_VSS_DEV_NAME); + + if (dev_sc->sc->app_register_done) + return (EBUSY); + + dev_sc->sc->app_register_done = true; + dev_sc->proc_task = curproc; + return (0); +} + +static int +hv_appvss_dev_close(struct cdev *dev, int fflag __unused, int devtype __unused, + struct thread *td) +{ + struct proc *td_proc; + td_proc = td->td_proc; + + struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1; + + hv_vss_log_info("%s: %s closes device \"%s\".\n", + __func__, td_proc->p_comm, APP_VSS_DEV_NAME); + dev_sc->sc->app_register_done = false; + return (0); +} + +static int +hv_appvss_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, + struct thread *td) +{ + struct proc *td_proc; + struct hv_vss_dev_sc *dev_sc; + + td_proc = td->td_proc; + dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1; + + hv_vss_log_info("%s: %s invoked vss ioctl\n", __func__, td_proc->p_comm); + + struct hv_vss_opt_msg* userdata = (struct hv_vss_opt_msg*)data; + switch(cmd) { + case IOCHVVSSREAD: + hv_vss_notified(dev_sc, userdata); + break; + case IOCHVVSSWRITE: + hv_vss_app_acked(dev_sc, userdata); + break; + } + return (0); +} + +/* + * hv_vss_daemon poll invokes this function to check if data is available + * for daemon to read. + */ +static int +hv_appvss_dev_poll(struct cdev *dev, int events, struct thread *td) +{ + int revent = 0; + struct hv_vss_dev_sc *dev_sc = (struct hv_vss_dev_sc*)dev->si_drv1; + + mtx_lock(&dev_sc->sc->pending_mutex); + /** + * if there is data ready, inform daemon's poll + */ + if (!STAILQ_EMPTY(&dev_sc->to_notify_queue)) + revent = POLLIN; + if (revent == 0) + selrecord(td, &dev_sc->hv_vss_selinfo); + hv_vss_log_info("%s return 0x%x\n", __func__, revent); + mtx_unlock(&dev_sc->sc->pending_mutex); + return (revent); +} + +static void +hv_vss_timeout(void *arg) +{ + hv_vss_req_internal *reqp = arg; + hv_vss_req_internal *request; + hv_vss_sc* sc = reqp->sc; + uint64_t req_id = reqp->vss_req.opt_msg.msgid; + /* This thread is locked */ + KASSERT(mtx_owned(&sc->pending_mutex), ("mutex lock is not owned!")); + request = hv_vss_drain_req_queue_locked(sc, req_id); + KASSERT(request != NULL, ("timeout but fail to find request")); + hv_vss_notify_host_result_locked(reqp, HV_E_FAIL); +} + +/* + * This routine is called whenever a message is received from the host + */ +static void +hv_vss_init_req(hv_vss_req_internal *reqp, + uint32_t recvlen, uint64_t requestid, uint8_t *vss_buf, hv_vss_sc *sc) +{ + struct timespec vm_ts; + struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf; + + memset(reqp, 0, __offsetof(hv_vss_req_internal, callout)); + reqp->host_msg_len = recvlen; + reqp->host_msg_id = requestid; + reqp->rcv_buf = vss_buf; + reqp->sc = sc; + memcpy(&reqp->vss_req.msg, + (struct hv_vss_msg *)vss_buf, sizeof(struct hv_vss_msg)); + /* set the opt for users */ + switch (msg->hdr.vss_hdr.operation) { + case VSS_OP_FREEZE: + reqp->vss_req.opt_msg.opt = HV_VSS_FREEZE; + break; + case VSS_OP_THAW: + reqp->vss_req.opt_msg.opt = HV_VSS_THAW; + break; + case VSS_OP_HOT_BACKUP: + reqp->vss_req.opt_msg.opt = HV_VSS_CHECK; + break; + } + /* Use a timestamp as msg request ID */ + nanotime(&vm_ts); + reqp->vss_req.opt_msg.msgid = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec; +} + +static hv_vss_req_internal* +hv_vss_get_new_req_locked(hv_vss_sc *sc) +{ + hv_vss_req_internal *reqp; + if (!STAILQ_EMPTY(&sc->daemon_sc.to_notify_queue) || + !STAILQ_EMPTY(&sc->daemon_sc.to_ack_queue) || + !STAILQ_EMPTY(&sc->app_sc.to_notify_queue) || + !STAILQ_EMPTY(&sc->app_sc.to_ack_queue)) { + /* + * There is request coming from host before + * finishing previous requests + */ + hv_vss_log_info("%s: Warning: there is new request " + "coming before finishing previous requests\n", __func__); + return (NULL); + } + if (LIST_EMPTY(&sc->req_free_list)) { + /* TODO Error: no buffer */ + hv_vss_log_info("Error: No buffer\n"); + return (NULL); + } + reqp = LIST_FIRST(&sc->req_free_list); + LIST_REMOVE(reqp, link); + return (reqp); +} + +static void +hv_vss_start_notify(hv_vss_req_internal *reqp, uint32_t opt) +{ + hv_vss_sc *sc = reqp->sc; + /* + * Freeze/Check notification sequence: kernel -> app -> daemon(fs) + * Thaw notification sequence: kernel -> daemon(fs) -> app + * + * We should wake up the daemon, in case it's doing poll(). + * The response should be received after 5s, otherwise, trigger timeout. + */ + switch (opt) { + case VSS_OP_FREEZE: + case VSS_OP_HOT_BACKUP: + if (sc->app_register_done) + hv_vss_notify(&sc->app_sc, reqp); + else + hv_vss_notify(&sc->daemon_sc, reqp); + callout_reset(&reqp->callout, TIMEOUT_LIMIT * hz, + hv_vss_timeout, reqp); + break; + case VSS_OP_THAW: + hv_vss_notify(&sc->daemon_sc, reqp); + callout_reset(&reqp->callout, TIMEOUT_LIMIT * hz, + hv_vss_timeout, reqp); + break; + } +} + +/* + * Function to read the vss request buffer from host + * and interact with daemon + */ +static void +hv_vss_process_request(void *context, int pending __unused) +{ + uint8_t *vss_buf; + struct vmbus_channel *channel; + uint32_t recvlen = 0; + uint64_t requestid; + struct vmbus_icmsg_hdr *icmsghdrp; + int ret = 0; + hv_vss_sc *sc; + hv_vss_req_internal *reqp; + + hv_vss_log_info("%s: entering hv_vss_process_request\n", __func__); + + sc = (hv_vss_sc*)context; + vss_buf = sc->util_sc.receive_buffer; + channel = vmbus_get_channel(sc->dev); + + recvlen = sc->util_sc.ic_buflen; + ret = vmbus_chan_recv(channel, vss_buf, &recvlen, &requestid); + KASSERT(ret != ENOBUFS, ("hvvss recvbuf is not large enough")); + /* XXX check recvlen to make sure that it contains enough data */ + + while ((ret == 0) && (recvlen > 0)) { + icmsghdrp = (struct vmbus_icmsg_hdr *)vss_buf; + + if (icmsghdrp->ic_type == HV_ICMSGTYPE_NEGOTIATE) { + ret = vmbus_ic_negomsg(&sc->util_sc, vss_buf, + &recvlen, VSS_FWVER, VSS_MSGVER); + hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev), + recvlen, requestid, ret); + hv_vss_log_info("%s: version negotiated\n", __func__); + } else if (!hv_vss_is_daemon_killed_after_launch(sc)) { + struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf; + switch(msg->hdr.vss_hdr.operation) { + case VSS_OP_FREEZE: + case VSS_OP_THAW: + case VSS_OP_HOT_BACKUP: + mtx_lock(&sc->pending_mutex); + reqp = hv_vss_get_new_req_locked(sc); + mtx_unlock(&sc->pending_mutex); + if (reqp == NULL) { + /* ignore this request from host */ + break; + } + hv_vss_init_req(reqp, recvlen, requestid, vss_buf, sc); + hv_vss_log_info("%s: receive %s (%ju) from host\n", + __func__, + vss_opt_name[reqp->vss_req.opt_msg.opt], + (uintmax_t)reqp->vss_req.opt_msg.msgid); + hv_vss_start_notify(reqp, msg->hdr.vss_hdr.operation); + break; + case VSS_OP_GET_DM_INFO: + hv_vss_log_info("%s: receive GET_DM_INFO from host\n", + __func__); + msg->body.dm_info.flags = 0; + hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev), + recvlen, requestid, HV_S_OK); + break; + default: + device_printf(sc->dev, "Unknown opt from host: %d\n", + msg->hdr.vss_hdr.operation); + break; + } + } else { + /* daemon was killed for some reason after it was launched */ + struct hv_vss_msg* msg = (struct hv_vss_msg *)vss_buf; + switch(msg->hdr.vss_hdr.operation) { + case VSS_OP_FREEZE: + hv_vss_log_info("%s: response fail for FREEZE\n", + __func__); + break; + case VSS_OP_THAW: + hv_vss_log_info("%s: response fail for THAW\n", + __func__); + break; + case VSS_OP_HOT_BACKUP: + hv_vss_log_info("%s: response fail for HOT_BACKUP\n", + __func__); + msg->body.vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY; + break; + case VSS_OP_GET_DM_INFO: + hv_vss_log_info("%s: response fail for GET_DM_INFO\n", + __func__); + msg->body.dm_info.flags = 0; + break; + default: + device_printf(sc->dev, "Unknown opt from host: %d\n", + msg->hdr.vss_hdr.operation); + break; + } + hv_vss_respond_host(vss_buf, vmbus_get_channel(sc->dev), + recvlen, requestid, HV_E_FAIL); + } + /* + * Try reading next buffer + */ + recvlen = sc->util_sc.ic_buflen; + ret = vmbus_chan_recv(channel, vss_buf, &recvlen, &requestid); + KASSERT(ret != ENOBUFS, ("hvvss recvbuf is not large enough")); + /* XXX check recvlen to make sure that it contains enough data */ + + hv_vss_log_info("%s: read: context %p, ret =%d, recvlen=%d\n", + __func__, context, ret, recvlen); + } +} + +static int +hv_vss_probe(device_t dev) +{ + return (vmbus_ic_probe(dev, vmbus_vss_descs)); +} + +static int +hv_vss_init_send_receive_queue(device_t dev) +{ + hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev); + int i; + const int max_list = 4; /* It is big enough for the list */ + struct hv_vss_req_internal* reqp; + + LIST_INIT(&sc->req_free_list); + STAILQ_INIT(&sc->daemon_sc.to_notify_queue); + STAILQ_INIT(&sc->daemon_sc.to_ack_queue); + STAILQ_INIT(&sc->app_sc.to_notify_queue); + STAILQ_INIT(&sc->app_sc.to_ack_queue); + + for (i = 0; i < max_list; i++) { + reqp = malloc(sizeof(struct hv_vss_req_internal), + M_DEVBUF, M_WAITOK|M_ZERO); + LIST_INSERT_HEAD(&sc->req_free_list, reqp, link); + callout_init_mtx(&reqp->callout, &sc->pending_mutex, 0); + } + return (0); +} + +static int +hv_vss_destroy_send_receive_queue(device_t dev) +{ + hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev); + hv_vss_req_internal* reqp; + + while (!LIST_EMPTY(&sc->req_free_list)) { + reqp = LIST_FIRST(&sc->req_free_list); + LIST_REMOVE(reqp, link); + free(reqp, M_DEVBUF); + } + + while (!STAILQ_EMPTY(&sc->daemon_sc.to_notify_queue)) { + reqp = STAILQ_FIRST(&sc->daemon_sc.to_notify_queue); + STAILQ_REMOVE_HEAD(&sc->daemon_sc.to_notify_queue, slink); + free(reqp, M_DEVBUF); + } + + while (!STAILQ_EMPTY(&sc->daemon_sc.to_ack_queue)) { + reqp = STAILQ_FIRST(&sc->daemon_sc.to_ack_queue); + STAILQ_REMOVE_HEAD(&sc->daemon_sc.to_ack_queue, slink); + free(reqp, M_DEVBUF); + } + + while (!STAILQ_EMPTY(&sc->app_sc.to_notify_queue)) { + reqp = STAILQ_FIRST(&sc->app_sc.to_notify_queue); + STAILQ_REMOVE_HEAD(&sc->app_sc.to_notify_queue, slink); + free(reqp, M_DEVBUF); + } + + while (!STAILQ_EMPTY(&sc->app_sc.to_ack_queue)) { + reqp = STAILQ_FIRST(&sc->app_sc.to_ack_queue); + STAILQ_REMOVE_HEAD(&sc->app_sc.to_ack_queue, slink); + free(reqp, M_DEVBUF); + } + return (0); +} + +static int +hv_vss_attach(device_t dev) +{ + int error; + struct sysctl_oid_list *child; + struct sysctl_ctx_list *ctx; + + hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev); + + sc->dev = dev; + mtx_init(&sc->pending_mutex, "hv_vss pending mutex", NULL, MTX_DEF); + + ctx = device_get_sysctl_ctx(dev); + child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); + + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "hv_vss_log", + CTLFLAG_RWTUN, &hv_vss_log, 0, "Hyperv VSS service log level"); + + TASK_INIT(&sc->task, 0, hv_vss_process_request, sc); + hv_vss_init_send_receive_queue(dev); + /* create character device for file system freeze/thaw */ + error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, + &sc->hv_vss_dev, + &hv_vss_cdevsw, + 0, + UID_ROOT, + GID_WHEEL, + 0640, + FS_VSS_DEV_NAME); + + if (error != 0) { + hv_vss_log_info("Fail to create '%s': %d\n", FS_VSS_DEV_NAME, error); + return (error); + } + sc->hv_vss_dev->si_drv1 = &sc->daemon_sc; + sc->daemon_sc.sc = sc; + /* create character device for application freeze/thaw */ + error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, + &sc->hv_appvss_dev, + &hv_appvss_cdevsw, + 0, + UID_ROOT, + GID_WHEEL, + 0640, + APP_VSS_DEV_NAME); + + if (error != 0) { + hv_vss_log_info("Fail to create '%s': %d\n", APP_VSS_DEV_NAME, error); + return (error); + } + sc->hv_appvss_dev->si_drv1 = &sc->app_sc; + sc->app_sc.sc = sc; + + return hv_util_attach(dev, hv_vss_callback); +} + +static int +hv_vss_detach(device_t dev) +{ + hv_vss_sc *sc = (hv_vss_sc*)device_get_softc(dev); + mtx_destroy(&sc->pending_mutex); + if (sc->daemon_sc.proc_task != NULL) { + PROC_LOCK(sc->daemon_sc.proc_task); + kern_psignal(sc->daemon_sc.proc_task, SIGKILL); + PROC_UNLOCK(sc->daemon_sc.proc_task); + } + if (sc->app_sc.proc_task != NULL) { + PROC_LOCK(sc->app_sc.proc_task); + kern_psignal(sc->app_sc.proc_task, SIGKILL); + PROC_UNLOCK(sc->app_sc.proc_task); + } + hv_vss_destroy_send_receive_queue(dev); + destroy_dev(sc->hv_vss_dev); + destroy_dev(sc->hv_appvss_dev); + return hv_util_detach(dev); +} + +static device_method_t vss_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, hv_vss_probe), + DEVMETHOD(device_attach, hv_vss_attach), + DEVMETHOD(device_detach, hv_vss_detach), + { 0, 0 } +}; + +static driver_t vss_driver = { "hvvss", vss_methods, sizeof(hv_vss_sc)}; + +static devclass_t vss_devclass; + +DRIVER_MODULE(hv_vss, vmbus, vss_driver, vss_devclass, NULL, NULL); +MODULE_VERSION(hv_vss, 1); +MODULE_DEPEND(hv_vss, vmbus, 1, 1, 1); diff --git a/sys/dev/hyperv/utilities/hv_snapshot.h b/sys/dev/hyperv/utilities/hv_snapshot.h new file mode 100644 index 00000000000..e3c9e0c9fef --- /dev/null +++ b/sys/dev/hyperv/utilities/hv_snapshot.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * 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 ``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 _VSS_H +#define _VSS_H +#include +#define FS_VSS_DEV_NAME "hv_fsvss_dev" +#define APP_VSS_DEV_NAME "hv_appvss_dev" + +#define VSS_DEV(VSS) "/dev/"VSS + +#define VSS_SUCCESS 0x00000000 +#define VSS_FAIL 0x00000001 + +enum hv_vss_op_t { + HV_VSS_NONE = 0, + HV_VSS_CHECK, + HV_VSS_FREEZE, + HV_VSS_THAW, + HV_VSS_COUNT +}; + +struct hv_vss_opt_msg { + uint32_t opt; /* operation */ + uint32_t status; /* 0 for success, 1 for error */ + uint64_t msgid; /* an ID used to identify the transaction */ + uint8_t reserved[48]; /* reserved values are all zeroes */ +}; +#define IOCHVVSSREAD _IOR('v', 2, struct hv_vss_opt_msg) +#define IOCHVVSSWRITE _IOW('v', 3, struct hv_vss_opt_msg) +#endif diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c index 11be35ba4d7..4695d957257 100644 --- a/sys/dev/hyperv/vmbus/vmbus.c +++ b/sys/dev/hyperv/vmbus/vmbus.c @@ -44,10 +44,13 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include +#include #include #include +#include #include #include @@ -58,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include "acpi_if.h" +#include "pcib_if.h" #include "vmbus_if.h" #define VMBUS_GPADL_START 0xe1e10 @@ -74,9 +78,25 @@ static int vmbus_read_ivar(device_t, device_t, int, uintptr_t *); static int vmbus_child_pnpinfo_str(device_t, device_t, char *, size_t); +static struct resource *vmbus_alloc_resource(device_t dev, + device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, + rman_res_t count, u_int flags); +static int vmbus_alloc_msi(device_t bus, device_t dev, + int count, int maxcount, int *irqs); +static int vmbus_release_msi(device_t bus, device_t dev, + int count, int *irqs); +static int vmbus_alloc_msix(device_t bus, device_t dev, + int *irq); +static int vmbus_release_msix(device_t bus, device_t dev, + int irq); +static int vmbus_map_msi(device_t bus, device_t dev, + int irq, uint64_t *addr, uint32_t *data); static uint32_t vmbus_get_version_method(device_t, device_t); static int vmbus_probe_guid_method(device_t, device_t, const struct hyperv_guid *); +static uint32_t vmbus_get_vcpu_id_method(device_t bus, + device_t dev, int cpu); static int vmbus_init(struct vmbus_softc *); static int vmbus_connect(struct vmbus_softc *, uint32_t); @@ -131,10 +151,27 @@ static device_method_t vmbus_methods[] = { DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_read_ivar, vmbus_read_ivar), DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str), + DEVMETHOD(bus_alloc_resource, vmbus_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), +#if __FreeBSD_version >= 1100000 + DEVMETHOD(bus_get_cpus, bus_generic_get_cpus), +#endif + + /* pcib interface */ + DEVMETHOD(pcib_alloc_msi, vmbus_alloc_msi), + DEVMETHOD(pcib_release_msi, vmbus_release_msi), + DEVMETHOD(pcib_alloc_msix, vmbus_alloc_msix), + DEVMETHOD(pcib_release_msix, vmbus_release_msix), + DEVMETHOD(pcib_map_msi, vmbus_map_msi), /* Vmbus interface */ DEVMETHOD(vmbus_get_version, vmbus_get_version_method), DEVMETHOD(vmbus_probe_guid, vmbus_probe_guid_method), + DEVMETHOD(vmbus_get_vcpu_id, vmbus_get_vcpu_id_method), DEVMETHOD_END }; @@ -149,6 +186,7 @@ static devclass_t vmbus_devclass; DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, NULL, NULL); MODULE_DEPEND(vmbus, acpi, 1, 1, 1); +MODULE_DEPEND(vmbus, pci, 1, 1, 1); MODULE_VERSION(vmbus, 1); static __inline struct vmbus_softc * @@ -972,6 +1010,69 @@ vmbus_sysctl_version(SYSCTL_HANDLER_ARGS) return sysctl_handle_string(oidp, verstr, sizeof(verstr), req); } +/* + * We need the function to make sure the MMIO resource is allocated from the + * ranges found in _CRS. + * + * For the release function, we can use bus_generic_release_resource(). + */ +static struct resource * +vmbus_alloc_resource(device_t dev, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct vmbus_softc *sc = device_get_softc(dev); + device_t parent = device_get_parent(dev); + struct resource *res; + + if (type != SYS_RES_MEMORY) + res = BUS_ALLOC_RESOURCE(parent, child, type, rid, start, + end, count, flags); + else + res = pcib_host_res_alloc(&sc->vmbus_mmio_res, child, type, + rid, start, end, count, flags); + + return (res); +} + +static device_t +get_nexus(device_t vmbus) +{ + device_t acpi = device_get_parent(vmbus); + device_t nexus = device_get_parent(acpi); + return (nexus); +} + +static int +vmbus_alloc_msi(device_t bus, device_t dev, int count, int maxcount, int *irqs) +{ + return (PCIB_ALLOC_MSI(get_nexus(bus), dev, count, maxcount, irqs)); +} + +static int +vmbus_release_msi(device_t bus, device_t dev, int count, int *irqs) +{ + return (PCIB_RELEASE_MSI(get_nexus(bus), dev, count, irqs)); +} + +static int +vmbus_alloc_msix(device_t bus, device_t dev, int *irq) +{ + return (PCIB_ALLOC_MSIX(get_nexus(bus), dev, irq)); +} + +static int +vmbus_release_msix(device_t bus, device_t dev, int irq) +{ + return (PCIB_RELEASE_MSIX(get_nexus(bus), dev, irq)); +} + +static int +vmbus_map_msi(device_t bus, device_t dev, int irq, uint64_t *addr, + uint32_t *data) +{ + return (PCIB_MAP_MSI(get_nexus(bus), dev, irq, addr, data)); +} + static uint32_t vmbus_get_version_method(device_t bus, device_t dev) { @@ -991,6 +1092,146 @@ vmbus_probe_guid_method(device_t bus, device_t dev, return ENXIO; } +static uint32_t +vmbus_get_vcpu_id_method(device_t bus, device_t dev, int cpu) +{ + const struct vmbus_softc *sc = device_get_softc(bus); + + return (VMBUS_PCPU_GET(sc, vcpuid, cpu)); +} + +#define VTPM_BASE_ADDR 0xfed40000 +#define FOUR_GB (1ULL << 32) + +enum parse_pass { parse_64, parse_32 }; + +struct parse_context { + device_t vmbus_dev; + enum parse_pass pass; +}; + +static ACPI_STATUS +parse_crs(ACPI_RESOURCE *res, void *ctx) +{ + const struct parse_context *pc = ctx; + device_t vmbus_dev = pc->vmbus_dev; + + struct vmbus_softc *sc = device_get_softc(vmbus_dev); + UINT64 start, end; + + switch (res->Type) { + case ACPI_RESOURCE_TYPE_ADDRESS32: + start = res->Data.Address32.Address.Minimum; + end = res->Data.Address32.Address.Maximum; + break; + + case ACPI_RESOURCE_TYPE_ADDRESS64: + start = res->Data.Address64.Address.Minimum; + end = res->Data.Address64.Address.Maximum; + break; + + default: + /* Unused types. */ + return (AE_OK); + } + + /* + * We don't use <1MB addresses. + */ + if (end < 0x100000) + return (AE_OK); + + /* Don't conflict with vTPM. */ + if (end >= VTPM_BASE_ADDR && start < VTPM_BASE_ADDR) + end = VTPM_BASE_ADDR - 1; + + if ((pc->pass == parse_32 && start < FOUR_GB) || + (pc->pass == parse_64 && start >= FOUR_GB)) + pcib_host_res_decodes(&sc->vmbus_mmio_res, SYS_RES_MEMORY, + start, end, 0); + + return (AE_OK); +} + +static void +vmbus_get_crs(device_t dev, device_t vmbus_dev, enum parse_pass pass) +{ + struct parse_context pc; + ACPI_STATUS status; + + if (bootverbose) + device_printf(dev, "walking _CRS, pass=%d\n", pass); + + pc.vmbus_dev = vmbus_dev; + pc.pass = pass; + status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", + parse_crs, &pc); + + if (bootverbose && ACPI_FAILURE(status)) + device_printf(dev, "_CRS: not found, pass=%d\n", pass); +} + +static void +vmbus_get_mmio_res_pass(device_t dev, enum parse_pass pass) +{ + device_t acpi0, pcib0 = NULL; + device_t *children; + int i, count; + + /* Try to find _CRS on VMBus device */ + vmbus_get_crs(dev, dev, pass); + + /* Try to find _CRS on VMBus device's parent */ + acpi0 = device_get_parent(dev); + vmbus_get_crs(acpi0, dev, pass); + + /* Try to locate pcib0 and find _CRS on it */ + if (device_get_children(acpi0, &children, &count) != 0) + return; + + for (i = 0; i < count; i++) { + if (!device_is_attached(children[i])) + continue; + + if (strcmp("pcib0", device_get_nameunit(children[i]))) + continue; + + pcib0 = children[i]; + break; + } + + if (pcib0) + vmbus_get_crs(pcib0, dev, pass); + + free(children, M_TEMP); +} + +static void +vmbus_get_mmio_res(device_t dev) +{ + struct vmbus_softc *sc = device_get_softc(dev); + /* + * We walk the resources twice to make sure that: in the resource + * list, the 32-bit resources appear behind the 64-bit resources. + * NB: resource_list_add() uses INSERT_TAIL. This way, when we + * iterate through the list to find a range for a 64-bit BAR in + * vmbus_alloc_resource(), we can make sure we try to use >4GB + * ranges first. + */ + pcib_host_res_init(dev, &sc->vmbus_mmio_res); + + vmbus_get_mmio_res_pass(dev, parse_64); + vmbus_get_mmio_res_pass(dev, parse_32); +} + +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); +} + static int vmbus_probe(device_t dev) { @@ -1027,6 +1268,9 @@ vmbus_doattach(struct vmbus_softc *sc) if (sc->vmbus_flags & VMBUS_FLAG_ATTACHED) return (0); + + vmbus_get_mmio_res(sc->vmbus_dev); + sc->vmbus_flags |= VMBUS_FLAG_ATTACHED; sc->vmbus_gpadl = VMBUS_GPADL_START; @@ -1173,6 +1417,8 @@ vmbus_detach(device_t dev) mtx_destroy(&sc->vmbus_prichan_lock); mtx_destroy(&sc->vmbus_chan_lock); + vmbus_free_mmio_res(dev); + return (0); } diff --git a/sys/dev/hyperv/vmbus/vmbus_if.m b/sys/dev/hyperv/vmbus/vmbus_if.m index 592f45f5d88..65de846eb6b 100644 --- a/sys/dev/hyperv/vmbus/vmbus_if.m +++ b/sys/dev/hyperv/vmbus/vmbus_if.m @@ -45,3 +45,9 @@ METHOD int probe_guid { device_t dev; const struct hyperv_guid *guid; }; + +METHOD uint32_t get_vcpu_id { + device_t bus; + device_t dev; + int cpu; +}; diff --git a/sys/dev/hyperv/vmbus/vmbus_var.h b/sys/dev/hyperv/vmbus/vmbus_var.h index df4553a9e40..7aa035f94d8 100644 --- a/sys/dev/hyperv/vmbus/vmbus_var.h +++ b/sys/dev/hyperv/vmbus/vmbus_var.h @@ -31,8 +31,11 @@ #include #include +#include #include +#include +#include /* * NOTE: DO NOT CHANGE THIS. @@ -77,6 +80,10 @@ struct vmbus_pcpu_data { struct task message_task; /* message task */ } __aligned(CACHE_LINE_SIZE); +#if __FreeBSD_version < 1100000 +typedef u_long rman_res_t; +#endif + struct vmbus_softc { void (*vmbus_event_proc)(struct vmbus_softc *, int); u_long *vmbus_tx_evtflags; @@ -120,6 +127,9 @@ struct vmbus_softc { /* Complete channel list */ struct mtx vmbus_chan_lock; TAILQ_HEAD(, vmbus_channel) vmbus_chans; + + /* The list of usable MMIO ranges for PCIe pass-through */ + struct pcib_host_resources vmbus_mmio_res; }; #define VMBUS_FLAG_ATTACHED 0x0001 /* vmbus was attached */ diff --git a/sys/dev/ic/ns16550.h b/sys/dev/ic/ns16550.h index e4c714f2146..29a73a01861 100644 --- a/sys/dev/ic/ns16550.h +++ b/sys/dev/ic/ns16550.h @@ -45,8 +45,13 @@ #define IER_ETXRDY 0x2 #define IER_ERLS 0x4 #define IER_EMSC 0x8 +/* + * Receive timeout interrupt enable. + * Implemented in Intel XScale, Ingenic XBurst. + */ +#define IER_RXTMOUT 0x10 -#define IER_BITS "\20\1ERXRDY\2ETXRDY\3ERLS\4EMSC" +#define IER_BITS "\20\1ERXRDY\2ETXRDY\3ERLS\4EMSC\5RXTMOUT" #define com_iir 2 /* interrupt identification register (R) */ #define REG_IIR com_iir @@ -156,6 +161,9 @@ #define FIFO_XMT_RST FCR_XMT_RST #define FCR_DMA 0x08 #define FIFO_DMA_MODE FCR_DMA +#ifdef CPU_XBURST +#define FCR_UART_ON 0x10 +#endif #define FCR_RX_LOW 0x00 #define FIFO_RX_LOW FCR_RX_LOW #define FCR_RX_MEDL 0x40 diff --git a/sys/dev/iicbus/iicsmb.c b/sys/dev/iicbus/iicsmb.c index b49d93d56ef..88af163d2fe 100644 --- a/sys/dev/iicbus/iicsmb.c +++ b/sys/dev/iicbus/iicsmb.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include "iicbus_if.h" @@ -432,7 +433,7 @@ iicsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) }; int error; - if (count > 32 || count == 0) + if (count > SMB_MAXBLOCKSIZE || count == 0) return (SMB_EINVAL); error = TRANSFER_MSGS(dev, msgs); return (iic2smb_error(error)); @@ -450,12 +451,6 @@ iicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) }; device_t parent = device_get_parent(dev); int error; - u_char bufsz; - - /* Stash output buffer size before overwriting it. */ - bufsz = *count; - if (bufsz == 0) - return (SMB_EINVAL); /* Have to do this because the command is split in two transfers. */ error = iicbus_request_bus(parent, dev, IIC_WAIT); @@ -465,18 +460,13 @@ iicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) /* * If the slave offers an empty or a too long reply, * read one byte to generate the stop or abort. - * XXX 32 is hardcoded until SMB_MAXBLOCKSIZE is restored - * to sanity. */ - if (*count > 32 || *count == 0) + if (*count > SMB_MAXBLOCKSIZE || *count == 0) block_msg[0].len = 1; - /* If longer than the buffer, then clamp at the buffer size. */ - if (*count > bufsz) - block_msg[0].len = bufsz; else block_msg[0].len = *count; error = TRANSFER_MSGS(dev, block_msg); - if (*count > 32 || *count == 0) + if (*count > SMB_MAXBLOCKSIZE || *count == 0) error = SMB_EINVAL; } (void)iicbus_release_bus(parent, dev); diff --git a/sys/dev/intpm/intpm.c b/sys/dev/intpm/intpm.c index bab2a7b73cf..bcb3d6dd1bc 100644 --- a/sys/dev/intpm/intpm.c +++ b/sys/dev/intpm/intpm.c @@ -785,39 +785,11 @@ intsmb_readw(device_t dev, u_char slave, char cmd, short *word) return (error); } -/* - * Data sheet claims that it implements all function, but also claims - * that it implements 7 function and not mention PCALL. So I don't know - * whether it will work. - */ static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) { -#ifdef PROCCALL_TEST - struct intsmb_softc *sc = device_get_softc(dev); - int error; - INTSMB_LOCK(sc); - error = intsmb_free(sc); - if (error) { - INTSMB_UNLOCK(sc); - return (error); - } - bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); - bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); - bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, sdata & 0xff); - bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (sdata & 0xff) >> 8); - intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); - error = intsmb_stop(sc); - if (error == 0) { - *rdata = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); - *rdata |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; - } - INTSMB_UNLOCK(sc); - return (error); -#else return (SMB_ENOTSUPP); -#endif } static int @@ -857,9 +829,6 @@ intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) int error, i; u_char data, nread; - if (*count > SMBBLOCKTRANS_MAX || *count == 0) - return (SMB_EINVAL); - INTSMB_LOCK(sc); error = intsmb_free(sc); if (error) { @@ -872,18 +841,14 @@ intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); - bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, *count); intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); error = intsmb_stop(sc); if (error == 0) { nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) { - for (i = 0; i < nread; i++) { - data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT); - if (i < *count) - buf[i] = data; - } *count = nread; + for (i = 0; i < nread; i++) + data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT); } else error = SMB_EBUSERR; } diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c index a434b422534..b7a2b44327d 100644 --- a/sys/dev/ioat/ioat.c +++ b/sys/dev/ioat/ioat.c @@ -765,6 +765,15 @@ out: mtx_lock(&ioat->submit_lock); mtx_lock(&ioat->cleanup_lock); ioat->quiescing = TRUE; + /* + * This is safe to do here because we have both locks and the submit + * queue is quiesced. We know that we will drain all outstanding + * events, so ioat_reset_hw can't deadlock. It is necessary to + * protect other ioat_process_event threads from racing ioat_reset_hw, + * reading an indeterminate hw state, and attempting to continue + * issuing completions. + */ + ioat->resetting_cleanup = TRUE; chanerr = ioat_read_4(ioat, IOAT_CHANERR_OFFSET); if (1 <= g_ioat_debug_level) diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c index 854c9e5a697..c61857453a3 100644 --- a/sys/dev/iwm/if_iwm.c +++ b/sys/dev/iwm/if_iwm.c @@ -1666,8 +1666,10 @@ const int nvm_to_read[] = { #define IWM_NVM_READ_OPCODE 0 /* load nvm chunk response */ -#define IWM_READ_NVM_CHUNK_SUCCEED 0 -#define IWM_READ_NVM_CHUNK_INVALID_ADDRESS 1 +enum { + IWM_READ_NVM_CHUNK_SUCCEED = 0, + IWM_READ_NVM_CHUNK_NOT_VALID_ADDRESS = 1 +}; static int iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section, @@ -1684,12 +1686,10 @@ iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section, struct iwm_rx_packet *pkt; struct iwm_host_cmd cmd = { .id = IWM_NVM_ACCESS_CMD, - .flags = IWM_CMD_SYNC | IWM_CMD_WANT_SKB | - IWM_CMD_SEND_IN_RFKILL, + .flags = IWM_CMD_WANT_SKB | IWM_CMD_SEND_IN_RFKILL, .data = { &nvm_access_cmd, }, }; - int ret, offset_read; - size_t bytes_read; + int ret, bytes_read, offset_read; uint8_t *resp_data; cmd.len[0] = sizeof(struct iwm_nvm_access_cmd); @@ -1718,9 +1718,26 @@ iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section, offset_read = le16toh(nvm_resp->offset); resp_data = nvm_resp->data; if (ret) { - IWM_DPRINTF(sc, IWM_DEBUG_RESET, - "NVM access command failed with status %d\n", ret); - ret = EINVAL; + if ((offset != 0) && + (ret == IWM_READ_NVM_CHUNK_NOT_VALID_ADDRESS)) { + /* + * meaning of NOT_VALID_ADDRESS: + * driver try to read chunk from address that is + * multiple of 2K and got an error since addr is empty. + * meaning of (offset != 0): driver already + * read valid data from another chunk so this case + * is not an error. + */ + IWM_DPRINTF(sc, IWM_DEBUG_EEPROM | IWM_DEBUG_RESET, + "NVM access command failed on offset 0x%x since that section size is multiple 2K\n", + offset); + *len = 0; + ret = 0; + } else { + IWM_DPRINTF(sc, IWM_DEBUG_EEPROM | IWM_DEBUG_RESET, + "NVM access command failed with status %d\n", ret); + ret = EIO; + } goto exit; } @@ -1735,7 +1752,7 @@ iwm_nvm_read_chunk(struct iwm_softc *sc, uint16_t section, if (bytes_read > length) { device_printf(sc->sc_dev, "NVM ACCESS response with too much data " - "(%d bytes requested, %zd bytes received)\n", + "(%d bytes requested, %d bytes received)\n", length, bytes_read); ret = EINVAL; goto exit; @@ -6192,7 +6209,8 @@ iwm_detach_local(struct iwm_softc *sc, int do_net80211) device_t dev = sc->sc_dev; int i; - ieee80211_draintask(&sc->sc_ic, &sc->sc_es_task); + if (do_net80211) + ieee80211_draintask(&sc->sc_ic, &sc->sc_es_task); callout_drain(&sc->sc_led_blink_to); callout_drain(&sc->sc_watchdog_to); diff --git a/sys/dev/kbdmux/kbdmux.c b/sys/dev/kbdmux/kbdmux.c index 4720a0e6fc8..9a80760a873 100644 --- a/sys/dev/kbdmux/kbdmux.c +++ b/sys/dev/kbdmux/kbdmux.c @@ -32,6 +32,7 @@ */ #include "opt_compat.h" +#include "opt_evdev.h" #include "opt_kbd.h" #include "opt_kbdmux.h" @@ -64,6 +65,11 @@ #include +#ifdef EVDEV_SUPPORT +#include +#include +#endif + #define KEYBOARD_NAME "kbdmux" MALLOC_DECLARE(M_KBDMUX); @@ -159,6 +165,11 @@ struct kbdmux_state u_int ks_composed_char; /* composed char code */ u_char ks_prefix; /* AT scan code prefix */ +#ifdef EVDEV_SUPPORT + struct evdev_dev * ks_evdev; + int ks_evdev_state; +#endif + SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */ KBDMUX_LOCK_DECL_GLOBAL; @@ -371,6 +382,12 @@ static keyboard_switch_t kbdmuxsw = { .diag = genkbd_diag, }; +#ifdef EVDEV_SUPPORT +static const struct evdev_methods kbdmux_evdev_methods = { + .ev_event = evdev_ev_kbd_event, +}; +#endif + /* * Return the number of found keyboards */ @@ -404,6 +421,10 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags) accentmap_t *accmap = NULL; fkeytab_t *fkeymap = NULL; int error, needfree, fkeymap_size, delay[2]; +#ifdef EVDEV_SUPPORT + struct evdev_dev *evdev; + char phys_loc[NAMELEN]; +#endif if (*kbdp == NULL) { *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO); @@ -464,6 +485,30 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags) delay[1] = kbd->kb_delay2; kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); +#ifdef EVDEV_SUPPORT + /* register as evdev provider */ + evdev = evdev_alloc(); + evdev_set_name(evdev, "System keyboard multiplexer"); + snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit); + evdev_set_phys(evdev, phys_loc); + evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0); + evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods); + evdev_support_event(evdev, EV_SYN); + evdev_support_event(evdev, EV_KEY); + evdev_support_event(evdev, EV_LED); + evdev_support_event(evdev, EV_REP); + evdev_support_all_known_keys(evdev); + evdev_support_led(evdev, LED_NUML); + evdev_support_led(evdev, LED_CAPSL); + evdev_support_led(evdev, LED_SCROLLL); + + if (evdev_register(evdev)) + evdev_free(evdev); + else + state->ks_evdev = evdev; + state->ks_evdev_state = 0; +#endif + KBD_INIT_DONE(kbd); } @@ -532,6 +577,10 @@ kbdmux_term(keyboard_t *kbd) kbd_unregister(kbd); +#ifdef EVDEV_SUPPORT + evdev_free(state->ks_evdev); +#endif + KBDMUX_LOCK_DESTROY(state); bzero(state, sizeof(*state)); free(state, M_KBDMUX); @@ -694,6 +743,20 @@ next_code: kbd->kb_count ++; +#ifdef EVDEV_SUPPORT + /* push evdev event */ + if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) { + uint16_t key = evdev_scancode2key(&state->ks_evdev_state, + scancode); + + if (key != KEY_RESERVED) { + evdev_push_event(state->ks_evdev, EV_KEY, + key, scancode & 0x80 ? 0 : 1); + evdev_sync(state->ks_evdev); + } + } +#endif + /* return the byte as is for the K_RAW mode */ if (state->ks_mode == K_RAW) { KBDMUX_UNLOCK(state); @@ -1120,7 +1183,11 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) } KBD_LED_VAL(kbd) = *(int *)arg; - +#ifdef EVDEV_SUPPORT + if (state->ks_evdev != NULL && + evdev_rcpt_mask & EVDEV_RCPT_KBDMUX) + evdev_push_leds(state->ks_evdev, *(int *)arg); +#endif /* KDSETLED on all slave keyboards */ SLIST_FOREACH(k, &state->ks_kbds, next) (void)kbdd_ioctl(k->kbd, KDSETLED, arg); @@ -1197,7 +1264,11 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) kbd->kb_delay1 = delays[(mode >> 5) & 3]; kbd->kb_delay2 = rates[mode & 0x1f]; - +#ifdef EVDEV_SUPPORT + if (state->ks_evdev != NULL && + evdev_rcpt_mask & EVDEV_RCPT_KBDMUX) + evdev_push_repeats(state->ks_evdev, kbd); +#endif /* perform command on all slave keyboards */ SLIST_FOREACH(k, &state->ks_kbds, next) (void)kbdd_ioctl(k->kbd, cmd, arg); @@ -1396,4 +1467,6 @@ kbdmux_modevent(module_t mod, int type, void *data) } DEV_MODULE(kbdmux, kbdmux_modevent, NULL); - +#ifdef EVDEV_SUPPORT +MODULE_DEPEND(kbdmux, evdev, 1, 1, 1); +#endif diff --git a/sys/dev/rtwn/if_rtwn_tx.h b/sys/dev/rtwn/if_rtwn_tx.h index d38a8550f2c..e02fb56499d 100644 --- a/sys/dev/rtwn/if_rtwn_tx.h +++ b/sys/dev/rtwn/if_rtwn_tx.h @@ -20,7 +20,9 @@ #define IF_RTWN_TX_H void rtwn_drain_mbufq(struct rtwn_softc *); +#ifdef IEEE80211_SUPPORT_SUPERG void rtwn_ff_flush_all(struct rtwn_softc *, union sec_param *); +#endif int rtwn_transmit(struct ieee80211com *, struct mbuf *); void rtwn_start(struct rtwn_softc *); int rtwn_raw_xmit(struct ieee80211_node *, struct mbuf *, diff --git a/sys/dev/rtwn/pci/rtwn_pci_attach.c b/sys/dev/rtwn/pci/rtwn_pci_attach.c index 00dcacc50f5..e021c401ad3 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_attach.c +++ b/sys/dev/rtwn/pci/rtwn_pci_attach.c @@ -149,8 +149,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc) /* Create RX buffer DMA tag. */ error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, - 1, MCLBYTES, 0, NULL, NULL, &rx_ring->data_dmat); + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &rx_ring->data_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create rx buf DMA tag\n"); goto fail; @@ -166,7 +166,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc) goto fail; } - rx_data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + rx_data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, + MJUMPAGESIZE); if (rx_data->m == NULL) { device_printf(sc->sc_dev, "could not allocate rx mbuf\n"); @@ -175,8 +176,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc) } error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map, - mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr, - &rx_data->paddr, BUS_DMA_NOWAIT); + mtod(rx_data->m, void *), MJUMPAGESIZE, + rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT); if (error != 0) { device_printf(sc->sc_dev, "could not load rx buf DMA map"); @@ -184,7 +185,7 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc) } rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr, - MCLBYTES, i); + MJUMPAGESIZE, i); } rx_ring->cur = 0; @@ -206,7 +207,7 @@ rtwn_pci_reset_rx_list(struct rtwn_softc *sc) for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) { rx_data = &rx_ring->rx_data[i]; rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], - rx_data->paddr, MCLBYTES, i); + rx_data->paddr, MJUMPAGESIZE, i); } rx_ring->cur = 0; } @@ -287,8 +288,8 @@ rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid) BUS_DMASYNC_PREWRITE); error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, - 1, MCLBYTES, 0, NULL, NULL, &tx_ring->data_dmat); + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &tx_ring->data_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create tx buf DMA tag\n"); goto fail; diff --git a/sys/dev/rtwn/pci/rtwn_pci_rx.c b/sys/dev/rtwn/pci/rtwn_pci_rx.c index df375a19760..00f7409efeb 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_rx.c +++ b/sys/dev/rtwn/pci/rtwn_pci_rx.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -120,7 +121,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc, pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN); if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack) || - pktlen > MCLBYTES)) { + pktlen > MJUMPAGESIZE)) { RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, "%s: frame is too short/long: %d\n", __func__, pktlen); goto fail; @@ -129,7 +130,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc, infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8; shift = MS(rxdw0, R92C_RXDW0_SHIFT); - m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); if (__predict_false(m1 == NULL)) { device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n", __func__); @@ -139,20 +140,20 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc, bus_dmamap_unload(ring->data_dmat, rx_data->map); error = bus_dmamap_load(ring->data_dmat, rx_data->map, mtod(m1, void *), - MCLBYTES, rtwn_pci_dma_map_addr, &rx_data->paddr, 0); + MJUMPAGESIZE, rtwn_pci_dma_map_addr, &rx_data->paddr, 0); if (error != 0) { m_freem(m1); error = bus_dmamap_load(ring->data_dmat, rx_data->map, - mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr, - &rx_data->paddr, BUS_DMA_NOWAIT); + mtod(rx_data->m, void *), MJUMPAGESIZE, + rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT); if (error != 0) panic("%s: could not load old RX mbuf", device_get_name(sc->sc_dev)); /* Physical address may have changed. */ - rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES, - desc_idx); + rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, + MJUMPAGESIZE, desc_idx); goto fail; } @@ -169,7 +170,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc, __func__, pktlen, infosz, shift, rssi); /* Update RX descriptor. */ - rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES, + rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE, desc_idx); /* Send the frame to the 802.11 layer. */ @@ -222,6 +223,8 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid) data->ni = NULL; ring->queued--; + KASSERT(ring->queued >= 0, + ("ring->queued (qid %d) underflow!\n", qid)); } else m_freem(data->m); @@ -235,9 +238,27 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid) #endif } - if (ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1)) + if ((sc->qfullmsk & (1 << qid)) != 0 && + ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1)) { sc->qfullmsk &= ~(1 << qid); - rtwn_start(sc); + rtwn_start(sc); + } + +#ifdef IEEE80211_SUPPORT_SUPERG + /* + * If the TX active queue drops below a certain + * threshold, ensure we age fast-frames out so they're + * transmitted. + */ + if (sc->sc_ratectl != RTWN_RATECTL_NET80211 && ring->queued <= 1) { + /* + * XXX TODO: just make this a callout timer schedule + * so we can flush the FF staging queue if we're + * approaching idle. + */ + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); + } +#endif } static void @@ -261,6 +282,17 @@ rtwn_pci_rx_done(struct rtwn_softc *sc) ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT; } + + /* Finished receive; age anything left on the FF queue by a little bump */ + /* + * XXX TODO: just make this a callout timer schedule so we can + * flush the FF staging queue if we're approaching idle. + */ +#ifdef IEEE80211_SUPPORT_SUPERG + if (!(sc->sc_flags & RTWN_FW_LOADED) || + sc->sc_ratectl != RTWN_RATECTL_NET80211) + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); +#endif } void diff --git a/sys/dev/rtwn/pci/rtwn_pci_tx.c b/sys/dev/rtwn/pci/rtwn_pci_tx.c index d3e18083fdd..b450e4ee9f6 100644 --- a/sys/dev/rtwn/pci/rtwn_pci_tx.c +++ b/sys/dev/rtwn/pci/rtwn_pci_tx.c @@ -58,6 +58,37 @@ __FBSDID("$FreeBSD$"); #include +static struct mbuf * +rtwn_mbuf_defrag(struct mbuf *m0, int how) +{ + struct mbuf *m = NULL; + + KASSERT(m0->m_flags & M_PKTHDR, + ("M_PKTHDR flag is absent (m %p)!", m0)); + + /* NB: we need _exactly_ one mbuf (no less, no more). */ + if (m0->m_pkthdr.len > MJUMPAGESIZE) { + /* XXX MJUM9BYTES? */ + return (NULL); + } else if (m0->m_pkthdr.len > MCLBYTES) { + m = m_getjcl(how, MT_DATA, M_PKTHDR, MJUMPAGESIZE); + if (m == NULL) + return (NULL); + + if (m_dup_pkthdr(m, m0, how) == 0) { + m_freem(m); + return (NULL); + } + + m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t)); + m->m_len = m->m_pkthdr.len; + m_freem(m0); + + return (m); + } else + return (m_defrag(m0, how)); +} + static int rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m, uint8_t *tx_desc, uint8_t type) @@ -114,7 +145,7 @@ rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni, if (error != 0) { struct mbuf *mnew; - mnew = m_defrag(m, M_NOWAIT); + mnew = rtwn_mbuf_defrag(m, M_NOWAIT); if (mnew == NULL) { device_printf(sc->sc_dev, "can't defragment mbuf\n"); return (ENOBUFS); diff --git a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c index 65e98a0399c..f38782fced6 100644 --- a/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c +++ b/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c @@ -138,15 +138,11 @@ r92ce_adj_devcaps(struct rtwn_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; - /* XXX TODO: test everything that removed here before enabling. */ - /* XX do NOT enable PMGT until RSVD_PAGE command will not be fixed. */ - ic->ic_caps &= ~( - IEEE80211_C_PMGT /* check null frame / device usability */ - | IEEE80211_C_SWAMSDUTX - | IEEE80211_C_FF - ); - - ic->ic_htcaps = 0; + /* + * XXX do NOT enable PMGT until RSVD_PAGE command + * will not be tested / fixed + HRPWM register must be set too. + */ + ic->ic_caps &= ~IEEE80211_C_PMGT; } void diff --git a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c index e6edea7af49..c15d1e2a034 100644 --- a/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c +++ b/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/dev/rtwn/rtl8812a/r12a_rom.c b/sys/dev/rtwn/rtl8812a/r12a_rom.c index df8bea64653..f5d16a3ff71 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_rom.c +++ b/sys/dev/rtwn/rtl8812a/r12a_rom.c @@ -65,7 +65,7 @@ r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf) { struct r12a_softc *rs = sc->sc_priv; struct r12a_rom *rom = (struct r12a_rom *)buf; - int i, j; + int i, j, k; sc->thermal_meter = rom->thermal_meter; rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap, @@ -99,15 +99,15 @@ r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf) MS(pwr_diff_2g->ht20_ofdm, HIGH_PART)); rs->bw40_tx_pwr_diff_2g[i][0] = 0; - for (j = 1; j < nitems(pwr_diff_2g->diff123); j++) { + for (j = 1, k = 0; k < nitems(pwr_diff_2g->diff123); j++, k++) { rs->cck_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( - MS(pwr_diff_2g->diff123[j].ofdm_cck, LOW_PART)); + MS(pwr_diff_2g->diff123[k].ofdm_cck, LOW_PART)); rs->ofdm_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( - MS(pwr_diff_2g->diff123[j].ofdm_cck, HIGH_PART)); + MS(pwr_diff_2g->diff123[k].ofdm_cck, HIGH_PART)); rs->bw20_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( - MS(pwr_diff_2g->diff123[j].ht40_ht20, LOW_PART)); + MS(pwr_diff_2g->diff123[k].ht40_ht20, LOW_PART)); rs->bw40_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( - MS(pwr_diff_2g->diff123[j].ht40_ht20, HIGH_PART)); + MS(pwr_diff_2g->diff123[k].ht40_ht20, HIGH_PART)); } for (j = 0; j < R12A_GROUP_5G; j++) { @@ -128,11 +128,12 @@ r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf) rs->bw20_tx_pwr_diff_5g[i][0] = RTWN_SIGN4TO8( MS(pwr_diff_5g->ht20_ofdm, HIGH_PART)); rs->bw40_tx_pwr_diff_5g[i][0] = 0; - for (j = 1; j < nitems(pwr_diff_5g->ht40_ht20); j++) { + for (j = 1, k = 0; k < nitems(pwr_diff_5g->ht40_ht20); + j++, k++) { rs->bw20_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8( - MS(pwr_diff_5g->ht40_ht20[j], LOW_PART)); + MS(pwr_diff_5g->ht40_ht20[k], LOW_PART)); rs->bw40_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8( - MS(pwr_diff_5g->ht40_ht20[j], HIGH_PART)); + MS(pwr_diff_5g->ht40_ht20[k], HIGH_PART)); } for (j = 0; j < nitems(pwr_diff_5g->ht80_ht160); j++) { diff --git a/sys/dev/rtwn/rtl8812a/r12a_var.h b/sys/dev/rtwn/rtl8812a/r12a_var.h index 9c22cf98ddb..e236a5cdeec 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_var.h +++ b/sys/dev/rtwn/rtl8812a/r12a_var.h @@ -64,16 +64,16 @@ struct r12a_softc { uint8_t ht40_tx_pwr_2g[R12A_MAX_RF_PATH][R12A_GROUP_2G]; uint8_t ht40_tx_pwr_5g[R12A_MAX_RF_PATH][R12A_GROUP_5G]; - uint8_t cck_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t ofdm_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t bw20_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t bw40_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t cck_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t ofdm_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw20_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw40_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t ofdm_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t bw20_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t bw40_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t bw80_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; - uint8_t bw160_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t ofdm_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw20_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw40_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw80_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw160_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; int sc_ant; diff --git a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c index 9134dce51af..855d2b0b7c8 100644 --- a/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c +++ b/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c @@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include diff --git a/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c b/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c index a9bc47b8969..86f605c335d 100644 --- a/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c +++ b/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/dev/rtwn/usb/rtwn_usb_rx.c b/sys/dev/rtwn/usb/rtwn_usb_rx.c index 8c6aa168679..f15d6c66252 100644 --- a/sys/dev/rtwn/usb/rtwn_usb_rx.c +++ b/sys/dev/rtwn/usb/rtwn_usb_rx.c @@ -326,7 +326,8 @@ finish: * flush the FF staging queue if we're approaching idle. */ #ifdef IEEE80211_SUPPORT_SUPERG - if (!(sc->sc_flags & RTWN_FW_LOADED)) + if (!(sc->sc_flags & RTWN_FW_LOADED) || + sc->sc_ratectl != RTWN_RATECTL_NET80211) rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); #endif diff --git a/sys/dev/smbus/smb.c b/sys/dev/smbus/smb.c index 21d1e2f7c3d..5f6eff03962 100644 --- a/sys/dev/smbus/smb.c +++ b/sys/dev/smbus/smb.c @@ -41,7 +41,9 @@ #include "smbus_if.h" -#define BUFSIZE 1024 +#define SMB_OLD_READB _IOW('i', 7, struct smbcmd) +#define SMB_OLD_READW _IOW('i', 8, struct smbcmd) +#define SMB_OLD_PCALL _IOW('i', 9, struct smbcmd) struct smb_softc { device_t sc_dev; @@ -224,7 +226,9 @@ smbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t s->cmd, s->wdata.word)); break; + case SMB_OLD_READB: case SMB_READB: + /* NB: for SMB_OLD_READB the read data goes to rbuf only. */ error = smbus_error(smbus_readb(parent, s->slave, s->cmd, &s->rdata.byte)); if (error) @@ -235,7 +239,9 @@ smbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t } break; + case SMB_OLD_READW: case SMB_READW: + /* NB: for SMB_OLD_READW the read data goes to rbuf only. */ error = smbus_error(smbus_readw(parent, s->slave, s->cmd, &s->rdata.word)); if (error) @@ -248,7 +254,9 @@ smbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t } break; + case SMB_OLD_PCALL: case SMB_PCALL: + /* NB: for SMB_OLD_PCALL the read data goes to rbuf only. */ error = smbus_error(smbus_pcall(parent, s->slave, s->cmd, s->wdata.word, &s->rdata.word)); if (error) diff --git a/sys/dev/smbus/smb.h b/sys/dev/smbus/smb.h index 44b71e8a40e..b766a656d27 100644 --- a/sys/dev/smbus/smb.h +++ b/sys/dev/smbus/smb.h @@ -63,11 +63,10 @@ struct smbcmd { #define SMB_RECVB _IOWR('i', 4, struct smbcmd) #define SMB_WRITEB _IOW('i', 5, struct smbcmd) #define SMB_WRITEW _IOW('i', 6, struct smbcmd) -#define SMB_READB _IOW('i', 7, struct smbcmd) -#define SMB_READW _IOW('i', 8, struct smbcmd) -#define SMB_PCALL _IOW('i', 9, struct smbcmd) +#define SMB_READB _IOWR('i', 7, struct smbcmd) +#define SMB_READW _IOWR('i', 8, struct smbcmd) +#define SMB_PCALL _IOWR('i', 9, struct smbcmd) #define SMB_BWRITE _IOW('i', 10, struct smbcmd) -#define SMB_OLD_BREAD _IOW('i', 11, struct smbcmd) #define SMB_BREAD _IOWR('i', 11, struct smbcmd) #define SMB_OLD_TRANS _IOWR('i', 12, struct smbcmd) diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c index adcf5d2bfa0..8ad3714e2f6 100644 --- a/sys/dev/uart/uart_bus_fdt.c +++ b/sys/dev/uart/uart_bus_fdt.c @@ -123,7 +123,7 @@ uart_fdt_find_compatible(phandle_t node, const struct ofw_compat_data *cd) const struct ofw_compat_data *ocd; for (ocd = cd; ocd->ocd_str != NULL; ocd++) { - if (fdt_is_compatible(node, ocd->ocd_str)) + if (ofw_bus_node_is_compatible(node, ocd->ocd_str)) return (ocd); } return (NULL); diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c index f4dbcfc2dcc..6c9d7aa23a0 100644 --- a/sys/dev/uart/uart_core.c +++ b/sys/dev/uart/uart_core.c @@ -573,7 +573,7 @@ uart_bus_attach(device_t dev) * the device. */ sc0 = device_get_softc(dev); - if (sc0->sc_class->size > sizeof(*sc)) { + if (sc0->sc_class->size > device_get_driver(dev)->size) { sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO); bcopy(sc0, sc, sizeof(*sc)); device_set_softc(dev, sc); @@ -781,11 +781,10 @@ uart_bus_detach(device_t dev) mtx_destroy(&sc->sc_hwmtx_s); - if (sc->sc_class->size > sizeof(*sc)) { + if (sc->sc_class->size > device_get_driver(dev)->size) { device_set_softc(dev, NULL); free(sc, M_UART); - } else - device_set_softc(dev, NULL); + } return (0); } diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index 2498fa37db7..74d7bb7c1f9 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -198,6 +198,9 @@ ns8250_flush(struct uart_bas *bas, int what) uint8_t fcr; fcr = FCR_ENABLE; +#ifdef CPU_XBURST + fcr |= FCR_UART_ON; +#endif if (what & UART_FLUSH_TRANSMITTER) fcr |= FCR_XMT_RST; if (what & UART_FLUSH_RECEIVER) @@ -268,6 +271,10 @@ ns8250_probe(struct uart_bas *bas) { u_char val; +#ifdef CPU_XBURST + uart_setreg(bas, REG_FCR, FCR_UART_ON); +#endif + /* Check known 0 bits that don't depend on DLAB. */ val = uart_getreg(bas, REG_IIR); if (val & 0x30) @@ -289,7 +296,7 @@ static void ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { - u_char ier; + u_char ier, val; if (bas->rclk == 0) bas->rclk = DEFAULT_RCLK; @@ -306,7 +313,11 @@ ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, uart_barrier(bas); /* Disable the FIFO (if present). */ - uart_setreg(bas, REG_FCR, 0); + val = 0; +#ifdef CPU_XBURST + val = FCR_UART_ON; +#endif + uart_setreg(bas, REG_FCR, val); uart_barrier(bas); /* Set RTS & DTR. */ @@ -461,6 +472,9 @@ ns8250_bus_attach(struct uart_softc *sc) ns8250->mcr = uart_getreg(bas, REG_MCR); ns8250->fcr = FCR_ENABLE; +#ifdef CPU_XBURST + ns8250->fcr |= FCR_UART_ON; +#endif if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags", &ivar)) { if (UART_FLAGS_FCR_RX_LOW(ivar)) @@ -753,6 +767,7 @@ ns8250_bus_probe(struct uart_softc *sc) struct uart_bas *bas; int count, delay, error, limit; uint8_t lsr, mcr, ier; + uint8_t val; ns8250 = (struct ns8250_softc *)sc; bas = &sc->sc_bas; @@ -786,7 +801,11 @@ ns8250_bus_probe(struct uart_softc *sc) * done. Since this is the first time we enable the FIFOs, we reset * them. */ - uart_setreg(bas, REG_FCR, FCR_ENABLE); + val = FCR_ENABLE; +#ifdef CPU_XBURST + val |= FCR_UART_ON; +#endif + uart_setreg(bas, REG_FCR, val); uart_barrier(bas); if (!(uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK)) { /* @@ -800,7 +819,11 @@ ns8250_bus_probe(struct uart_softc *sc) return (0); } - uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST); + val = FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST; +#ifdef CPU_XBURST + val |= FCR_UART_ON; +#endif + uart_setreg(bas, REG_FCR, val); uart_barrier(bas); count = 0; @@ -810,7 +833,11 @@ ns8250_bus_probe(struct uart_softc *sc) error = ns8250_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER); if (error) { uart_setreg(bas, REG_MCR, mcr); - uart_setreg(bas, REG_FCR, 0); + val = 0; +#ifdef CPU_XBURST + val |= FCR_UART_ON; +#endif + uart_setreg(bas, REG_FCR, val); uart_barrier(bas); goto describe; } @@ -840,7 +867,11 @@ ns8250_bus_probe(struct uart_softc *sc) ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; uart_setreg(bas, REG_IER, ier); uart_setreg(bas, REG_MCR, mcr); - uart_setreg(bas, REG_FCR, 0); + val = 0; +#ifdef CPU_XBURST + val |= FCR_UART_ON; +#endif + uart_setreg(bas, REG_FCR, val); uart_barrier(bas); count = 0; goto describe; diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c index 5560f070dc9..08c037706ea 100644 --- a/sys/dev/usb/controller/dwc_otg.c +++ b/sys/dev/usb/controller/dwc_otg.c @@ -98,10 +98,6 @@ GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTMSK_OTGINTMSK | \ GINTSTS_SESSREQINT) -#define DWC_OTG_PHY_ULPI 0 -#define DWC_OTG_PHY_HSIC 1 -#define DWC_OTG_PHY_INTERNAL 2 - #ifndef DWC_OTG_PHY_DEFAULT #define DWC_OTG_PHY_DEFAULT DWC_OTG_PHY_ULPI #endif @@ -110,10 +106,10 @@ static int dwc_otg_phy_type = DWC_OTG_PHY_DEFAULT; static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW, 0, "USB DWC OTG"); SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, - &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2 - ULPI/HSIC/INTERNAL"); + &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+"); #ifdef USB_DEBUG -static int dwc_otg_debug; +static int dwc_otg_debug = 0; SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, debug, CTLFLAG_RWTUN, &dwc_otg_debug, 0, "DWC OTG debug level"); @@ -3889,8 +3885,13 @@ dwc_otg_init(struct dwc_otg_softc *sc) break; } - /* select HSIC, ULPI or internal PHY mode */ - switch (dwc_otg_phy_type) { + if (sc->sc_phy_type == 0) + sc->sc_phy_type = dwc_otg_phy_type + 1; + if (sc->sc_phy_bits == 0) + sc->sc_phy_bits = 16; + + /* select HSIC, ULPI, UTMI+ or internal PHY mode */ + switch (sc->sc_phy_type) { case DWC_OTG_PHY_HSIC: DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG, GUSBCFG_PHYIF | @@ -3910,6 +3911,16 @@ dwc_otg_init(struct dwc_otg_softc *sc) GUSBCFG_TRD_TIM_SET(5) | temp); DWC_OTG_WRITE_4(sc, DOTG_GOTGCTL, 0); + temp = DWC_OTG_READ_4(sc, DOTG_GLPMCFG); + DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG, + temp & ~GLPMCFG_HSIC_CONN); + break; + case DWC_OTG_PHY_UTMI: + DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG, + (sc->sc_phy_bits == 16 ? GUSBCFG_PHYIF : 0) | + GUSBCFG_TRD_TIM_SET(5) | temp); + DWC_OTG_WRITE_4(sc, DOTG_GOTGCTL, 0); + temp = DWC_OTG_READ_4(sc, DOTG_GLPMCFG); DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG, temp & ~GLPMCFG_HSIC_CONN); diff --git a/sys/dev/usb/controller/dwc_otg.h b/sys/dev/usb/controller/dwc_otg.h index 038b072aeef..7f5ede481e5 100644 --- a/sys/dev/usb/controller/dwc_otg.h +++ b/sys/dev/usb/controller/dwc_otg.h @@ -191,6 +191,13 @@ struct dwc_otg_softc { uint16_t sc_active_rx_ep; uint16_t sc_last_frame_num; + uint8_t sc_phy_type; + uint8_t sc_phy_bits; +#define DWC_OTG_PHY_ULPI 1 +#define DWC_OTG_PHY_HSIC 2 +#define DWC_OTG_PHY_INTERNAL 3 +#define DWC_OTG_PHY_UTMI 4 + uint8_t sc_timer_active; uint8_t sc_dev_ep_max; uint8_t sc_dev_in_ep_max; diff --git a/sys/dev/usb/controller/dwc_otg_fdt.c b/sys/dev/usb/controller/dwc_otg_fdt.c index 80d3388050f..8cc8e754fab 100644 --- a/sys/dev/usb/controller/dwc_otg_fdt.c +++ b/sys/dev/usb/controller/dwc_otg_fdt.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include static device_probe_t dwc_otg_probe; -static device_detach_t dwc_otg_detach; static int dwc_otg_probe(device_t dev) @@ -159,7 +158,7 @@ error: return (ENXIO); } -static int +int dwc_otg_detach(device_t dev) { struct dwc_otg_fdt_softc *sc = device_get_softc(dev); diff --git a/sys/dev/usb/controller/dwc_otg_fdt.h b/sys/dev/usb/controller/dwc_otg_fdt.h index 9e01118c80d..634b7960b0a 100644 --- a/sys/dev/usb/controller/dwc_otg_fdt.h +++ b/sys/dev/usb/controller/dwc_otg_fdt.h @@ -35,5 +35,6 @@ struct dwc_otg_fdt_softc { extern driver_t dwc_otg_driver; device_attach_t dwc_otg_attach; +device_attach_t dwc_otg_detach; #endif diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c index 915dd838b38..375ab5f2189 100644 --- a/sys/dev/usb/net/if_smsc.c +++ b/sys/dev/usb/net/if_smsc.c @@ -152,7 +152,7 @@ static const struct usb_device_id smsc_devs[] = { device_printf((sc)->sc_ue.ue_dev, "debug: " fmt, ##args); \ } while(0) #else -#define smsc_dbg_printf(sc, fmt, args...) +#define smsc_dbg_printf(sc, fmt, args...) do { } while (0) #endif #define smsc_warn_printf(sc, fmt, args...) \ @@ -822,7 +822,6 @@ static int smsc_sethwcsum(struct smsc_softc *sc) return (0); } - /** * smsc_setmacaddress - Sets the mac address in the device * @sc: driver soft context @@ -905,6 +904,9 @@ smsc_init(struct usb_ether *ue) SMSC_LOCK_ASSERT(sc, MA_OWNED); + if (smsc_setmacaddress(sc, IF_LLADDR(ifp))) + smsc_dbg_printf(sc, "setting MAC address failed\n"); + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) return; @@ -1566,8 +1568,8 @@ smsc_fdt_find_eth_node(phandle_t start) /* Traverse through entire tree to find usb ethernet nodes. */ for (node = OF_child(start); node != 0; node = OF_peer(node)) { - if (fdt_is_compatible(node, "net,ethernet") && - fdt_is_compatible(node, "usb,device")) + if (ofw_bus_node_is_compatible(node, "net,ethernet") && + ofw_bus_node_is_compatible(node, "usb,device")) return (node); child = smsc_fdt_find_eth_node(node); if (child != -1) diff --git a/sys/dev/virtio/console/virtio_console.c b/sys/dev/virtio/console/virtio_console.c index bfef07f1d94..4c673c8d129 100644 --- a/sys/dev/virtio/console/virtio_console.c +++ b/sys/dev/virtio/console/virtio_console.c @@ -600,7 +600,7 @@ vtcon_ctrl_event_enqueue(struct vtcon_softc *sc, sglist_init(&sg, 2, segs); error = sglist_append(&sg, control, - sizeof(struct virtio_console_control)); + sizeof(struct virtio_console_control) + VTCON_BULK_BUFSZ); KASSERT(error == 0, ("%s: error %d adding control to sglist", __func__, error)); @@ -633,7 +633,8 @@ vtcon_ctrl_event_requeue(struct vtcon_softc *sc, { int error; - bzero(control, sizeof(struct virtio_console_control)); + bzero(control, sizeof(struct virtio_console_control) + + VTCON_BULK_BUFSZ); error = vtcon_ctrl_event_enqueue(sc, control); KASSERT(error == 0, diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c index 5389b1c4b16..1119ee7a4b1 100644 --- a/sys/fs/autofs/autofs.c +++ b/sys/fs/autofs/autofs.c @@ -61,7 +61,7 @@ */ #include - __FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD$"); #include #include diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 02b85e7e733..7b65a606129 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -827,6 +827,12 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp, struct dqblk dqb; uid_t savuid; #endif + static struct timeval last64fileid; + static size_t count64fileid; + static struct timeval last64mountfileid; + static size_t count64mountfileid; + static struct timeval warninterval = { 60, 0 }; + if (compare) { retnotsup = 0; error = nfsrv_getattrbits(nd, &attrbits, NULL, &retnotsup); @@ -1202,8 +1208,14 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp, *retcmpp = NFSERR_NOTSAME; } } else if (nap != NULL) { - if (*tl++) - printf("NFSv4 fileid > 32bits\n"); + if (*tl++) { + count64fileid++; + if (ratecheck(&last64fileid, &warninterval)) { + printf("NFSv4 fileid > 32bits (%zu occurrences)\n", + count64fileid); + count64fileid = 0; + } + } nap->na_fileid = thyp; } attrsum += NFSX_HYPER; @@ -1740,8 +1752,14 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp, } } } else if (nap != NULL) { - if (*tl++) - printf("NFSv4 mounted on fileid > 32bits\n"); + if (*tl++) { + count64mountfileid++; + if (ratecheck(&last64mountfileid, &warninterval)) { + printf("NFSv4 mounted on fileid > 32bits (%zu occurrences)\n", + count64mountfileid); + count64mountfileid = 0; + } + } nap->na_mntonfileno = thyp; } attrsum += NFSX_HYPER; diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 7ce4789c72a..d3019f60549 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -1372,12 +1372,9 @@ retry: VM_WAIT; VM_OBJECT_WLOCK(uobj); goto retry; - } else if (m->valid != VM_PAGE_BITS_ALL) - rv = vm_pager_get_pages(uobj, &m, 1, - NULL, NULL); - else - /* A cached page was reactivated. */ - rv = VM_PAGER_OK; + } + rv = vm_pager_get_pages(uobj, &m, 1, NULL, + NULL); vm_page_lock(m); if (rv == VM_PAGER_OK) { vm_page_deactivate(m); diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index 52c007efd1d..e1daae1ddaf 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -79,12 +79,12 @@ SYSCTL_UINT(_kern_geom_mirror, OID_AUTO, sync_requests, CTLFLAG_RDTUN, static eventhandler_tag g_mirror_post_sync = NULL; static int g_mirror_shutdown = 0; -static int g_mirror_destroy_geom(struct gctl_req *req, struct g_class *mp, - struct g_geom *gp); +static g_ctl_destroy_geom_t g_mirror_destroy_geom; static g_taste_t g_mirror_taste; +static g_init_t g_mirror_init; +static g_fini_t g_mirror_fini; +static g_provgone_t g_mirror_providergone; static g_resize_t g_mirror_resize; -static void g_mirror_init(struct g_class *mp); -static void g_mirror_fini(struct g_class *mp); struct g_class g_mirror_class = { .name = G_MIRROR_CLASS_NAME, @@ -94,6 +94,7 @@ struct g_class g_mirror_class = { .destroy_geom = g_mirror_destroy_geom, .init = g_mirror_init, .fini = g_mirror_fini, + .providergone = g_mirror_providergone, .resize = g_mirror_resize }; @@ -507,6 +508,26 @@ g_mirror_destroy_disk(struct g_mirror_disk *disk) } } +static void +g_mirror_free_device(struct g_mirror_softc *sc) +{ + + mtx_destroy(&sc->sc_queue_mtx); + mtx_destroy(&sc->sc_events_mtx); + mtx_destroy(&sc->sc_done_mtx); + sx_destroy(&sc->sc_lock); + free(sc, M_MIRROR); +} + +static void +g_mirror_providergone(struct g_provider *pp) +{ + struct g_mirror_softc *sc = pp->private; + + if ((--sc->sc_refcnt) == 0) + g_mirror_free_device(sc); +} + static void g_mirror_destroy_device(struct g_mirror_softc *sc) { @@ -549,12 +570,10 @@ g_mirror_destroy_device(struct g_mirror_softc *sc) g_wither_geom(sc->sc_sync.ds_geom, ENXIO); G_MIRROR_DEBUG(0, "Device %s destroyed.", gp->name); g_wither_geom(gp, ENXIO); - g_topology_unlock(); - mtx_destroy(&sc->sc_queue_mtx); - mtx_destroy(&sc->sc_events_mtx); - mtx_destroy(&sc->sc_done_mtx); sx_xunlock(&sc->sc_lock); - sx_destroy(&sc->sc_lock); + if ((--sc->sc_refcnt) == 0) + g_mirror_free_device(sc); + g_topology_unlock(); } static void @@ -868,7 +887,7 @@ g_mirror_flush_done(struct bio *bp) struct bio *pbp; pbp = bp->bio_parent; - sc = pbp->bio_to->geom->softc; + sc = pbp->bio_to->private; mtx_lock(&sc->sc_done_mtx); if (pbp->bio_error == 0) pbp->bio_error = bp->bio_error; @@ -905,7 +924,7 @@ g_mirror_regular_request(struct bio *bp) g_topology_assert_not(); pbp = bp->bio_parent; - sc = pbp->bio_to->geom->softc; + sc = pbp->bio_to->private; bp->bio_from->index--; if (bp->bio_cmd == BIO_WRITE) sc->sc_writes--; @@ -1036,7 +1055,7 @@ g_mirror_candelete(struct bio *bp) struct g_mirror_disk *disk; int *val; - sc = bp->bio_to->geom->softc; + sc = bp->bio_to->private; LIST_FOREACH(disk, &sc->sc_disks, d_next) { if (disk->d_flags & G_MIRROR_DISK_FLAG_CANDELETE) break; @@ -1061,7 +1080,7 @@ g_mirror_kernel_dump(struct bio *bp) * we will not be able to read the dump after the reboot if it will be * connected and synchronized later. Can we do something better? */ - sc = bp->bio_to->geom->softc; + sc = bp->bio_to->private; disk = LIST_FIRST(&sc->sc_disks); gkd = (struct g_kerneldump *)bp->bio_data; @@ -1121,7 +1140,7 @@ g_mirror_start(struct bio *bp) { struct g_mirror_softc *sc; - sc = bp->bio_to->geom->softc; + sc = bp->bio_to->private; /* * If sc == NULL or there are no valid disks, provider's error * should be set and g_mirror_start() should not be called at all. @@ -1637,7 +1656,7 @@ g_mirror_register_request(struct bio *bp) { struct g_mirror_softc *sc; - sc = bp->bio_to->geom->softc; + sc = bp->bio_to->private; switch (bp->bio_cmd) { case BIO_READ: switch (sc->sc_balance) { @@ -1804,7 +1823,6 @@ g_mirror_try_destroy(struct g_mirror_softc *sc) } else { g_topology_unlock(); g_mirror_destroy_device(sc); - free(sc, M_MIRROR); } return (1); } @@ -2117,6 +2135,8 @@ g_mirror_launch_provider(struct g_mirror_softc *sc) } } } + pp->private = sc; + sc->sc_refcnt++; sc->sc_provider = pp; g_error_provider(pp, 0); g_topology_unlock(); @@ -2898,9 +2918,7 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace) G_MIRROR_DEBUG(2, "Access request for %s: r%dw%de%d.", pp->name, acr, acw, ace); - sc = pp->geom->softc; - if (sc == NULL && acr <= 0 && acw <= 0 && ace <= 0) - return (0); + sc = pp->private; KASSERT(sc != NULL, ("NULL softc (provider=%s).", pp->name)); g_topology_unlock(); @@ -2959,6 +2977,7 @@ g_mirror_create(struct g_class *mp, const struct g_mirror_metadata *md) sc->sc_idle = 1; sc->sc_last_write = time_uptime; sc->sc_writes = 0; + sc->sc_refcnt = 1; sx_init(&sc->sc_lock, "gmirror:lock"); bioq_init(&sc->sc_queue); mtx_init(&sc->sc_queue_mtx, "gmirror:queue", NULL, MTX_DEF); @@ -2989,12 +3008,8 @@ g_mirror_create(struct g_class *mp, const struct g_mirror_metadata *md) G_MIRROR_DEBUG(1, "Cannot create kernel thread for %s.", sc->sc_name); g_destroy_geom(sc->sc_sync.ds_geom); - mtx_destroy(&sc->sc_done_mtx); - mtx_destroy(&sc->sc_events_mtx); - mtx_destroy(&sc->sc_queue_mtx); - sx_destroy(&sc->sc_lock); g_destroy_geom(sc->sc_geom); - free(sc, M_MIRROR); + g_mirror_free_device(sc); return (NULL); } @@ -3017,8 +3032,6 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how) struct g_mirror_disk *disk; g_topology_assert_not(); - if (sc == NULL) - return (ENXIO); sx_assert(&sc->sc_lock, SX_XLOCKED); if (sc->sc_provider_open != 0 || SCHEDULER_STOPPED()) { @@ -3068,7 +3081,6 @@ g_mirror_destroy(struct g_mirror_softc *sc, int how) G_MIRROR_DEBUG(4, "%s: Woken up %p.", __func__, &sc->sc_worker); sx_xlock(&sc->sc_lock); g_mirror_destroy_device(sc); - free(sc, M_MIRROR); return (0); } diff --git a/sys/geom/mirror/g_mirror.h b/sys/geom/mirror/g_mirror.h index e730e42e876..ed499a55c8f 100644 --- a/sys/geom/mirror/g_mirror.h +++ b/sys/geom/mirror/g_mirror.h @@ -207,6 +207,7 @@ struct g_mirror_softc { int sc_idle; /* DIRTY flags removed. */ time_t sc_last_write; u_int sc_writes; + u_int sc_refcnt; /* Number of softc references */ TAILQ_HEAD(, g_mirror_event) sc_events; struct mtx sc_events_mtx; diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index 6644532d02e..b461747bf35 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -470,7 +470,7 @@ g_multipath_access(struct g_provider *pp, int dr, int dw, int de) gp = pp->geom; /* Error used if we have no valid consumers. */ - error = ENXIO; + error = (dr > 0 || dw > 0 || de > 0) ? ENXIO : 0; LIST_FOREACH(cp, &gp->consumer, consumer) { if (cp->index & MP_WITHER) diff --git a/sys/gnu/dts/include/dt-bindings/dma/jz4780-dma.h b/sys/gnu/dts/include/dt-bindings/dma/jz4780-dma.h new file mode 100644 index 00000000000..df017fdfb44 --- /dev/null +++ b/sys/gnu/dts/include/dt-bindings/dma/jz4780-dma.h @@ -0,0 +1,49 @@ +#ifndef __DT_BINDINGS_DMA_JZ4780_DMA_H__ +#define __DT_BINDINGS_DMA_JZ4780_DMA_H__ + +/* + * Request type numbers for the JZ4780 DMA controller (written to the DRTn + * register for the channel). + */ +#define JZ4780_DMA_I2S1_TX 0x4 +#define JZ4780_DMA_I2S1_RX 0x5 +#define JZ4780_DMA_I2S0_TX 0x6 +#define JZ4780_DMA_I2S0_RX 0x7 +#define JZ4780_DMA_AUTO 0x8 +#define JZ4780_DMA_SADC_RX 0x9 +#define JZ4780_DMA_UART4_TX 0xc +#define JZ4780_DMA_UART4_RX 0xd +#define JZ4780_DMA_UART3_TX 0xe +#define JZ4780_DMA_UART3_RX 0xf +#define JZ4780_DMA_UART2_TX 0x10 +#define JZ4780_DMA_UART2_RX 0x11 +#define JZ4780_DMA_UART1_TX 0x12 +#define JZ4780_DMA_UART1_RX 0x13 +#define JZ4780_DMA_UART0_TX 0x14 +#define JZ4780_DMA_UART0_RX 0x15 +#define JZ4780_DMA_SSI0_TX 0x16 +#define JZ4780_DMA_SSI0_RX 0x17 +#define JZ4780_DMA_SSI1_TX 0x18 +#define JZ4780_DMA_SSI1_RX 0x19 +#define JZ4780_DMA_MSC0_TX 0x1a +#define JZ4780_DMA_MSC0_RX 0x1b +#define JZ4780_DMA_MSC1_TX 0x1c +#define JZ4780_DMA_MSC1_RX 0x1d +#define JZ4780_DMA_MSC2_TX 0x1e +#define JZ4780_DMA_MSC2_RX 0x1f +#define JZ4780_DMA_PCM0_TX 0x20 +#define JZ4780_DMA_PCM0_RX 0x21 +#define JZ4780_DMA_SMB0_TX 0x24 +#define JZ4780_DMA_SMB0_RX 0x25 +#define JZ4780_DMA_SMB1_TX 0x26 +#define JZ4780_DMA_SMB1_RX 0x27 +#define JZ4780_DMA_SMB2_TX 0x28 +#define JZ4780_DMA_SMB2_RX 0x29 +#define JZ4780_DMA_SMB3_TX 0x2a +#define JZ4780_DMA_SMB3_RX 0x2b +#define JZ4780_DMA_SMB4_TX 0x2c +#define JZ4780_DMA_SMB4_RX 0x2d +#define JZ4780_DMA_DES_TX 0x2e +#define JZ4780_DMA_DES_RX 0x2f + +#endif /* __DT_BINDINGS_DMA_JZ4780_DMA_H__ */ diff --git a/sys/gnu/dts/include/dt-bindings/net/rfkill-regulator.h b/sys/gnu/dts/include/dt-bindings/net/rfkill-regulator.h new file mode 100644 index 00000000000..ae32273c7ba --- /dev/null +++ b/sys/gnu/dts/include/dt-bindings/net/rfkill-regulator.h @@ -0,0 +1,23 @@ +/* + * This header provides macros for rfkill-regulator bindings. + * + * Copyright (C) 2014 Marek Belisko + * + * GPLv2 only + */ + +#ifndef __DT_BINDINGS_RFKILL_REGULATOR_H__ +#define __DT_BINDINGS_RFKILL_REGULATOR_H__ + + +#define RFKILL_TYPE_ALL (0) +#define RFKILL_TYPE_WLAN (1) +#define RFKILL_TYPE_BLUETOOTH (2) +#define RFKILL_TYPE_UWB (3) +#define RFKILL_TYPE_WIMAX (4) +#define RFKILL_TYPE_WWAN (5) +#define RFKILL_TYPE_GPS (6) +#define RFKILL_TYPE_FM (7) +#define RFKILL_TYPE_NFC (8) + +#endif /* __DT_BINDINGS_RFKILL_REGULATOR_H__ */ diff --git a/sys/gnu/dts/mips/ingenic/canna.dts b/sys/gnu/dts/mips/ingenic/canna.dts new file mode 100644 index 00000000000..98ddb98f7ee --- /dev/null +++ b/sys/gnu/dts/mips/ingenic/canna.dts @@ -0,0 +1,42 @@ +/dts-v1/; +#include +#include +#include "x1000.dtsi" + +/ { + compatible = "ingenic,x1000"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + }; + + chosen { + stdout-path = &uart2; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x2000000>; /* 32 MiB at 0x0 */ + }; +}; + +&ext { + clock-frequency = <48000000>; +}; + +&msc0 { + bus-width = <4>; + max-frequency = <6000000>; + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_msc0_pa>; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pins_uart2_dataplusflow>; +}; diff --git a/sys/gnu/dts/mips/ingenic/ci20.dts b/sys/gnu/dts/mips/ingenic/ci20.dts new file mode 100644 index 00000000000..456c8b83f0d --- /dev/null +++ b/sys/gnu/dts/mips/ingenic/ci20.dts @@ -0,0 +1,395 @@ +/dts-v1/; +#include +#include +#include "jz4780.dtsi" + +/ { + compatible = "imgtec,ci20", "ingenic,jz4780"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial3 = &uart3; + serial4 = &uart4; + }; + + chosen { + stdout-path = &uart4; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x10000000 + 0x30000000 0x30000000>; + }; + + audio: audio-ci20 { + compatible = "ingenic,ci20-audio"; + ingenic,i2s-controller = <&i2s>; + ingenic,codec = <&codec>; + }; + + eth0_power: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "eth0_power"; + gpio = <&gpb 25 GPIO_ACTIVE_LOW>; + enable-active-high; + }; + + hdmi_power: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "hdmi_power"; + gpio = <&gpa 25 GPIO_ACTIVE_LOW>; + enable-active-high; + regulator-always-on; + }; + + wifi_power: fixedregulator@2 { + compatible = "regulator-fixed"; + regulator-name = "wifi_power_gpio"; + gpio = <&gpb 19 0>; + enable-active-high; + + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + }; + + /* HACK: Keeping wifi reset high. No simple driver fix */ + wifi_reset: fixedregulator@3 { + compatible = "regulator-fixed"; + regulator-name = "wifi_reset_gpio"; + gpio = <&gpf 7 0>; + enable-active-high; + regulator-always-on; + }; + + /* HACK: Keeping BT reset high. No simple driver fix */ + bt_reset: fixedregulator@4 { + compatible = "regulator-fixed"; + regulator-name = "bt_reset_gpio"; + gpio = <&gpf 8 0>; + enable-active-high; + }; + + /* HACK: Keeping BT_reg_on high. No simple driver fix */ + bt_reg_on: fixedregulator@5 { + compatible = "regulator-fixed"; + regulator-name = "bt_reg_on_gpio"; + gpio = <&gpf 4 0>; + enable-active-high; + regulator-always-on; + }; + + /* HACK: Keeping BT wake high. No simple driver fix */ + bt_wake: fixedregulator@6 { + compatible = "regulator-fixed"; + regulator-name = "bt_wake_gpio"; + gpio = <&gpf 5 0>; + enable-active-high; + regulator-always-on; + }; + + ir: ir-receiver { + compatible = "gpio-ir-receiver"; + gpios = <&gpe 3 GPIO_ACTIVE_LOW>; + }; + + bt-rfkill { + compatible = "rfkill-regulator"; + label = "bt-reset"; + type = ; + vrfkill-supply = <&bt_reset>; + }; + + leds { + compatible = "gpio-leds"; + led3 { + gpios = <&gpc 0 0>; + linux,default-trigger = "cpu0"; + }; + led2 { + gpios = <&gpc 1 0>; + linux,default-trigger = "cpu1"; + }; + led1 { + gpios = <&gpc 2 0>; + linux,default-trigger = "nand-disk"; + }; + led0 { + gpios = <&gpc 3 0>; + linux,default-trigger = "none"; + }; + }; +}; + +&ext { + clock-frequency = <48000000>; +}; + +&msc0 { + bus-width = <4>; + max-frequency = <50000000>; + cd-gpios = <&gpf 20 GPIO_ACTIVE_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_msc0_pe>; +}; + +&msc1 { + bus-width = <4>; + max-frequency = <24000000>; + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_msc1_pd>; + vmmc-supply = <&wifi_power>; +}; + +&ehci { + ingenic,vbus-gpio = <&gpf 15 0>; +}; + +&ohci { + ingenic,vbus-gpio = <&gpf 15 0>; +}; + +&nemc { + /* + * Only CLE/ALE are needed for the devices that are connected, rather + * than the full address line set. + */ + pinctrl-names = "default"; + pinctrl-0 = <&pins_nemc_data + &pins_nemc_cle_ale + &pins_nemc_rd_we + &pins_nemc_frd_fwe>; + + nand: nand@1 { + compatible = "ingenic,jz4780-nand"; + reg = <1 0 0x1000000>; + + ingenic,nemc-tAS = <10>; + ingenic,nemc-tAH = <5>; + ingenic,nemc-tBP = <10>; + ingenic,nemc-tAW = <15>; + ingenic,nemc-tSTRV = <100>; + + ingenic,bch-device = <&bch>; + ingenic,ecc-size = <1024>; + ingenic,ecc-strength = <24>; + + ingenic,busy-gpio = <&gpa 20 GPIO_ACTIVE_LOW>; + ingenic,wp-gpio = <&gpf 22 GPIO_ACTIVE_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_nemc_cs1>; + + #address-cells = <2>; + #size-cells = <2>; + + partition@0 { + label = "u-boot-spl"; + reg = <0x0 0x0 0x0 0x800000>; + }; + + partition@0x800000 { + label = "u-boot"; + reg = <0x0 0x800000 0x0 0x200000>; + }; + + partition@0xa00000 { + label = "u-boot-env"; + reg = <0x0 0xa00000 0x0 0x200000>; + }; + + partition@0xc00000 { + label = "boot"; + reg = <0x0 0xc00000 0x0 0x4000000>; + }; + + partition@0x8c00000 { + label = "system"; + reg = <0x0 0x4c00000 0x1 0xfb400000>; + }; + }; + + dm9000@6 { + compatible = "davicom,dm9000"; + davicom,no-eeprom; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_nemc_cs6>; + + reg = <6 0x0 1 /* addr */ + 6 0x2 1>; /* data */ + + ingenic,nemc-tAS = <15>; + ingenic,nemc-tAH = <10>; + ingenic,nemc-tBP = <20>; + ingenic,nemc-tAW = <50>; + ingenic,nemc-tSTRV = <100>; + + reset-gpios = <&gpf 12 GPIO_ACTIVE_HIGH>; + vcc-supply = <ð0_power>; + + interrupt-parent = <&gpe>; + interrupts = <19 0x4>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pins_uart0_data>; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pins_uart1_data>; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pins_uart2_dataplusflow>; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pins_uart3_data>; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pins_uart4_data>; +}; + +&i2c0 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pins_i2c0_data>; + + pmic: act8600@5a { + compatible = "active-semi,act8600"; + reg = <0x5a>; + + regulators { + vcore1v_reg: DCDC_REG1 { + regulator-name = "vcore1v2"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-always-on; + }; + + vddmem1v5_reg: DCDC_REG2 { + regulator-name = "vddmem1v5"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + }; + + vccio3v3_reg: DCDC_REG3 { + regulator-name = "vccio3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vcc2v5_reg: LDO_REG5 { + regulator-name = "vcc2.5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + vwifi_reg: LDO_REG6 { + regulator-name = "vwifi3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcim2v8_reg: LDO_REG7 { + regulator-name = "vcim2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vcim1v5_reg: LDO_REG8 { + regulator-name = "vcim1v5"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + }; + + /* Do not disable RTC as they connect to reset line */ + vrtc1v8_reg: LDO_REG9 { + regulator-name = "vrtc1v8"; + regulator-always-on; + }; + + vrtc1v1_reg: LDO_REG10 { + regulator-name = "vrtc1v2"; + regulator-always-on; + }; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pins_i2c1_data>; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pins_i2c2_data>; + + ov5640@0x3C { + compatible = "omnivision,ov5640"; + reg = <0x3C>; + + core-supply = <&vcim1v5_reg>; + analog-supply = <&vcim2v8_reg>; + + gpio-enable = <&gpb 18 0>; + gpio-reset = <&gpb 26 0>; + + remote = <&cim>; + port { + ov5640_1: endpoint { + bus-width = <8>; + remote-endpoint = <&cim>; + }; + }; + }; +}; + +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pins_i2c3_data>; +}; + +&i2c4 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pins_i2c4_data_pf>; +}; + +&cim { + clock-frequency = <24000000>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + /* Parallel bus endpoint */ + camera: endpoint@0 { + reg = <0>; /* Local endpoint # */ + remote-endpoint = <&ov5640_1>; + hsync-active = <1>; /* Active high */ + vsync-active = <1>; /* Active high */ + pclk-sample = <0>; /* Falling */ + }; + }; +}; diff --git a/sys/gnu/dts/mips/ingenic/jz4780.dtsi b/sys/gnu/dts/mips/ingenic/jz4780.dtsi new file mode 100644 index 00000000000..c53ee03f463 --- /dev/null +++ b/sys/gnu/dts/mips/ingenic/jz4780.dtsi @@ -0,0 +1,768 @@ +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ingenic,jz4780"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "ingenic,xburst"; + reg = <0>; + }; + cpu1: cpu@1 { + compatible = "ingenic,xburst"; + reg = <1>; + clocks = <&cgu JZ4780_CLK_CORE1>; + }; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + intc: intc@10001000 { + compatible = "ingenic,jz4780-intc"; + reg = <0x10001000 0x50>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + ext: ext { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + rtc: rtc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + cgu: jz4780-cgu@10000000 { + compatible = "ingenic,jz4780-cgu"; + reg = <0x10000000 0x100>; + + clocks = <&ext>, <&rtc>; + clock-names = "ext", "rtc"; + + #clock-cells = <1>; + }; + + gpu: jz4780-sgx@13040000 { + compatible = "ingenic,jz4780-sgx"; + reg = <0x13040000 0x4000>; + + clocks = <&cgu JZ4780_CLK_GPU>; + clock-names = "gpu"; + + interrupt-parent = <&intc>; + interrupts = <63>; + }; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <>; + + tcu@0x10002000 { + compatible = "ingenic,jz4780-tcu"; + reg = <0x10002000 0x140>; + + interrupt-parent = <&intc>; + interrupts = <27 26 25>; + }; + + watchdog: jz47xx-watchdog@0x10002000 { + compatible = "ingenic,jz4780-watchdog"; + reg = <0x10002000 0x100>; + + clocks = <&rtc>; + clock-names = "rtc"; + }; + + rtcdev: rtcdev@10003000 { + compatible = "ingenic,jz4780-rtc"; + reg = <0x10003000 0x4c>; + interrupt-parent = <&intc>; + interrupts = <32>; + }; + + i2s: i2s@10020000 { + compatible = "ingenic,jz4780-i2s"; + reg = <0x10020000 0x94>; + + clocks = <&cgu JZ4780_CLK_AIC>, <&cgu JZ4780_CLK_I2SPLL>; + clock-names = "aic", "i2s"; + + dmas = <&dma 0 JZ4780_DMA_I2S0_RX 0xffffffff>, <&dma JZ4780_DMA_I2S0_TX 0 0xffffffff>; + dma-names = "rx" , "tx"; + + }; + + codec: codec@100200a4 { + compatible = "ingenic,jz4780-codec"; + reg = <0x100200a4 0x8>; + + clocks = <&cgu JZ4780_CLK_I2SPLL>; + clock-names = "i2s"; + + }; + + pinctrl@0x10010000 { + compatible = "ingenic,jz4780-pinctrl"; + reg = <0x10010000 0x600>; + + gpa: gpa { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <17>; + + ingenic,pull-ups = <0x3fffffff>; + }; + + gpb: gpb { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <16>; + + ingenic,pull-downs = <0x000f0c03>; + ingenic,pull-ups = <0xfff0030c>; + }; + + gpc: gpc { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <15>; + + ingenic,pull-ups = <0xffffffff>; + }; + + gpd: gpd { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <14>; + + ingenic,pull-downs = <0x0000b000>; + ingenic,pull-ups = <0xffff4fff>; + }; + + gpe: gpe { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <13>; + + ingenic,pull-downs = <0x00000483>; + ingenic,pull-ups = <0xfffffb7c>; + }; + + gpf: gpf { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <12>; + + ingenic,pull-downs = <0x00580ff0>; + ingenic,pull-ups = <0xffa7f00f>; + }; + + pincfg_nobias: nobias { + bias-disable; + }; + + pincfg_pull_up: pull_up { + bias-pull-up; + }; + + pincfg_pull_down: pull_down { + bias-pull-down; + }; + + pinfunc_uart0: uart0 { + pins_uart0_data: uart0-data { + ingenic,pins = <&gpf 0 0 &pincfg_pull_up /* rxd */ + &gpf 3 0 &pincfg_nobias>; /* txd */ + }; + + pins_uart0_dataplusflow: uart0-dataplusflow { + ingenic,pins = <&gpf 0 0 &pincfg_pull_up /* rxd */ + &gpf 1 0 &pincfg_nobias /* cts */ + &gpf 2 0 &pincfg_nobias /* rts */ + &gpf 3 0 &pincfg_nobias>; /* txd */ + }; + }; + + pinfunc_uart1: uart1 { + pins_uart1_data: uart1-data { + ingenic,pins = <&gpd 26 0 &pincfg_pull_up /* rxd */ + &gpd 28 0 &pincfg_nobias>; /* txd */ + }; + + pins_uart1_dataplusflow: uart1-dataplusflow { + ingenic,pins = <&gpd 26 0 &pincfg_pull_up /* rxd */ + &gpd 27 0 &pincfg_nobias /* cts */ + &gpd 29 0 &pincfg_nobias /* rts */ + &gpd 28 0 &pincfg_nobias>; /* txd */ + }; + }; + + pinfunc_uart2: uart2 { + pins_uart2_data: uart2-data { + ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */ + &gpd 7 1 &pincfg_nobias>; /* txd */ + }; + + pins_uart2_dataplusflow: uart2-dataplusflow { + ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */ + &gpd 5 1 &pincfg_nobias /* cts */ + &gpd 4 1 &pincfg_nobias /* rts */ + &gpd 7 1 &pincfg_nobias>; /* txd */ + }; + }; + + pinfunc_uart3: uart3 { + pins_uart3_data: uart3-data { + ingenic,pins = <&gpd 12 0 &pincfg_pull_down /* rxd */ + &gpe 5 1 &pincfg_nobias>; /* txd */ + }; + + pins_uart3_dataplusflow: uart3-dataplusflow { + ingenic,pins = <&gpd 12 0 &pincfg_pull_down /* rxd */ + &gpe 5 1 &pincfg_nobias /* txd */ + &gpe 8 0 &pincfg_nobias /* cts */ + &gpe 9 0 &pincfg_nobias>; /* rts */ + }; + }; + + pinfunc_uart4: uart4 { + pins_uart4_data: uart4-data { + ingenic,pins = <&gpc 20 2 &pincfg_pull_up /* rxd */ + &gpc 10 2 &pincfg_nobias>; /* txd */ + }; + }; + + pinfunc_msc0: msc0 { + pins_msc0_pa: msc0-pa { + ingenic,pins = <&gpa 4 1 &pincfg_nobias /* d4 */ + &gpa 5 1 &pincfg_nobias /* d5 */ + &gpa 6 1 &pincfg_nobias /* d6 */ + &gpa 7 1 &pincfg_nobias /* d7 */ + &gpa 18 1 &pincfg_nobias /* clk */ + &gpa 19 1 &pincfg_nobias /* cmd */ + &gpa 20 1 &pincfg_nobias /* d0 */ + &gpa 21 1 &pincfg_nobias /* d1 */ + &gpa 22 1 &pincfg_nobias /* d2 */ + &gpa 23 1 &pincfg_nobias /* d3 */ + &gpa 24 1 &pincfg_nobias>; /* rst */ + }; + + pins_msc0_pe: msc0-pe { + ingenic,pins = <&gpe 20 0 &pincfg_nobias /* d0 */ + &gpe 21 0 &pincfg_nobias /* d1 */ + &gpe 22 0 &pincfg_nobias /* d2 */ + &gpe 23 0 &pincfg_nobias /* d3 */ + &gpe 28 0 &pincfg_nobias /* clk */ + &gpe 29 0 &pincfg_nobias>; /* cmd */ + }; + }; + + pinfunc_msc1: msc1 { + pins_msc1_pd: msc1-pd { + ingenic,pins = <&gpd 20 0 &pincfg_nobias /* d0 */ + &gpd 21 0 &pincfg_nobias /* d1 */ + &gpd 22 0 &pincfg_nobias /* d2 */ + &gpd 23 0 &pincfg_nobias /* d3 */ + &gpd 24 0 &pincfg_nobias /* clk */ + &gpd 25 0 &pincfg_nobias>; /* cmd */ + }; + + pins_msc1_pe: msc1-pe { + ingenic,pins = <&gpe 20 1 &pincfg_nobias /* d0 */ + &gpe 21 1 &pincfg_nobias /* d1 */ + &gpe 22 1 &pincfg_nobias /* d2 */ + &gpe 23 1 &pincfg_nobias /* d3 */ + &gpe 28 1 &pincfg_nobias /* clk */ + &gpe 29 1 &pincfg_nobias>; /* cmd */ + }; + }; + + pinfunc_nemc: nemc { + pins_nemc_data: nemc-data { + ingenic,pins = <&gpa 0 0 &pincfg_nobias /* sd0 */ + &gpa 1 0 &pincfg_nobias /* sd1 */ + &gpa 2 0 &pincfg_nobias /* sd2 */ + &gpa 3 0 &pincfg_nobias /* sd3 */ + &gpa 4 0 &pincfg_nobias /* sd4 */ + &gpa 5 0 &pincfg_nobias /* sd5 */ + &gpa 6 0 &pincfg_nobias /* sd6 */ + &gpa 7 0 &pincfg_nobias>; /* sd7 */ + }; + + pins_nemc_cle_ale: nemc-cle-ale { + ingenic,pins = <&gpb 0 0 &pincfg_nobias /* sa0_cl */ + &gpb 1 0 &pincfg_nobias>; /* sa1_al */ + }; + + pins_nemc_addr: nemc-addr { + ingenic,pins = <&gpb 0 0 &pincfg_nobias /* sa0_cl */ + &gpb 1 0 &pincfg_nobias /* sa1_al */ + &gpb 2 0 &pincfg_nobias /* sa2 */ + &gpb 3 0 &pincfg_nobias /* sa3 */ + &gpb 4 0 &pincfg_nobias /* sa4 */ + &gpb 5 0 &pincfg_nobias>; /* sa5 */ + }; + + pins_nemc_rd_we: nemc-rd-we { + ingenic,pins = <&gpa 16 0 &pincfg_nobias /* rd */ + &gpa 17 0 &pincfg_nobias>; /* we */ + }; + + pins_nemc_frd_fwe: nemc-frd-fwe { + ingenic,pins = <&gpa 18 0 &pincfg_nobias /* rd */ + &gpa 19 0 &pincfg_nobias>; /* we */ + }; + + pins_nemc_cs1: nemc-cs1 { + ingenic,pins = <&gpa 21 0 &pincfg_nobias>; /* cs1 */ + }; + + pins_nemc_cs6: nemc-cs6 { + ingenic,pins = <&gpa 26 0 &pincfg_nobias>; /* cs6 */ + }; + }; + + pinfunc_i2c0: i2c0 { + pins_i2c0_data: i2c0-data{ + ingenic,pins = <&gpd 30 0 &pincfg_nobias /* sda */ + &gpd 31 0 &pincfg_nobias>; /* sck */ + }; + }; + + pinfunc_i2c1: i2c1 { + pins_i2c1_data: i2c1-data{ + ingenic,pins = <&gpe 30 0 &pincfg_nobias /* sda */ + &gpe 31 0 &pincfg_nobias>; /* sck */ + }; + }; + + pinfunc_i2c2: i2c2 { + pins_i2c2_data: i2c2-data{ + ingenic,pins = <&gpf 16 2 &pincfg_nobias /* sda */ + &gpf 17 2 &pincfg_nobias>; /* sck */ + }; + }; + + pinfunc_i2c3: i2c3 { + pins_i2c3_data: i2c3-data{ + ingenic,pins = <&gpd 10 1 &pincfg_nobias /* sda */ + &gpd 11 1 &pincfg_nobias>; /* sck */ + }; + }; + + pinfunc_i2c4: i2c4 { + pins_i2c4_data: i2c4-data-pe{ + ingenic,pins = <&gpe 12 1 &pincfg_nobias /* sda */ + &gpe 13 1 &pincfg_nobias>; /* sck */ + }; + + pins_i2c4_data_pf: i2c4-data-pf{ + ingenic,pins = <&gpf 25 1 &pincfg_nobias /* hdmi_sda */ + &gpf 24 1 &pincfg_nobias>; /* hdmi_sck */ + }; + }; + + pinfunc_cim: cim { + pins_cim: cim-pb { + ingenic,pins = <&gpb 6 0 &pincfg_nobias + &gpb 7 0 &pincfg_nobias + &gpb 8 0 &pincfg_nobias + &gpb 9 0 &pincfg_nobias + &gpb 10 0 &pincfg_nobias + &gpb 11 0 &pincfg_nobias + &gpb 12 0 &pincfg_nobias + &gpb 13 0 &pincfg_nobias + &gpb 14 0 &pincfg_nobias + &gpb 15 0 &pincfg_nobias + &gpb 16 0 &pincfg_nobias + &gpb 17 0 &pincfg_nobias>; + }; + }; + }; + + spi_gpio { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + num-chipselects = <2>; + + gpio-miso = <&gpe 14 0>; + gpio-sck = <&gpe 15 0>; + gpio-mosi = <&gpe 17 0>; + cs-gpios = <&gpe 16 0 + &gpe 18 0>; + + spidev@0 { + compatible = "spidev"; + reg = <0>; + spi-max-frequency = <1000000>; + }; + }; + + uart0: serial@10030000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10030000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <51>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART0>; + clock-names = "baud", "module"; + }; + + uart1: serial@10031000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10031000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <50>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART1>; + clock-names = "baud", "module"; + }; + + uart2: serial@10032000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10032000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <49>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART2>; + clock-names = "baud", "module"; + }; + + uart3: serial@10033000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10033000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <48>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART3>; + clock-names = "baud", "module"; + }; + + uart4: serial@10034000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10034000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <34>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART4>; + clock-names = "baud", "module"; + }; + + i2c0: i2c0@0x10050000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10050000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <60>; + + clocks = <&cgu JZ4780_CLK_SMB0>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c1@0x10051000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10051000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <59>; + + clocks = <&cgu JZ4780_CLK_SMB1>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c2@0x10052000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10052000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <58>; + + clocks = <&cgu JZ4780_CLK_SMB2>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c3: i2c3@0x10053000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10053000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <57>; + + clocks = <&cgu JZ4780_CLK_SMB3>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c4: i2c4@0x10054000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10054000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <56>; + + clocks = <&cgu JZ4780_CLK_SMB4>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + lpcr: lcr@0x10000004 { + compatible = "ingenic,jz4780-lcr"; + reg = <0x10000004 0x4>; + + regulators { + vpu_power: VPU { + }; + gpu_power: GPU { + }; + gps_power: GPS { + }; + }; + }; + + adc@0x10070000 { + compatible = "ingenic,jz4780-adc"; + reg = <0x10070000 0x30>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + clocks = <&cgu JZ4780_CLK_SADC>; + clock-names = "adc"; + }; + }; + + ahb2 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <>; + + + lcd: jz4780-lcdk@0x13050000 { + compatible = "ingenic,jz4780-lcd"; + reg = <0x13050000 0x1800>; + + clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD0PIXCLK>; + clock-names = "lcd_clk", "lcd_pixclk"; + + interrupt-parent = <&intc>; + interrupts = <31>; + + hdmi = <&hdmi>; + ddc = <&i2c4>; + }; + + cim: jz4780-cim@0x13060000 { + compatible = "ingenic,jz4780-cim"; + reg = <0x13060000 0x68>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <30>; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_cim>; + + clocks = <&cgu JZ4780_CLK_CIM>, <&cgu JZ4780_CLK_CIMMCLK>; + clock-names = "cim", "module"; + }; + + hdmi: jz4780-hdmi3@0x10180000 { + compatible = "synopsys,dwc-hdmi"; + reg = <0x10180000 0x8000>; + reg-shift = <2>; + + clocks = <&cgu JZ4780_CLK_HDMI>, <&cgu JZ4780_CLK_AHB0>; + clock-names = "hdmi" , "ahb"; + + clock-frequency = <27000000>; + + interrupt-parent = <&intc>; + interrupts = <3>; + + ddc = <&i2c4>; + }; + + + nemc: nemc@13410000 { + compatible = "ingenic,jz4780-nemc"; + reg = <0x13410000 0x10000>; + #address-cells = <2>; + #size-cells = <1>; + ranges = <1 0 0x1b000000 0x1000000 + 2 0 0x1a000000 0x1000000 + 3 0 0x19000000 0x1000000 + 4 0 0x18000000 0x1000000 + 5 0 0x17000000 0x1000000 + 6 0 0x16000000 0x1000000>; + + clocks = <&cgu JZ4780_CLK_NEMC>; + }; + + efuse: efuse@134100D0 { + compatible = "ingenic,jz4780-efuse"; + reg = <0x134100D0 0xFF>; + + clocks = <&cgu JZ4780_CLK_AHB2>; + clock-names = "bus_clk"; + }; + + dma: dma@13420000 { + compatible = "ingenic,jz4780-dma"; + reg = <0x13420000 0x10000>; + + interrupt-parent = <&intc>; + interrupts = <10>; + + clocks = <&cgu JZ4780_CLK_PDMA>; + + #dma-cells = <3>; + }; + + msc0: msc@13450000 { + compatible = "ingenic,jz4780-mmc"; + reg = <0x13450000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <37>; + + clocks = <&cgu JZ4780_CLK_MSC0>; + clock-names = "mmc"; + + cap-sd-highspeed; + cap-mmc-highspeed; + cap-sdio-irq; + + dmas = <&dma JZ4780_DMA_MSC0_TX JZ4780_DMA_MSC0_RX 0xffffffff>; + dma-names = "rx-tx"; + }; + + msc1: msc@13460000 { + compatible = "ingenic,jz4780-mmc"; + reg = <0x13460000 0x1000>; + + status = "disabled"; + + interrupt-parent = <&intc>; + interrupts = <36>; + + clocks = <&cgu JZ4780_CLK_MSC1>; + clock-names = "mmc"; + + cap-sd-highspeed; + cap-mmc-highspeed; + cap-sdio-irq; + + dmas = <&dma JZ4780_DMA_MSC1_TX JZ4780_DMA_MSC1_RX 0xffffffff>; + dma-names = "rx-tx"; + }; + + ehci: jz4780-ehci@0x13490000 { + compatible = "ingenic,jz4780-ehci"; + reg = <0x13490000 0x10000>; + + interrupt-parent = <&intc>; + interrupts = <20>; + + clocks = <&cgu JZ4780_CLK_UHC>; + }; + + ohci: jz4780-ohci@0x134a0000 { + compatible = "ingenic,jz4780-ohci"; + reg = <0x134a0000 0x10000>; + + interrupt-parent = <&intc>; + interrupts = <5>; + + clocks = <&cgu JZ4780_CLK_UHC>; + clock-names = "uhc"; + }; + + bch: bch@134d0000 { + compatible = "ingenic,jz4780-bch"; + reg = <0x134d0000 0x10000>; + + clocks = <&cgu JZ4780_CLK_BCH>; + }; + + otg: jz4780-otg@0x13500000 { + compatible = "ingenic,jz4780-otg"; + reg = <0x13500000 0x40000>; + + interrupt-parent = <&intc>; + interrupts = <21>; + + clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_OTG1>; + clock-names = "otg_phy", "otg1"; + }; + }; +}; diff --git a/sys/gnu/dts/mips/ingenic/x1000.dtsi b/sys/gnu/dts/mips/ingenic/x1000.dtsi new file mode 100644 index 00000000000..dd0105e04e5 --- /dev/null +++ b/sys/gnu/dts/mips/ingenic/x1000.dtsi @@ -0,0 +1,420 @@ +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ingenic,x1000"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "ingenic,xburst"; + reg = <0>; + }; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + intc: intc@10001000 { + compatible = "ingenic,jz4780-intc"; + reg = <0x10001000 0x50>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + ext: ext { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + rtc: rtc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + cgu: jz4780-cgu@10000000 { + compatible = "ingenic,jz4780-cgu"; + reg = <0x10000000 0x100>; + + clocks = <&ext>, <&rtc>; + clock-names = "ext", "rtc"; + + #clock-cells = <1>; + }; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <>; + + tcu@0x10002000 { + compatible = "ingenic,jz4780-tcu"; + reg = <0x10002000 0x140>; + + interrupt-parent = <&intc>; + interrupts = <27 26 25>; + }; + + watchdog: jz47xx-watchdog@0x10002000 { + compatible = "ingenic,jz4780-watchdog"; + reg = <0x10002000 0x100>; + + clocks = <&rtc>; + clock-names = "rtc"; + }; + + rtcdev: rtcdev@10003000 { + compatible = "ingenic,jz4780-rtc"; + reg = <0x10003000 0x4c>; + interrupt-parent = <&intc>; + interrupts = <32>; + }; + + i2s: i2s@10020000 { + compatible = "ingenic,jz4780-i2s"; + reg = <0x10020000 0x94>; + + clocks = <&cgu JZ4780_CLK_AIC>, <&cgu JZ4780_CLK_I2SPLL>; + clock-names = "aic", "i2s"; + + dmas = <&dma 0 JZ4780_DMA_I2S0_RX 0xffffffff>, <&dma JZ4780_DMA_I2S0_TX 0 0xffffffff>; + dma-names = "rx" , "tx"; + + }; + + codec: codec@100200a4 { + compatible = "ingenic,jz4780-codec"; + reg = <0x100200a4 0x8>; + + clocks = <&cgu JZ4780_CLK_I2SPLL>; + clock-names = "i2s"; + + }; + + pinctrl@0x10010000 { + compatible = "ingenic,jz4780-pinctrl"; + reg = <0x10010000 0x600>; + + gpa: gpa { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <17>; + + ingenic,pull-ups = <0x3fffffff>; + }; + + gpb: gpb { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <16>; + + ingenic,pull-downs = <0x000f0c03>; + ingenic,pull-ups = <0xfff0030c>; + }; + + gpc: gpc { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <15>; + + ingenic,pull-ups = <0xffffffff>; + }; + + gpd: gpd { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&intc>; + interrupts = <14>; + + ingenic,pull-downs = <0x0000b000>; + ingenic,pull-ups = <0xffff4fff>; + }; + + pincfg_nobias: nobias { + bias-disable; + }; + + pincfg_pull_up: pull_up { + bias-pull-up; + }; + + pincfg_pull_down: pull_down { + bias-pull-down; + }; + + pinfunc_uart2: uart2 { + pins_uart2_data: uart2-data { + ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */ + &gpd 7 1 &pincfg_nobias>; /* txd */ + }; + + pins_uart2_dataplusflow: uart2-dataplusflow { + ingenic,pins = <&gpd 6 1 &pincfg_nobias /* rxd */ + &gpd 5 1 &pincfg_nobias /* cts */ + &gpd 4 1 &pincfg_nobias /* rts */ + &gpd 7 1 &pincfg_nobias>; /* txd */ + }; + }; + + pinfunc_msc0: msc0 { + pins_msc0_pa: msc0-pa { + ingenic,pins = <&gpa 16 1 &pincfg_nobias /* d7 */ + &gpa 17 1 &pincfg_nobias /* d6 */ + &gpa 18 1 &pincfg_nobias /* d5 */ + &gpa 19 1 &pincfg_nobias /* d4 */ + &gpa 20 1 &pincfg_nobias /* d3 */ + &gpa 21 1 &pincfg_nobias /* d2 */ + &gpa 22 1 &pincfg_nobias /* d1 */ + &gpa 23 1 &pincfg_nobias /* d0 */ + &gpa 24 1 &pincfg_nobias /* clk */ + &gpa 25 1 &pincfg_nobias>; /* cmd */ + }; + }; + + pinfunc_cim: cim { + pins_cim: cim-pb { + ingenic,pins = < /* Fill me. */ >; + }; + }; + }; + + uart0: serial@10030000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10030000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <51>; + status = "disabled"; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART0>; + clock-names = "baud", "module"; + }; + + uart1: serial@10031000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10031000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <50>; + status = "disabled"; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART1>; + clock-names = "baud", "module"; + }; + + uart2: serial@10032000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10032000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <49>; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART2>; + clock-names = "baud", "module"; + }; + + uart3: serial@10033000 { + compatible = "ingenic,jz4780-uart"; + reg = <0x10033000 0x100>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <48>; + status = "disabled"; + + clocks = <&ext>, <&cgu JZ4780_CLK_UART3>; + clock-names = "baud", "module"; + }; + + i2c0: i2c0@0x10050000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10050000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <60>; + + clocks = <&cgu JZ4780_CLK_SMB0>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c1: i2c1@0x10051000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10051000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <59>; + + clocks = <&cgu JZ4780_CLK_SMB1>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c2: i2c2@0x10052000 { + compatible = "ingenic,jz4780-i2c"; + reg = <0x10052000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <58>; + + clocks = <&cgu JZ4780_CLK_SMB2>; + + #address-cells = <1>; + #size-cells = <0>; + }; + + lpcr: lcr@0x10000004 { + compatible = "ingenic,jz4780-lcr"; + reg = <0x10000004 0x4>; + + regulators { + vpu_power: VPU { + }; + gpu_power: GPU { + }; + gps_power: GPS { + }; + }; + }; + }; + + ahb2 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <>; + + lcd: jz4780-lcdk@0x13050000 { + compatible = "ingenic,jz4780-lcd"; + reg = <0x13050000 0x1800>; + + clocks = <&cgu JZ4780_CLK_TVE>, <&cgu JZ4780_CLK_LCD0PIXCLK>; + clock-names = "lcd_clk", "lcd_pixclk"; + + interrupt-parent = <&intc>; + interrupts = <31>; + }; + + cim: jz4780-cim@0x13060000 { + compatible = "ingenic,jz4780-cim"; + reg = <0x13060000 0x68>; + reg-shift = <2>; + + interrupt-parent = <&intc>; + interrupts = <30>; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_cim>; + + clocks = <&cgu JZ4780_CLK_CIM>, <&cgu JZ4780_CLK_CIMMCLK>; + clock-names = "cim", "module"; + }; + + efuse: efuse@13540000 { + compatible = "ingenic,jz4780-efuse"; + reg = <0x13540000 0xFF>; + + clocks = <&cgu JZ4780_CLK_AHB2>; + clock-names = "bus_clk"; + }; + + dma: dma@13420000 { + compatible = "ingenic,jz4780-dma"; + reg = <0x13420000 0x10000>; + + interrupt-parent = <&intc>; + interrupts = <10>; + + clocks = <&cgu JZ4780_CLK_PDMA>; + + #dma-cells = <3>; + }; + + msc0: msc@13450000 { + compatible = "ingenic,jz4780-mmc"; + reg = <0x13450000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <37>; + + clocks = <&cgu JZ4780_CLK_MSC0>; + clock-names = "mmc"; + + cap-sd-highspeed; + cap-mmc-highspeed; + cap-sdio-irq; + + dmas = <&dma JZ4780_DMA_MSC0_TX JZ4780_DMA_MSC0_RX 0xffffffff>; + dma-names = "rx-tx"; + }; + + msc1: msc@13460000 { + compatible = "ingenic,jz4780-mmc"; + reg = <0x13460000 0x1000>; + + status = "disabled"; + + interrupt-parent = <&intc>; + interrupts = <36>; + + clocks = <&cgu JZ4780_CLK_MSC1>; + clock-names = "mmc"; + + cap-sd-highspeed; + cap-mmc-highspeed; + cap-sdio-irq; + + dmas = <&dma JZ4780_DMA_MSC1_TX JZ4780_DMA_MSC1_RX 0xffffffff>; + dma-names = "rx-tx"; + }; + + otg: jz4780-otg@0x13500000 { + compatible = "ingenic,jz4780-otg"; + reg = <0x13500000 0x40000>; + + interrupt-parent = <&intc>; + interrupts = <21>; + + clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_OTG1>; + clock-names = "otg_phy", "otg1"; + }; + }; +}; diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 3cf0c5a6658..2ab8d1b485c 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -856,6 +856,14 @@ trap_pfault(frame, usermode, eva) } } + /* + * If the trap was caused by errant bits in the PTE then panic. + */ + if (frame->tf_err & PGEX_RSV) { + trap_fatal(frame, eva); + return (-1); + } + /* * PGEX_I is defined only if the execute disable bit capability is * supported and enabled. @@ -926,9 +934,15 @@ trap_fatal(frame, eva) #endif if (type == T_PAGEFLT) { printf("fault virtual address = 0x%x\n", eva); - printf("fault code = %s %s, %s\n", + printf("fault code = %s %s%s, %s\n", code & PGEX_U ? "user" : "supervisor", code & PGEX_W ? "write" : "read", +#if defined(PAE) || defined(PAE_TABLES) + pg_nx != 0 ? + (code & PGEX_I ? " instruction" : " data") : +#endif + "", + code & PGEX_RSV ? "reserved bits in PTE" : code & PGEX_P ? "protection violation" : "page not present"); } printf("instruction pointer = 0x%x:0x%x\n", diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 7d9adb05021..1a41aac581d 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1006,7 +1006,7 @@ exec_map_first_page(imgp) break; } else { ma[i] = vm_page_alloc(object, i, - VM_ALLOC_NORMAL | VM_ALLOC_IFNOTCACHED); + VM_ALLOC_NORMAL); if (ma[i] == NULL) break; } diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c index cac4d3649e6..2b21b3831d0 100644 --- a/sys/kern/kern_sendfile.c +++ b/sys/kern/kern_sendfile.c @@ -62,6 +62,8 @@ __FBSDID("$FreeBSD$"); #include #include +extern vm_page_t bogus_page; + /* * Structure describing a single sendfile(2) I/O, which may consist of * several underlying pager I/Os. @@ -258,7 +260,8 @@ sendfile_iodone(void *arg, vm_page_t *pg, int count, int error) struct socket *so; for (int i = 0; i < count; i++) - vm_page_xunbusy(pg[i]); + if (pg[i] != bogus_page) + vm_page_xunbusy(pg[i]); if (error) sfio->error = error; @@ -341,51 +344,53 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, off_t off, off_t len, } /* - * Now 'i' points to first invalid page, iterate further - * to make 'j' point at first valid after a bunch of - * invalid ones. - */ - for (j = i + 1; j < npages; j++) - if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK, - xfsize(j, npages, off, len))) { - SFSTAT_INC(sf_pages_valid); - break; - } - - /* - * Now we got region of invalid pages between 'i' and 'j'. - * Check that they belong to pager. They may not be there, - * which is a regular situation for shmem pager. For vnode - * pager this happens only in case of sparse file. + * Next page is invalid. Check if it belongs to pager. It + * may not be there, which is a regular situation for shmem + * pager. For vnode pager this happens only in case of + * a sparse file. * * Important feature of vm_pager_has_page() is the hint * stored in 'a', about how many pages we can pagein after * this page in a single I/O. */ - while (!vm_pager_has_page(obj, OFF_TO_IDX(vmoff(i, off)), - NULL, &a) && i < j) { + if (!vm_pager_has_page(obj, OFF_TO_IDX(vmoff(i, off)), NULL, + &a)) { pmap_zero_page(pa[i]); pa[i]->valid = VM_PAGE_BITS_ALL; pa[i]->dirty = 0; vm_page_xunbusy(pa[i]); i++; - } - if (i == j) continue; + } /* * We want to pagein as many pages as possible, limited only * by the 'a' hint and actual request. - * - * We should not pagein into already valid page, thus if - * 'j' didn't reach last page, trim by that page. - * - * When the pagein fulfils the request, also specify readahead. */ - if (j < npages) - a = min(a, j - i - 1); count = min(a + 1, npages - i); + /* + * We should not pagein into a valid page, thus we first trim + * any valid pages off the end of request, and substitute + * to bogus_page those, that are in the middle. + */ + for (j = i + count - 1; j > i; j--) { + if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK, + xfsize(j, npages, off, len))) { + count--; + rhpages = 0; + } else + break; + } + for (j = i + 1; j < i + count - 1; j++) + if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK, + xfsize(j, npages, off, len))) { + vm_page_xunbusy(pa[j]); + SFSTAT_INC(sf_pages_valid); + SFSTAT_INC(sf_pages_bogus); + pa[j] = bogus_page; + } + refcount_acquire(&sfio->nios); rv = vm_pager_get_pages_async(obj, pa + i, count, NULL, i + count == npages ? &rhpages : NULL, @@ -398,13 +403,18 @@ sendfile_swapin(vm_object_t obj, struct sf_io *sfio, off_t off, off_t len, if (i + count == npages) SFSTAT_ADD(sf_rhpages_read, rhpages); -#ifdef INVARIANTS - for (j = i; j < i + count && j < npages; j++) - KASSERT(pa[j] == vm_page_lookup(obj, - OFF_TO_IDX(vmoff(j, off))), - ("pa[j] %p lookup %p\n", pa[j], - vm_page_lookup(obj, OFF_TO_IDX(vmoff(j, off))))); -#endif + /* + * Restore the valid page pointers. They are already + * unbusied, but still wired. + */ + for (j = i; j < i + count; j++) + if (pa[j] == bogus_page) { + pa[j] = vm_page_lookup(obj, + OFF_TO_IDX(vmoff(j, off))); + KASSERT(pa[j], ("%s: page %p[%d] disappeared", + __func__, pa, j)); + + } i += count; nios++; } @@ -696,13 +706,20 @@ retry_space: /* * Calculate maximum allowed number of pages for readahead - * at this iteration. First, we allow readahead up to "rem". + * at this iteration. If SF_USER_READAHEAD was set, we don't + * do any heuristics and use exactly the value supplied by + * application. Otherwise, we allow readahead up to "rem". * If application wants more, let it be, but there is no * reason to go above MAXPHYS. Also check against "obj_size", * since vm_pager_has_page() can hint beyond EOF. */ - rhpages = howmany(rem + (off & PAGE_MASK), PAGE_SIZE) - npages; - rhpages += SF_READAHEAD(flags); + if (flags & SF_USER_READAHEAD) { + rhpages = SF_READAHEAD(flags); + } else { + rhpages = howmany(rem + (off & PAGE_MASK), PAGE_SIZE) - + npages; + rhpages += SF_READAHEAD(flags); + } rhpages = min(howmany(MAXPHYS, PAGE_SIZE), rhpages); rhpages = min(howmany(obj_size - trunc_page(off), PAGE_SIZE) - npages, rhpages); diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index ae2dfcd52ec..2bdc2bf8d81 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -198,7 +198,9 @@ struct umtxq_chain { PRI_MAX_TIMESHARE : (td)->td_user_pri) #define GOLDEN_RATIO_PRIME 2654404609U +#ifndef UMTX_CHAINS #define UMTX_CHAINS 512 +#endif #define UMTX_SHIFTS (__WORD_BIT - 9) #define GET_SHARE(flags) \ diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c index 82dc6e9ecdb..f97da171468 100644 --- a/sys/kern/sched_4bsd.c +++ b/sys/kern/sched_4bsd.c @@ -308,9 +308,8 @@ maybe_resched(struct thread *td) /* * This function is called when a thread is about to be put on run queue * because it has been made runnable or its priority has been adjusted. It - * determines if the new thread should be immediately preempted to. If so, - * it switches to it and eventually returns true. If not, it returns false - * so that the caller may place the thread on an appropriate run queue. + * determines if the new thread should preempt the current thread. If so, + * it sets td_owepreempt to request a preemption. */ int maybe_preempt(struct thread *td) @@ -327,7 +326,6 @@ maybe_preempt(struct thread *td) * - The current thread has a higher (numerically lower) or * equivalent priority. Note that this prevents curthread from * trying to preempt to itself. - * - It is too early in the boot for context switches (cold is set). * - The current thread has an inhibitor set or is in the process of * exiting. In this case, the current thread is about to switch * out anyways, so there's no point in preempting. If we did, @@ -348,7 +346,7 @@ maybe_preempt(struct thread *td) ("maybe_preempt: trying to run inhibited thread")); pri = td->td_priority; cpri = ctd->td_priority; - if (panicstr != NULL || pri >= cpri || cold /* || dumping */ || + if (panicstr != NULL || pri >= cpri /* || dumping */ || TD_IS_INHIBITED(ctd)) return (0); #ifndef FULL_PREEMPTION @@ -356,29 +354,8 @@ maybe_preempt(struct thread *td) return (0); #endif - if (ctd->td_critnest > 1) { - CTR1(KTR_PROC, "maybe_preempt: in critical section %d", - ctd->td_critnest); - ctd->td_owepreempt = 1; - return (0); - } - /* - * Thread is runnable but not yet put on system run queue. - */ - MPASS(ctd->td_lock == td->td_lock); - MPASS(TD_ON_RUNQ(td)); - TD_SET_RUNNING(td); - CTR3(KTR_PROC, "preempting to thread %p (pid %d, %s)\n", td, - td->td_proc->p_pid, td->td_name); - mi_switch(SW_INVOL | SW_PREEMPT | SWT_PREEMPT, td); - /* - * td's lock pointer may have changed. We have to return with it - * locked. - */ - spinlock_enter(); - thread_unlock(ctd); - thread_lock(td); - spinlock_exit(); + CTR0(KTR_PROC, "maybe_preempt: scheduling preemption"); + ctd->td_owepreempt = 1; return (1); #else return (0); @@ -1127,7 +1104,7 @@ forward_wakeup(int cpunum) if ((!forward_wakeup_enabled) || (forward_wakeup_use_mask == 0 && forward_wakeup_use_loop == 0)) return (0); - if (!smp_started || cold || panicstr) + if (!smp_started || panicstr) return (0); forward_wakeups_requested++; @@ -1332,6 +1309,12 @@ sched_add(struct thread *td, int flags) ts->ts_runq = &runq; } + if ((td->td_flags & TDF_NOLOAD) == 0) + sched_load_add(); + runq_add(ts->ts_runq, td, flags); + if (cpu != NOCPU) + runq_length[cpu]++; + cpuid = PCPU_GET(cpuid); if (single_cpu && cpu != cpuid) { kick_other_cpu(td->td_priority, cpu); @@ -1348,18 +1331,10 @@ sched_add(struct thread *td, int flags) } if (!forwarded) { - if ((flags & SRQ_YIELDING) == 0 && maybe_preempt(td)) - return; - else + if (!maybe_preempt(td)) maybe_resched(td); } } - - if ((td->td_flags & TDF_NOLOAD) == 0) - sched_load_add(); - runq_add(ts->ts_runq, td, flags); - if (cpu != NOCPU) - runq_length[cpu]++; } #else /* SMP */ { @@ -1393,23 +1368,11 @@ sched_add(struct thread *td, int flags) CTR2(KTR_RUNQ, "sched_add: adding td_sched:%p (td:%p) to runq", ts, td); ts->ts_runq = &runq; - /* - * If we are yielding (on the way out anyhow) or the thread - * being saved is US, then don't try be smart about preemption - * or kicking off another CPU as it won't help and may hinder. - * In the YIEDLING case, we are about to run whoever is being - * put in the queue anyhow, and in the OURSELF case, we are - * putting ourself on the run queue which also only happens - * when we are about to yield. - */ - if ((flags & SRQ_YIELDING) == 0) { - if (maybe_preempt(td)) - return; - } if ((td->td_flags & TDF_NOLOAD) == 0) sched_load_add(); runq_add(ts->ts_runq, td, flags); - maybe_resched(td); + if (!maybe_preempt(td)) + maybe_resched(td); } #endif /* SMP */ diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index d80c3d91075..91dc30b9109 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include "opt_bus.h" +#include "opt_ddb.h" #include #include @@ -65,6 +66,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL); SYSCTL_ROOT_NODE(OID_AUTO, dev, CTLFLAG_RW, NULL, NULL); @@ -143,6 +146,9 @@ static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); static void devctl2_init(void); +#define DRIVERNAME(d) ((d)? d->name : "no driver") +#define DEVCLANAME(d) ((d)? d->name : "no devclass") + #ifdef BUS_DEBUG static int bus_debug = 1; @@ -151,8 +157,6 @@ SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0, #define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");} #define DEVICENAME(d) ((d)? device_get_name(d): "no device") -#define DRIVERNAME(d) ((d)? d->name : "no driver") -#define DEVCLANAME(d) ((d)? d->name : "no devclass") /** * Produce the indenting, indent*2 spaces plus a '.' ahead of that to @@ -176,8 +180,6 @@ void print_devclass_list(void); /* Make the compiler ignore the function calls */ #define PDEBUG(a) /* nop */ #define DEVICENAME(d) /* nop */ -#define DRIVERNAME(d) /* nop */ -#define DEVCLANAME(d) /* nop */ #define print_device_short(d,i) /* nop */ #define print_device(d,i) /* nop */ @@ -5586,3 +5588,32 @@ devctl2_init(void) make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0600, "devctl2"); } + +#ifdef DDB +DB_SHOW_COMMAND(device, db_show_device) +{ + device_t dev; + + if (!have_addr) + return; + + dev = (device_t)addr; + + db_printf("name: %s\n", device_get_nameunit(dev)); + db_printf(" driver: %s\n", DRIVERNAME(dev->driver)); + db_printf(" class: %s\n", DEVCLANAME(dev->devclass)); + db_printf(" addr: %p\n", dev); + db_printf(" parent: %p\n", dev->parent); + db_printf(" softc: %p\n", dev->softc); + db_printf(" ivars: %p\n", dev->ivars); +} + +DB_SHOW_ALL_COMMAND(devices, db_show_all_devices) +{ + device_t dev; + + TAILQ_FOREACH(dev, &bus_data_devices, devlink) { + db_show_device((db_expr_t)dev, true, count, modif); + } +} +#endif diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index a04569e2eea..488650190a3 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -2242,10 +2242,10 @@ sys_kmq_setattr(struct thread *td, struct kmq_setattr_args *uap) } error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL, &oattr); - if (error != 0) - return (error); - if (uap->oattr != NULL) + if (error == 0 && uap->oattr != NULL) { + bzero(oattr.__reserved, sizeof(oattr.__reserved)); error = copyout(&oattr, uap->oattr, sizeof(oattr)); + } return (error); } @@ -2759,10 +2759,9 @@ freebsd32_kmq_setattr(struct thread *td, struct freebsd32_kmq_setattr_args *uap) } error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL, &oattr); - if (error != 0) - return (error); - if (uap->oattr != NULL) { + if (error == 0 && uap->oattr != NULL) { mq_attr_to32(&oattr, &oattr32); + bzero(oattr32.__reserved, sizeof(oattr32.__reserved)); error = copyout(&oattr32, uap->oattr, sizeof(oattr32)); } return (error); diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index be922edf0b0..febba784835 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -455,12 +455,9 @@ retry: VM_WAIT; VM_OBJECT_WLOCK(object); goto retry; - } else if (m->valid != VM_PAGE_BITS_ALL) - rv = vm_pager_get_pages(object, &m, 1, - NULL, NULL); - else - /* A cached page was reactivated. */ - rv = VM_PAGER_OK; + } + rv = vm_pager_get_pages(object, &m, 1, NULL, + NULL); vm_page_lock(m); if (rv == VM_PAGER_OK) { vm_page_deactivate(m); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 54f32c99d27..8d3d839d99e 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -4655,7 +4655,24 @@ bdata2bio(struct buf *bp, struct bio *bip) } } -static int buf_pager_relbuf; +/* + * The MIPS pmap code currently doesn't handle aliased pages. + * The VIPT caches may not handle page aliasing themselves, leading + * to data corruption. + * + * As such, this code makes a system extremely unhappy if said + * system doesn't support unaliasing the above situation in hardware. + * Some "recent" systems (eg some mips24k/mips74k cores) don't enable + * this feature at build time, so it has to be handled in software. + * + * Once the MIPS pmap/cache code grows to support this function on + * earlier chips, it should be flipped back off. + */ +#ifdef __mips__ +static int buf_pager_relbuf = 1; +#else +static int buf_pager_relbuf = 0; +#endif SYSCTL_INT(_vfs, OID_AUTO, buf_pager_relbuf, CTLFLAG_RWTUN, &buf_pager_relbuf, 0, "Make buffer pager release buffers after reading"); diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index bcfa5001219..bdde50222e6 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -783,7 +783,7 @@ cache_negative_shrink_select(int start, struct namecache **ncpp, static void cache_negative_zap_one(void) { - struct namecache *ncp, *ncp2, *ncpc; + struct namecache *ncp, *ncp2; struct neglist *neglist; struct mtx *dvlp; struct rwlock *blp; @@ -791,7 +791,6 @@ cache_negative_zap_one(void) if (!mtx_trylock(&ncneg_shrink_lock)) return; - ncpc = NULL; mtx_lock(&ncneg_hot.nl_lock); ncp = TAILQ_FIRST(&ncneg_hot.nl_list); if (ncp != NULL) { @@ -868,6 +867,13 @@ cache_zap_locked(struct namecache *ncp, bool neg_locked) nc_get_name(ncp), ncp->nc_neghits); } LIST_REMOVE(ncp, nc_hash); + if (!(ncp->nc_flag & NCF_NEGATIVE)) { + TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst); + if (ncp == ncp->nc_vp->v_cache_dd) + ncp->nc_vp->v_cache_dd = NULL; + } else { + cache_negative_remove(ncp, neg_locked); + } if (ncp->nc_flag & NCF_ISDOTDOT) { if (ncp == ncp->nc_dvp->v_cache_dd) ncp->nc_dvp->v_cache_dd = NULL; @@ -878,13 +884,6 @@ cache_zap_locked(struct namecache *ncp, bool neg_locked) atomic_subtract_rel_long(&numcachehv, 1); } } - if (!(ncp->nc_flag & NCF_NEGATIVE)) { - TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst); - if (ncp == ncp->nc_vp->v_cache_dd) - ncp->nc_vp->v_cache_dd = NULL; - } else { - cache_negative_remove(ncp, neg_locked); - } atomic_subtract_rel_long(&numcache, 1); } diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 988c687bda7..77a353b3cad 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -61,8 +61,10 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_NETADDR, "export_host", "Export host address structure"); +#if defined(INET) || defined(INET6) static struct radix_node_head *vfs_create_addrlist_af( struct radix_node_head **prnh, int off); +#endif static void vfs_free_addrlist(struct netexport *nep); static int vfs_free_netcred(struct radix_node *rn, void *w); static void vfs_free_addrlist_af(struct radix_node_head **prnh); @@ -239,6 +241,7 @@ vfs_free_netcred(struct radix_node *rn, void *w) return (0); } +#if defined(INET) || defined(INET6) static struct radix_node_head * vfs_create_addrlist_af(struct radix_node_head **prnh, int off) { @@ -248,6 +251,7 @@ vfs_create_addrlist_af(struct radix_node_head **prnh, int off) RADIX_NODE_HEAD_LOCK_INIT(*prnh); return (*prnh); } +#endif static void vfs_free_addrlist_af(struct radix_node_head **prnh) diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index da8b824f6c3..99bfb101f13 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -940,6 +940,11 @@ vfs_domount_update( VOP_UNLOCK(vp, 0); MNT_ILOCK(mp); + if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0) { + MNT_IUNLOCK(mp); + error = EBUSY; + goto end; + } mp->mnt_flag &= ~MNT_UPDATEMASK; mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY); @@ -1235,6 +1240,24 @@ vfs_check_usecounts(struct mount *mp) return (0); } +static void +dounmount_cleanup(struct mount *mp, struct vnode *coveredvp, int mntkflags) +{ + + mtx_assert(MNT_MTX(mp), MA_OWNED); + mp->mnt_kern_flag &= ~mntkflags; + if ((mp->mnt_kern_flag & MNTK_MWAIT) != 0) { + mp->mnt_kern_flag &= ~MNTK_MWAIT; + wakeup(mp); + } + MNT_IUNLOCK(mp); + if (coveredvp != NULL) { + VOP_UNLOCK(coveredvp, 0); + vdrop(coveredvp); + } + vn_finished_write(mp); +} + /* * Do the actual filesystem unmount. */ @@ -1281,13 +1304,9 @@ dounmount(struct mount *mp, int flags, struct thread *td) vn_start_write(NULL, &mp, V_WAIT | V_MNTREF); MNT_ILOCK(mp); if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 || + (mp->mnt_flag & MNT_UPDATE) != 0 || !TAILQ_EMPTY(&mp->mnt_uppers)) { - MNT_IUNLOCK(mp); - if (coveredvp != NULL) { - VOP_UNLOCK(coveredvp, 0); - vdrop(coveredvp); - } - vn_finished_write(mp); + dounmount_cleanup(mp, coveredvp, 0); return (EBUSY); } mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ; @@ -1296,17 +1315,8 @@ dounmount(struct mount *mp, int flags, struct thread *td) error = vfs_check_usecounts(mp); MNT_ILOCK(mp); if (error != 0) { - mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ); - if (mp->mnt_kern_flag & MNTK_MWAIT) { - mp->mnt_kern_flag &= ~MNTK_MWAIT; - wakeup(mp); - } - MNT_IUNLOCK(mp); - if (coveredvp != NULL) { - VOP_UNLOCK(coveredvp, 0); - vdrop(coveredvp); - } - vn_finished_write(mp); + dounmount_cleanup(mp, coveredvp, MNTK_UNMOUNT | + MNTK_NOINSMNTQ); return (error); } } diff --git a/sys/mips/atheros/ar531x/files.ar5315 b/sys/mips/atheros/ar531x/files.ar5315 index 7bb2dfa7a7b..f608aa69de1 100644 --- a/sys/mips/atheros/ar531x/files.ar5315 +++ b/sys/mips/atheros/ar531x/files.ar5315 @@ -14,17 +14,18 @@ mips/atheros/ar531x/uart_cpu_ar5315.c optional uart_ar5315 mips/atheros/ar531x/ar5312_chip.c standard mips/atheros/ar71xx_bus_space_reversed.c standard -#mips/mips/intr_machdep.c standard mips/mips/tick.c standard dev/etherswitch/e6000sw/e6060sw.c optional etherswitch -dev/etherswitch/realtek/rtl830x.c optional etherswitch # Hack to reuse ARM intrng code -kern/subr_intr.c standard -kern/msi_if.m standard -kern/pic_if.m standard +kern/subr_intr.c optional intrng +kern/msi_if.m optional intrng +kern/pic_if.m optional intrng # Intrng compatible MIPS32 interrupt controller -mips/mips/mips_pic.c standard +mips/mips/mips_pic.c optional intrng + +# Non Intrng +mips/mips/intr_machdep.c optional !intrng diff --git a/sys/mips/atheros/ar531x/if_are.c b/sys/mips/atheros/ar531x/if_are.c index d7bf6cbea84..294961825f7 100644 --- a/sys/mips/atheros/ar531x/if_are.c +++ b/sys/mips/atheros/ar531x/if_are.c @@ -35,7 +35,7 @@ __FBSDID("$FreeBSD$"); /* - * AR231x Ethernet interface driver + * AR531x Ethernet interface driver * copy from mips/idt/if_kr.c and netbsd code */ #include @@ -90,8 +90,6 @@ MODULE_DEPEND(are, miibus, 1, 1, 1); #include #include -//#define ARE_DEBUG - #ifdef ARE_DEBUG void dump_txdesc(struct are_softc *, int); void dump_status_reg(struct are_softc *); @@ -226,7 +224,7 @@ are_attach(device_t dev) unit = device_get_unit(dev); sc->are_dev = dev; - // hardcode macaddress + /* hardcode macaddress */ sc->are_eaddr[0] = 0x00; sc->are_eaddr[1] = 0x0C; sc->are_eaddr[2] = 0x42; @@ -234,7 +232,7 @@ are_attach(device_t dev) sc->are_eaddr[4] = 0x5E; sc->are_eaddr[5] = 0x6B; - // try to get from hints + /* try to get from hints */ if (!resource_string_value(device_get_name(dev), device_get_unit(dev), "macaddr", (const char **)&local_macstr)) { uint32_t tmpmac[ETHER_ADDR_LEN]; @@ -302,12 +300,16 @@ are_attach(device_t dev) ifp->if_ioctl = are_ioctl; ifp->if_start = are_start; ifp->if_init = are_init; + sc->are_if_flags = ifp->if_flags; /* XXX: add real size */ IFQ_SET_MAXLEN(&ifp->if_snd, 9); ifp->if_snd.ifq_maxlen = 9; IFQ_SET_READY(&ifp->if_snd); + /* Tell the upper layer(s) we support long frames. */ + ifp->if_capabilities |= IFCAP_VLAN_MTU; + ifp->if_capenable = ifp->if_capabilities; if (are_dma_alloc(sc) != 0) { @@ -315,14 +317,6 @@ are_attach(device_t dev) goto fail; } - /* TODO: calculate prescale */ -/* - CSR_WRITE_4(sc, ARE_ETHMCP, (165000000 / (1250000 + 1)) & ~1); - - CSR_WRITE_4(sc, ARE_MIIMCFG, ARE_MIIMCFG_R); - DELAY(1000); - CSR_WRITE_4(sc, ARE_MIIMCFG, 0); -*/ CSR_WRITE_4(sc, CSR_BUSMODE, BUSMODE_SWR); DELAY(1000); @@ -350,11 +344,11 @@ are_attach(device_t dev) #ifdef INTRNG char *name; - if(ar531x_soc >= AR531X_SOC_AR5315) { + if (ar531x_soc >= AR531X_SOC_AR5315) { enetirq = AR5315_CPU_IRQ_ENET; name = "enet"; } else { - if(device_get_unit(dev) == 0) { + if (device_get_unit(dev) == 0) { enetirq = AR5312_IRQ_ENET0; name = "enet0"; } else { @@ -465,7 +459,6 @@ are_miibus_readreg(device_t dev, int phy, int reg) addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT); CSR_WRITE_4(sc, CSR_MIIADDR, addr); -// AE_BARRIER(sc); for (i = 0; i < 100000000; i++) { if ((CSR_READ_4(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0) break; @@ -488,7 +481,6 @@ are_miibus_writereg(device_t dev, int phy, int reg, int data) addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT) | MIIADDR_WRITE; CSR_WRITE_4(sc, CSR_MIIADDR, addr); -// AE_BARRIER(sc); for (i = 0; i < 100000000; i++) { if ((CSR_READ_4(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0) @@ -610,7 +602,6 @@ are_init_locked(struct are_softc *sc) */ CSR_WRITE_4(sc, CSR_BUSMODE, /* XXX: not sure if this is a good thing or not... */ - //BUSMODE_ALIGN_16B | BUSMODE_BAR | BUSMODE_BLE | BUSMODE_PBL_4LW); /* @@ -648,15 +639,16 @@ are_init_locked(struct are_softc *sc) /* * Start the mac. */ - CSR_WRITE_4(sc, CSR_MACCTL, CSR_READ_4(sc, CSR_MACCTL) | - (MACCTL_RE | MACCTL_TE)); + CSR_WRITE_4(sc, CSR_FLOWC, FLOWC_FCE); + CSR_WRITE_4(sc, CSR_MACCTL, MACCTL_RE | MACCTL_TE | + MACCTL_PM | MACCTL_FDX | MACCTL_HBD | MACCTL_RA); /* * Write out the opmode. */ - CSR_WRITE_4(sc, CSR_OPMODE, OPMODE_SR | OPMODE_ST | -// ae_txthresh[sc->sc_txthresh].txth_opmode); + CSR_WRITE_4(sc, CSR_OPMODE, OPMODE_SR | OPMODE_ST | OPMODE_SF | OPMODE_TR_64); + /* * Start the receive process. */ @@ -741,7 +733,6 @@ are_encap(struct are_softc *sc, struct mbuf **m_head) if (i == 0) desc->are_devcs |= ADCTL_Tx_FS; desc->are_addr = txsegs[i].ds_addr; -// desc->are_link = 0; /* link with previous descriptor */ if (prev_desc) prev_desc->are_link = ARE_TX_RING_ADDR(sc, prod); @@ -850,6 +841,36 @@ are_stop(struct are_softc *sc) } +static int +are_set_filter(struct are_softc *sc) +{ + struct ifnet *ifp; + int mchash[2]; + int macctl; + + ifp = sc->are_ifp; + + macctl = CSR_READ_4(sc, CSR_MACCTL); + macctl &= ~(MACCTL_PR | MACCTL_PM); + macctl |= MACCTL_HBD; + + if (ifp->if_flags & IFF_PROMISC) + macctl |= MACCTL_PR; + + /* Todo: hash table set. + * But I don't know how to use multicast hash table at this soc. + */ + + /* this is allmulti */ + mchash[0] = mchash[1] = 0xffffffff; + macctl |= MACCTL_PM; + + CSR_WRITE_4(sc, CSR_HTLO, mchash[0]); + CSR_WRITE_4(sc, CSR_HTHI, mchash[1]); + CSR_WRITE_4(sc, CSR_MACCTL, macctl); + + return 0; +} static int are_ioctl(struct ifnet *ifp, u_long command, caddr_t data) @@ -863,7 +884,6 @@ are_ioctl(struct ifnet *ifp, u_long command, caddr_t data) switch (command) { case SIOCSIFFLAGS: -#if 0 ARE_LOCK(sc); if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING) { @@ -880,16 +900,13 @@ are_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } sc->are_if_flags = ifp->if_flags; ARE_UNLOCK(sc); -#endif error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: -#if 0 ARE_LOCK(sc); are_set_filter(sc); ARE_UNLOCK(sc); -#endif error = 0; break; case SIOCGIFMEDIA: @@ -903,28 +920,6 @@ are_ioctl(struct ifnet *ifp, u_long command, caddr_t data) break; case SIOCSIFCAP: error = 0; -#if 0 - mask = ifr->ifr_reqcap ^ ifp->if_capenable; - if ((mask & IFCAP_HWCSUM) != 0) { - ifp->if_capenable ^= IFCAP_HWCSUM; - if ((IFCAP_HWCSUM & ifp->if_capenable) && - (IFCAP_HWCSUM & ifp->if_capabilities)) - ifp->if_hwassist = ARE_CSUM_FEATURES; - else - ifp->if_hwassist = 0; - } - if ((mask & IFCAP_VLAN_HWTAGGING) != 0) { - ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; - if (IFCAP_VLAN_HWTAGGING & ifp->if_capenable && - IFCAP_VLAN_HWTAGGING & ifp->if_capabilities && - ifp->if_drv_flags & IFF_DRV_RUNNING) { - ARE_LOCK(sc); - are_vlan_setup(sc); - ARE_UNLOCK(sc); - } - } - VLAN_CAPABILITIES(ifp); -#endif break; default: error = ether_ioctl(ifp, command, data); @@ -1343,7 +1338,7 @@ are_newbuf(struct are_softc *sc, int idx) return (ENOBUFS); m->m_len = m->m_pkthdr.len = MCLBYTES; - // tcp header boundary margin + /* tcp header boundary margin */ m_adj(m, 4); if (bus_dmamap_load_mbuf_sg(sc->are_cdata.are_rx_tag, @@ -1355,9 +1350,11 @@ are_newbuf(struct are_softc *sc, int idx) rxd = &sc->are_cdata.are_rxdesc[idx]; if (rxd->rx_m != NULL) { -// This code make bug. Make scranble on buffer data. -// bus_dmamap_sync(sc->are_cdata.are_rx_tag, rxd->rx_dmamap, -// BUS_DMASYNC_POSTREAD); + /* + * THis is if_kr.c original code but make bug. Make scranble on buffer data. + * bus_dmamap_sync(sc->are_cdata.are_rx_tag, rxd->rx_dmamap, + * BUS_DMASYNC_POSTREAD); + */ bus_dmamap_unload(sc->are_cdata.are_rx_tag, rxd->rx_dmamap); } map = rxd->rx_dmamap; @@ -1551,7 +1548,6 @@ are_intr(void *arg) struct are_softc *sc = arg; uint32_t status; struct ifnet *ifp = sc->are_ifp; -//kdb_break(); ARE_LOCK(sc); diff --git a/sys/mips/atheros/ar531x/if_arereg.h b/sys/mips/atheros/ar531x/if_arereg.h index 19aad0ce394..f59df630d9e 100644 --- a/sys/mips/atheros/ar531x/if_arereg.h +++ b/sys/mips/atheros/ar531x/if_arereg.h @@ -37,17 +37,17 @@ struct are_desc { uint32_t are_link; }; -#define ARE_DMASIZE(len) ((len) & ((1 << 11)-1)) -#define ARE_PKTSIZE(len) ((len & 0xffff0000) >> 16) +#define ARE_DMASIZE(len) ((len) & ((1 << 11)-1)) +#define ARE_PKTSIZE(len) ((len & 0xffff0000) >> 16) -#define ARE_RX_RING_CNT 128 -#define ARE_TX_RING_CNT 128 -#define ARE_TX_RING_SIZE sizeof(struct are_desc) * ARE_TX_RING_CNT -#define ARE_RX_RING_SIZE sizeof(struct are_desc) * ARE_RX_RING_CNT -#define ARE_RING_ALIGN sizeof(struct are_desc) -#define ARE_RX_ALIGN sizeof(uint32_t) -#define ARE_MAXFRAGS 8 -#define ARE_TX_INTR_THRESH 8 +#define ARE_RX_RING_CNT 128 +#define ARE_TX_RING_CNT 128 +#define ARE_TX_RING_SIZE sizeof(struct are_desc) * ARE_TX_RING_CNT +#define ARE_RX_RING_SIZE sizeof(struct are_desc) * ARE_RX_RING_CNT +#define ARE_RING_ALIGN sizeof(struct are_desc) +#define ARE_RX_ALIGN sizeof(uint32_t) +#define ARE_MAXFRAGS 8 +#define ARE_TX_INTR_THRESH 8 #define ARE_TX_RING_ADDR(sc, i) \ ((sc)->are_rdata.are_tx_ring_paddr + sizeof(struct are_desc) * (i)) @@ -123,6 +123,7 @@ struct are_softc { struct are_ring_data are_rdata; int are_link_status; int are_detach; + int are_if_flags; /* last if flags */ }; #define ARE_LOCK(_sc) mtx_lock(&(_sc)->are_mtx) @@ -132,11 +133,11 @@ struct are_softc { /* * register space access macros */ -#define CSR_WRITE_4(sc, reg, val) \ - bus_space_write_4(sc->are_btag, sc->are_bhandle, reg, val) +#define CSR_WRITE_4(sc, reg, val) \ + bus_space_write_4(sc->are_btag, sc->are_bhandle, reg, val) -#define CSR_READ_4(sc, reg) \ - bus_space_read_4(sc->are_btag, sc->are_bhandle, reg) +#define CSR_READ_4(sc, reg) \ + bus_space_read_4(sc->are_btag, sc->are_bhandle, reg) /* $NetBSD: aereg.h,v 1.2 2008/04/28 20:23:28 martin Exp $ */ diff --git a/sys/mips/include/cpufunc.h b/sys/mips/include/cpufunc.h index 427aba74cd3..5ebaf4cc172 100644 --- a/sys/mips/include/cpufunc.h +++ b/sys/mips/include/cpufunc.h @@ -249,7 +249,8 @@ MIPS_RW32_COP0_SEL(config5, MIPS_COP_0_CONFIG, 5); #if defined(CPU_NLM) || defined(BERI_LARGE_TLB) MIPS_RW32_COP0_SEL(config6, MIPS_COP_0_CONFIG, 6); #endif -#if defined(CPU_NLM) || defined(CPU_MIPS1004K) +#if defined(CPU_NLM) || defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || \ + defined(CPU_MIPS24K) MIPS_RW32_COP0_SEL(config7, MIPS_COP_0_CONFIG, 7); #endif MIPS_RW32_COP0(count, MIPS_COP_0_COUNT); @@ -278,6 +279,13 @@ MIPS_RW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1); MIPS_RW32_COP0(prid, MIPS_COP_0_PRID); /* XXX 64-bit? */ MIPS_RW32_COP0_SEL(ebase, MIPS_COP_0_PRID, 1); +#ifdef CPU_XBURST +MIPS_RW32_COP0_SEL(xburst_mbox0, MIPS_COP_0_XBURST_MBOX, 0); +MIPS_RW32_COP0_SEL(xburst_mbox1, MIPS_COP_0_XBURST_MBOX, 1); +MIPS_RW32_COP0_SEL(xburst_core_ctl, MIPS_COP_0_XBURST_C12, 2); +MIPS_RW32_COP0_SEL(xburst_core_sts, MIPS_COP_0_XBURST_C12, 3); +MIPS_RW32_COP0_SEL(xburst_reim, MIPS_COP_0_XBURST_C12, 4); +#endif MIPS_RW32_COP0(watchlo, MIPS_COP_0_WATCH_LO); MIPS_RW32_COP0_SEL(watchlo1, MIPS_COP_0_WATCH_LO, 1); MIPS_RW32_COP0_SEL(watchlo2, MIPS_COP_0_WATCH_LO, 2); diff --git a/sys/mips/include/cpuregs.h b/sys/mips/include/cpuregs.h index 4ce7e1b4fb2..26bee195e64 100644 --- a/sys/mips/include/cpuregs.h +++ b/sys/mips/include/cpuregs.h @@ -522,12 +522,18 @@ #define MIPS_COP_0_COUNT _(9) #define MIPS_COP_0_COMPARE _(11) - +#ifdef CPU_XBURST +#define MIPS_COP_0_XBURST_C12 _(12) +#endif #define MIPS_COP_0_CONFIG _(16) #define MIPS_COP_0_LLADDR _(17) #define MIPS_COP_0_WATCH_LO _(18) #define MIPS_COP_0_WATCH_HI _(19) #define MIPS_COP_0_TLB_XCONTEXT _(20) +#ifdef CPU_XBURST +#define MIPS_COP_0_XBURST_MBOX _(20) +#endif + #define MIPS_COP_0_ECC _(26) #define MIPS_COP_0_CACHE_ERR _(27) #define MIPS_COP_0_TAG_LO _(28) diff --git a/sys/mips/include/locore.h b/sys/mips/include/locore.h index 1e4092e2318..1f101a5175f 100644 --- a/sys/mips/include/locore.h +++ b/sys/mips/include/locore.h @@ -59,6 +59,9 @@ #define MIPS_PRID_CID_LEXRA 0x0b /* Lexra */ #define MIPS_PRID_CID_RMI 0x0c /* RMI */ #define MIPS_PRID_CID_CAVIUM 0x0d /* Cavium */ +#define MIPS_PRID_CID_INGENIC 0xe1 /* Ingenic */ +#define MIPS_PRID_CID_INGENIC2 0xd1 /* Ingenic */ + #define MIPS_PRID_COPTS(x) (((x) >> 24) & 0x00ff) /* Company Options */ #endif /* _MIPS_LOCORE_H */ diff --git a/sys/mips/include/param.h b/sys/mips/include/param.h index 7c5e667858f..37e1fd344f7 100644 --- a/sys/mips/include/param.h +++ b/sys/mips/include/param.h @@ -53,33 +53,36 @@ #define __PCI_REROUTE_INTERRUPT +#if _BYTE_ORDER == _BIG_ENDIAN +# define _EL_SUFFIX "" +#else +# define _EL_SUFFIX "el" +#endif + +#ifdef __mips_n64 +# define _N64_SUFFIX "64" +#elif defined(__mips_n32) +# define _N64_SUFFIX "n32" +#else +# define _N64_SUFFIX "" +#endif + +#ifdef __mips_hard_float +# define _HF_SUFFIX "hf" +#else +# define _HF_SUFFIX "" +#endif + #ifndef MACHINE -#define MACHINE "mips" +# define MACHINE "mips" #endif #ifndef MACHINE_ARCH -#if _BYTE_ORDER == _BIG_ENDIAN +# define MACHINE_ARCH "mips" _N64_SUFFIX _EL_SUFFIX _HF_SUFFIX +#endif #ifdef __mips_n64 -#define MACHINE_ARCH "mips64" -#ifndef MACHINE_ARCH32 -#define MACHINE_ARCH32 "mips" -#endif -#elif defined(__mips_n32) -#define MACHINE_ARCH "mipsn32" -#else -#define MACHINE_ARCH "mips" -#endif -#else -#ifdef __mips_n64 -#define MACHINE_ARCH "mips64el" -#ifndef MACHINE_ARCH32 -#define MACHINE_ARCH32 "mipsel" -#endif -#elif defined(__mips_n32) -#define MACHINE_ARCH "mipsn32el" -#else -#define MACHINE_ARCH "mipsel" -#endif -#endif +# ifndef MACHINE_ARCH32 +# define MACHINE_ARCH32 "mips" _EL_SUFFIX _HF_SUFFIX +# endif #endif /* diff --git a/sys/mips/mediatek/mtk_soc.c b/sys/mips/mediatek/mtk_soc.c index ff40abfd1eb..62e01c80563 100644 --- a/sys/mips/mediatek/mtk_soc.c +++ b/sys/mips/mediatek/mtk_soc.c @@ -248,7 +248,7 @@ mtk_soc_try_early_detect(void) return; for (i = 0; compat_data[i].ocd_str != NULL; i++) { - if (fdt_is_compatible(node, compat_data[i].ocd_str)) { + if (ofw_bus_node_is_compatible(node, compat_data[i].ocd_str)) { mtk_soc_socid = compat_data[i].ocd_data; break; } diff --git a/sys/mips/mips/cpu.c b/sys/mips/mips/cpu.c index e8f48dcb8f8..fa68fd32e74 100644 --- a/sys/mips/mips/cpu.c +++ b/sys/mips/mips/cpu.c @@ -337,6 +337,9 @@ static void cpu_identify(void) { uint32_t cfg0, cfg1, cfg2, cfg3; +#if defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || defined (CPU_MIPS24K) + uint32_t cfg7; +#endif printf("cpu%d: ", 0); /* XXX per-cpu */ switch (cpuinfo.cpu_vendor) { case MIPS_PRID_CID_MTI: @@ -370,6 +373,10 @@ cpu_identify(void) case MIPS_PRID_CID_CAVIUM: printf("Cavium"); break; + case MIPS_PRID_CID_INGENIC: + case MIPS_PRID_CID_INGENIC2: + printf("Ingenic XBurst"); + break; case MIPS_PRID_CID_PREHISTORIC: default: printf("Unknown cid %#x", cpuinfo.cpu_vendor); @@ -478,7 +485,12 @@ cpu_identify(void) /* Print Config3 if it contains any useful info */ if (cfg3 & ~(0x80000000)) - printf(" Config3=0x%b\n", cfg3, "\20\14ULRI\2SmartMIPS\1TraceLogic"); + printf(" Config3=0x%b\n", cfg3, "\20\16ULRI\2SmartMIPS\1TraceLogic"); + +#if defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || defined (CPU_MIPS24K) + cfg7 = mips_rd_config7(); + printf(" Config7=0x%b\n", cfg7, "\20\40WII\21AR"); +#endif } static struct rman cpu_hardirq_rman; diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c index 2bc7787dc05..638c9cbc50f 100644 --- a/sys/mips/mips/pmap.c +++ b/sys/mips/mips/pmap.c @@ -74,11 +74,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef SMP #include -#else -#include -#endif #include #include @@ -3266,9 +3262,19 @@ pmap_activate(struct thread *td) critical_exit(); } +static void +pmap_sync_icache_one(void *arg __unused) +{ + + mips_icache_sync_all(); + mips_dcache_wbinv_all(); +} + void pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz) { + + smp_rendezvous(NULL, pmap_sync_icache_one, NULL, NULL); } /* diff --git a/sys/modules/Makefile b/sys/modules/Makefile index b5ac84dbabb..602f3da52b3 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -57,6 +57,7 @@ SUBDIR= \ ${_bios} \ ${_bktr} \ ${_bm} \ + bnxt \ bridgestp \ bwi \ bwn \ diff --git a/sys/modules/bnxt/Makefile b/sys/modules/bnxt/Makefile new file mode 100644 index 00000000000..1d478d16671 --- /dev/null +++ b/sys/modules/bnxt/Makefile @@ -0,0 +1,14 @@ +#$FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/bnxt + +KMOD = if_bnxt +SRCS = device_if.h bus_if.h pci_if.h pci_iov_if.h ifdi_if.h +SRCS += opt_inet.h opt_inet6.h opt_rss.h +SRCS += bnxt_txrx.c if_bnxt.c +SRCS += bnxt_hwrm.c bnxt_hwrm.h +SRCS += bnxt_sysctl.c bnxt_sysctl.h + +CFLAGS+= -DIFLIB + +.include diff --git a/sys/modules/dtrace/dtrace/Makefile b/sys/modules/dtrace/dtrace/Makefile index 543be8c2019..0889646f88c 100644 --- a/sys/modules/dtrace/dtrace/Makefile +++ b/sys/modules/dtrace/dtrace/Makefile @@ -60,7 +60,11 @@ assym.o: assym.s .if ${MACHINE_CPUARCH} == "riscv" assym.o: assym.s +.if ${TARGET_ARCH:Mriscv*sf} ${AS} -mfloat-abi=soft -o assym.o assym.s +.else + ${AS} -mfloat-abi=double -o assym.o assym.s +.endif .endif .include diff --git a/sys/modules/hyperv/pcib/Makefile b/sys/modules/hyperv/pcib/Makefile new file mode 100644 index 00000000000..1b63a138dc1 --- /dev/null +++ b/sys/modules/hyperv/pcib/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/hyperv/pcib \ + ${.CURDIR}/../../../dev/hyperv/vmbus + +KMOD= vmbus_pcib +SRCS= vmbus_pcib.c +SRCS+= bus_if.h device_if.h pci_if.h pcib_if.h vmbus_if.h + +CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/pcib + +.include diff --git a/sys/modules/hyperv/utilities/Makefile b/sys/modules/hyperv/utilities/Makefile index 290bd2737ad..28125fd2867 100644 --- a/sys/modules/hyperv/utilities/Makefile +++ b/sys/modules/hyperv/utilities/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../../dev/hyperv/utilities KMOD= hv_utils -SRCS= hv_util.c hv_kvp.c hv_timesync.c hv_shutdown.c hv_heartbeat.c +SRCS= hv_util.c hv_kvp.c hv_snapshot.c hv_timesync.c hv_shutdown.c hv_heartbeat.c hv_snapshot.c SRCS+= bus_if.h device_if.h vmbus_if.h CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \ diff --git a/sys/modules/hyperv/vmbus/Makefile b/sys/modules/hyperv/vmbus/Makefile index 105b4f5b751..d6052e51d75 100644 --- a/sys/modules/hyperv/vmbus/Makefile +++ b/sys/modules/hyperv/vmbus/Makefile @@ -13,7 +13,7 @@ SRCS= hyperv.c \ vmbus_et.c \ vmbus_if.c \ vmbus_xact.c -SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h vmbus_if.h +SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h pci_if.h pcib_if.h vmbus_if.h # XXX: for assym.s SRCS+= opt_kstack_pages.h opt_nfs.h opt_hwpmc_hooks.h opt_compat.h diff --git a/sys/modules/kbdmux/Makefile b/sys/modules/kbdmux/Makefile index 363343a87db..03feb8fb8b5 100644 --- a/sys/modules/kbdmux/Makefile +++ b/sys/modules/kbdmux/Makefile @@ -4,7 +4,8 @@ .PATH: ${.CURDIR}/../../dev/kbdmux KMOD= kbdmux -SRCS= kbdmux.c opt_compat.h opt_kbd.h opt_kbdmux.h bus_if.h device_if.h +SRCS= kbdmux.c opt_compat.h opt_evdev.h opt_kbd.h opt_kbdmux.h bus_if.h \ + device_if.h .if !defined(KERNBUILDDIR) opt_compat.h: diff --git a/sys/modules/rpi_ft5406/Makefile b/sys/modules/rpi_ft5406/Makefile index 2360ceda44a..3a1bbf5762a 100644 --- a/sys/modules/rpi_ft5406/Makefile +++ b/sys/modules/rpi_ft5406/Makefile @@ -5,6 +5,6 @@ KMOD= rpi_ft5406 SRCS= bcm2835_ft5406.c -SRCS+= bus_if.h device_if.h ofw_bus_if.h +SRCS+= bus_if.h device_if.h mbox_if.h ofw_bus_if.h .include diff --git a/sys/net/iflib.c b/sys/net/iflib.c index 42f0d4ce93e..25f5c741a88 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -93,7 +93,6 @@ __FBSDID("$FreeBSD$"); #include #endif - /* * enable accounting of every mbuf as it comes in to and goes out of iflib's software descriptor references */ @@ -500,7 +499,7 @@ static SYSCTL_NODE(_net, OID_AUTO, iflib, CTLFLAG_RD, 0, static int iflib_min_tx_latency = 0; SYSCTL_INT(_net_iflib, OID_AUTO, min_tx_latency, CTLFLAG_RW, - &iflib_min_tx_latency, 0, "minimize transmit latency at the possibel expense of throughput"); + &iflib_min_tx_latency, 0, "minimize transmit latency at the possible expense of throughput"); #if IFLIB_DEBUG_COUNTERS @@ -595,10 +594,23 @@ SYSCTL_INT(_net_iflib, OID_AUTO, verbose_debug, CTLFLAG_RW, &iflib_verbose_debug, 0, "enable verbose debugging"); #define DBG_COUNTER_INC(name) atomic_add_int(&(iflib_ ## name), 1) +static void +iflib_debug_reset(void) +{ + iflib_tx_seen = iflib_tx_sent = iflib_tx_encap = iflib_rx_allocs = + iflib_fl_refills = iflib_fl_refills_large = iflib_tx_frees = + iflib_txq_drain_flushing = iflib_txq_drain_oactive = + iflib_txq_drain_notready = iflib_txq_drain_encapfail = + iflib_encap_load_mbuf_fail = iflib_encap_txq_avail_fail = + iflib_encap_txd_encap_fail = iflib_task_fn_rxs = iflib_rx_intr_enables = + iflib_fast_intrs = iflib_intr_link = iflib_intr_msix = iflib_rx_unavail = + iflib_rx_ctx_inactive = iflib_rx_zero_len = iflib_rx_if_input = + iflib_rx_mbuf_null = iflib_rxd_flush = 0; +} #else #define DBG_COUNTER_INC(name) - +static void iflib_debug_reset(void) {} #endif @@ -619,6 +631,7 @@ static int iflib_register(if_ctx_t); static void iflib_init_locked(if_ctx_t ctx); static void iflib_add_device_sysctl_pre(if_ctx_t ctx); static void iflib_add_device_sysctl_post(if_ctx_t ctx); +static void iflib_ifmp_purge(iflib_txq_t txq); #ifdef DEV_NETMAP @@ -1266,11 +1279,6 @@ iflib_txsd_alloc(iflib_txq_t txq) sctx->isc_tx_maxsize, nsegments, sctx->isc_tx_maxsegsize); goto fail; } -#ifdef IFLIB_DIAGNOSTICS - device_printf(dev,"maxsize: %zd nsegments: %d maxsegsize: %zd\n", - sctx->isc_tx_maxsize, nsegments, sctx->isc_tx_maxsegsize); - -#endif if ((err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR, /* lowaddr */ @@ -1287,11 +1295,6 @@ iflib_txsd_alloc(iflib_txq_t txq) goto fail; } -#ifdef IFLIB_DIAGNOSTICS - device_printf(dev,"TSO maxsize: %d ntsosegments: %d maxsegsize: %d\n", - scctx->isc_tx_tso_size_max, ntsosegments, - scctx->isc_tx_tso_segsize_max); -#endif if (!(txq->ift_sds.ifsd_flags = (uint8_t *) malloc(sizeof(uint8_t) * scctx->isc_ntxd[txq->ift_br_offset], M_IFLIB, M_NOWAIT | M_ZERO))) { @@ -1921,20 +1924,23 @@ iflib_stop(if_ctx_t ctx) if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); IFDI_INTR_DISABLE(ctx); - msleep(ctx, &ctx->ifc_mtx, PUSER, "iflib_init", hz); + DELAY(100000); + IFDI_STOP(ctx); + DELAY(100000); + iflib_debug_reset(); /* Wait for current tx queue users to exit to disarm watchdog timer. */ for (i = 0; i < scctx->isc_ntxqsets; i++, txq++) { /* make sure all transmitters have completed before proceeding XXX */ /* clean any enqueued buffers */ - iflib_txq_check_drain(txq, 0); + iflib_ifmp_purge(txq); /* Free any existing tx buffers. */ for (j = 0; j < txq->ift_size; j++) { iflib_txsd_free(ctx, txq, j); } txq->ift_processed = txq->ift_cleaned = txq->ift_cidx_processed = 0; - txq->ift_in_use = txq->ift_cidx = txq->ift_pidx = txq->ift_no_desc_avail = 0; + txq->ift_in_use = txq->ift_gen = txq->ift_cidx = txq->ift_pidx = txq->ift_no_desc_avail = 0; txq->ift_closed = txq->ift_mbuf_defrag = txq->ift_mbuf_defrag_failed = 0; txq->ift_no_tx_dma_setup = txq->ift_txd_encap_efbig = txq->ift_map_failed = 0; txq->ift_pullups = 0; @@ -1951,7 +1957,6 @@ iflib_stop(if_ctx_t ctx) for (j = 0, fl = rxq->ifr_fl; j < rxq->ifr_nfl; j++, fl++) iflib_fl_bufs_free(fl); } - IFDI_STOP(ctx); } static iflib_rxsd_t @@ -2890,22 +2895,27 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) } consumed = mcast_sent = bytes_sent = pkt_sent = 0; count = MIN(avail, TX_BATCH_SIZE); +#ifdef INVARIANTS + if (iflib_verbose_debug) + printf("%s avail=%d ifc_flags=%x txq_avail=%d ", __FUNCTION__, + avail, ctx->ifc_flags, TXQ_AVAIL(txq)); +#endif for (desc_used = i = 0; i < count && TXQ_AVAIL(txq) > MAX_TX_DESC(ctx) + 2; i++) { mp = _ring_peek_one(r, cidx, i); + MPASS(mp != NULL && *mp != NULL); in_use_prev = txq->ift_in_use; - err = iflib_encap(txq, mp); - /* - * What other errors should we bail out for? - */ - if (err == ENOBUFS) { + if ((err = iflib_encap(txq, mp)) == ENOBUFS) { DBG_COUNTER_INC(txq_drain_encapfail); + /* no room - bail out */ break; } consumed++; - if (err) + if (err) { + DBG_COUNTER_INC(txq_drain_encapfail); + /* we can't send this packet - skip it */ continue; - + } pkt_sent++; m = *mp; DBG_COUNTER_INC(tx_sent); @@ -2936,10 +2946,58 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) if_inc_counter(ifp, IFCOUNTER_OPACKETS, pkt_sent); if (mcast_sent) if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast_sent); - +#ifdef INVARIANTS + if (iflib_verbose_debug) + printf("consumed=%d\n", consumed); +#endif return (consumed); } +static uint32_t +iflib_txq_drain_always(struct ifmp_ring *r) +{ + return (1); +} + +static uint32_t +iflib_txq_drain_free(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) +{ + int i, avail; + struct mbuf **mp; + iflib_txq_t txq; + + txq = r->cookie; + + txq->ift_qstatus = IFLIB_QUEUE_IDLE; + CALLOUT_LOCK(txq); + callout_stop(&txq->ift_timer); + callout_stop(&txq->ift_db_check); + CALLOUT_UNLOCK(txq); + + avail = IDXDIFF(pidx, cidx, r->size); + for (i = 0; i < avail; i++) { + mp = _ring_peek_one(r, cidx, i); + m_freem(*mp); + } + MPASS(ifmp_ring_is_stalled(r) == 0); + return (avail); +} + +static void +iflib_ifmp_purge(iflib_txq_t txq) +{ + struct ifmp_ring *r; + + r = txq->ift_br[0]; + r->drain = iflib_txq_drain_free; + r->can_drain = iflib_txq_drain_always; + + ifmp_ring_check_drainage(r, r->size); + + r->drain = iflib_txq_drain; + r->can_drain = iflib_txq_can_drain; +} + static void _task_fn_tx(void *context) { @@ -3073,7 +3131,7 @@ iflib_if_transmit(if_t ifp, struct mbuf *m) if (__predict_false((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || !LINK_ACTIVE(ctx))) { DBG_COUNTER_INC(tx_frees); m_freem(m); - return (0); + return (ENOBUFS); } MPASS(m->m_nextpkt == NULL); @@ -3590,6 +3648,10 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct if (scctx->isc_rss_table_size == 0) scctx->isc_rss_table_size = 64; scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1; + + GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx); + /* XXX format name */ + taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "admin"); /* ** Now setup MSI or MSI/X, should ** return us the number of supported @@ -4342,6 +4404,7 @@ iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, gtask = &ctx->ifc_txqs[qid].ift_task; tqg = qgroup_if_io_tqg; fn = _task_fn_tx; + GROUPTASK_INIT(gtask, 0, fn, q); break; case IFLIB_INTR_RX: q = &ctx->ifc_rxqs[qid]; @@ -4349,9 +4412,11 @@ iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, gtask = &ctx->ifc_rxqs[qid].ifr_task; tqg = qgroup_if_io_tqg; fn = _task_fn_rx; + GROUPTASK_INIT(gtask, 0, fn, q); break; case IFLIB_INTR_ADMIN: q = ctx; + tqrid = -1; info = &ctx->ifc_filter_info; gtask = &ctx->ifc_admin_task; tqg = qgroup_if_config_tqg; @@ -4360,17 +4425,19 @@ iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, default: panic("unknown net intr type"); } - GROUPTASK_INIT(gtask, 0, fn, q); info->ifi_filter = filter; info->ifi_filter_arg = filter_arg; info->ifi_task = gtask; - /* XXX query cpu that rid belongs to */ - err = _iflib_irq_alloc(ctx, irq, rid, iflib_fast_intr, NULL, info, name); - if (err != 0) + if (err != 0) { + device_printf(ctx->ifc_dev, "_iflib_irq_alloc failed %d\n", err); return (err); + } + if (type == IFLIB_INTR_ADMIN) + return (0); + if (tqrid != -1) { cpuid = find_nth(ctx, &cpus, qid); taskqgroup_attach_cpu(tqg, gtask, q, cpuid, irq->ii_rid, name); @@ -4402,13 +4469,6 @@ iflib_softirq_alloc_generic(if_ctx_t ctx, int rid, iflib_intr_type_t type, void tqg = qgroup_if_io_tqg; fn = _task_fn_rx; break; - case IFLIB_INTR_ADMIN: - q = ctx; - gtask = &ctx->ifc_admin_task; - tqg = qgroup_if_config_tqg; - rid = -1; - fn = _task_fn_admin; - break; case IFLIB_INTR_IOV: q = ctx; gtask = &ctx->ifc_vflr_task; @@ -4965,7 +5025,6 @@ iflib_add_device_sysctl_post(if_ctx_t ctx) SYSCTL_ADD_COUNTER_U64(ctx_list, queue_list, OID_AUTO, "r_abdications", CTLFLAG_RD, &txq->ift_br[0]->abdications, "# of consumer abdications in the mp_ring for this queue"); - } if (scctx->isc_nrxqsets > 100) @@ -4987,6 +5046,7 @@ iflib_add_device_sysctl_post(if_ctx_t ctx) CTLFLAG_RD, &rxq->ifr_cq_cidx, 1, "Consumer Index"); } + for (j = 0, fl = rxq->ifr_fl; j < rxq->ifr_nfl; j++, fl++) { snprintf(namebuf, NAME_BUFLEN, "rxq_fl%d", j); fl_node = SYSCTL_ADD_NODE(ctx_list, queue_list, OID_AUTO, namebuf, diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 91158b0fccc..5f14287d10c 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1566,8 +1566,8 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) } static int -sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info, - struct walkarg *w, int len) +sysctl_iflist_ifml(struct ifnet *ifp, const struct if_data *src_ifd, + struct rt_addrinfo *info, struct walkarg *w, int len) { struct if_msghdrl *ifm; struct if_data *ifd; @@ -1598,14 +1598,14 @@ sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info, ifd = &ifm->ifm_data; } - if_data_copy(ifp, ifd); + memcpy(ifd, src_ifd, sizeof(*ifd)); return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len)); } static int -sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info, - struct walkarg *w, int len) +sysctl_iflist_ifm(struct ifnet *ifp, const struct if_data *src_ifd, + struct rt_addrinfo *info, struct walkarg *w, int len) { struct if_msghdr *ifm; struct if_data *ifd; @@ -1630,7 +1630,7 @@ sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info, ifd = &ifm->ifm_data; } - if_data_copy(ifp, ifd); + memcpy(ifd, src_ifd, sizeof(*ifd)); return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len)); } @@ -1705,15 +1705,18 @@ sysctl_iflist(int af, struct walkarg *w) { struct ifnet *ifp; struct ifaddr *ifa; + struct if_data ifd; struct rt_addrinfo info; int len, error = 0; struct sockaddr_storage ss; bzero((caddr_t)&info, sizeof(info)); + bzero(&ifd, sizeof(ifd)); IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; + if_data_copy(ifp, &ifd); IF_ADDR_RLOCK(ifp); ifa = ifp->if_addr; info.rti_info[RTAX_IFP] = ifa->ifa_addr; @@ -1723,9 +1726,11 @@ sysctl_iflist(int af, struct walkarg *w) info.rti_info[RTAX_IFP] = NULL; if (w->w_req && w->w_tmem) { if (w->w_op == NET_RT_IFLISTL) - error = sysctl_iflist_ifml(ifp, &info, w, len); + error = sysctl_iflist_ifml(ifp, &ifd, &info, w, + len); else - error = sysctl_iflist_ifm(ifp, &info, w, len); + error = sysctl_iflist_ifm(ifp, &ifd, &info, w, + len); if (error) goto done; } @@ -1768,13 +1773,15 @@ done: static int sysctl_ifmalist(int af, struct walkarg *w) { - struct ifnet *ifp; - struct ifmultiaddr *ifma; - struct rt_addrinfo info; - int len, error = 0; + struct rt_addrinfo info; struct ifaddr *ifa; + struct ifmultiaddr *ifma; + struct ifnet *ifp; + int error, len; + error = 0; bzero((caddr_t)&info, sizeof(info)); + IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) @@ -1794,7 +1801,7 @@ sysctl_ifmalist(int af, struct walkarg *w) ifma->ifma_lladdr : NULL; error = rtsock_msg_buffer(RTM_NEWMADDR, &info, w, &len); if (error != 0) - goto done; + break; if (w->w_req && w->w_tmem) { struct ifma_msghdr *ifmam; @@ -1803,15 +1810,14 @@ sysctl_ifmalist(int af, struct walkarg *w) ifmam->ifmam_flags = 0; ifmam->ifmam_addrs = info.rti_addrs; error = SYSCTL_OUT(w->w_req, w->w_tmem, len); - if (error) { - IF_ADDR_RUNLOCK(ifp); - goto done; - } + if (error != 0) + break; } } IF_ADDR_RUNLOCK(ifp); + if (error != 0) + break; } -done: IFNET_RUNLOCK_NOSLEEP(); return (error); } diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h index aceaba57cb0..7a33b53a232 100644 --- a/sys/net80211/_ieee80211.h +++ b/sys/net80211/_ieee80211.h @@ -402,4 +402,71 @@ struct ieee80211_mimo_info { uint8_t pad[2]; uint32_t evm[3]; /* EVM data */ }; + +/* + * ic_caps/iv_caps: device driver capabilities + */ +/* 0x2e available */ +#define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */ +#define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */ +#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */ +#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/ +#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */ +#define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */ +#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ +#define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */ +#define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */ +#define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */ +#define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */ +#define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */ +#define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */ +#define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/ +#define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */ +#define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */ +#define IEEE80211_C_SWAMSDUTX 0x00100000 /* CAPABILITY: software A-MSDU TX */ +/* 0x7c0000 available */ +#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ +#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ +#define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/ +#define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */ +#define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */ +#define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */ +/* 0x10000000 reserved */ +#define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */ +#define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */ +#define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */ +/* XXX protection/barker? */ + +#define IEEE80211_C_OPMODE \ + (IEEE80211_C_STA | IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | \ + IEEE80211_C_AHDEMO | IEEE80211_C_MONITOR | IEEE80211_C_WDS | \ + IEEE80211_C_TDMA | IEEE80211_C_MBSS) + +#define IEEE80211_C_BITS \ + "\20\1STA\002803ENCAP\7FF\10TURBOP\11IBSS\12PMGT" \ + "\13HOSTAP\14AHDEMO\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE" \ + "\21MONITOR\22DFS\23MBSS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \ + "\37TXFRAG\40TDMA" + +/* + * ic_htcaps/iv_htcaps: HT-specific device/driver capabilities + * + * NB: the low 16-bits are the 802.11 definitions, the upper + * 16-bits are used to define s/w/driver capabilities. + */ +#define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */ +#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */ +/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */ +#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */ +#define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/ +#define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */ +#define IEEE80211_HTC_RXUNEQUAL 0x00200000 /* CAPABILITY: RX unequal MCS */ +#define IEEE80211_HTC_RXMCS32 0x00400000 /* CAPABILITY: MCS32 support */ +#define IEEE80211_HTC_TXUNEQUAL 0x00800000 /* CAPABILITY: TX unequal MCS */ +#define IEEE80211_HTC_TXMCS32 0x01000000 /* CAPABILITY: MCS32 support */ + +#define IEEE80211_C_HTCAP_BITS \ + "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \ + "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS" + #endif /* _NET80211__IEEE80211_H_ */ diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index 8362f54bf1a..f32892651e4 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -120,9 +120,9 @@ adhoc_vattach(struct ieee80211vap *vap) static void sta_leave(void *arg, struct ieee80211_node *ni) { - struct ieee80211vap *vap = arg; + struct ieee80211vap *vap = ni->ni_vap; - if (ni->ni_vap == vap && ni != vap->iv_bss) + if (ni != vap->iv_bss) ieee80211_node_leave(ni); } @@ -164,7 +164,8 @@ adhoc_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) switch (ostate) { case IEEE80211_S_RUN: /* beacon miss */ /* purge station table; entries are stale */ - ieee80211_iterate_nodes(&ic->ic_sta, sta_leave, vap); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, + sta_leave, NULL); /* fall thru... */ case IEEE80211_S_INIT: if (vap->iv_des_chan != IEEE80211_CHAN_ANYC && @@ -315,6 +316,16 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; uint8_t *bssid; + int is_hw_decrypted = 0; + int has_decrypted = 0; + + /* + * Some devices do hardware decryption all the way through + * to pretending the frame wasn't encrypted in the first place. + * So, tag it appropriately so it isn't discarded inappropriately. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) + is_hw_decrypted = 1; if (m->m_flags & M_AMPDU_MPDU) { /* @@ -478,7 +489,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, * crypto cipher modules used to do delayed update * of replay sequence numbers. */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { /* * Discard encrypted frames when privacy is off. @@ -489,14 +500,14 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, IEEE80211_NODE_STAT(ni, rx_noprivacy); goto out; } - key = ieee80211_crypto_decap(ni, m, hdrspace); - if (key == NULL) { + if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) { /* NB: stats+msgs handled in crypto_decap */ IEEE80211_NODE_STAT(ni, rx_wepfail); goto out; } wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; + has_decrypted = 1; } else { /* XXX M_WEP and IEEE80211_F_PRIVACY */ key = NULL; @@ -527,7 +538,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, /* * Next strip any MSDU crypto bits. */ - if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) { + if (!ieee80211_crypto_demic(vap, key, m, 0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, ni->ni_macaddr, "data", "%s", "demic error"); vap->iv_stats.is_rx_demicfail++; @@ -581,7 +592,8 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, * any non-PAE frames received without encryption. */ if ((vap->iv_flags & IEEE80211_F_DROPUNENC) && - (key == NULL && (m->m_flags & M_WEP) == 0) && + ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) && + (is_hw_decrypted == 0) && eh->ether_type != htons(ETHERTYPE_PAE)) { /* * Drop unencrypted frames. diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c index 28bbddaf87c..9b0dc1e2dfd 100644 --- a/sys/net80211/ieee80211_crypto.c +++ b/sys/net80211/ieee80211_crypto.c @@ -580,8 +580,9 @@ ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m) * Validate and strip privacy headers (and trailer) for a * received frame that has the WEP/Privacy bit set. */ -struct ieee80211_key * -ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen) +int +ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen, + struct ieee80211_key **key) { #define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN) #define IEEE80211_WEP_MINLEN \ @@ -590,16 +591,38 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_key *k; struct ieee80211_frame *wh; + const struct ieee80211_rx_stats *rxs; const struct ieee80211_cipher *cip; uint8_t keyid; + /* + * Check for hardware decryption and IV stripping. + * If the IV is stripped then we definitely can't find a key. + * Set the key to NULL but return true; upper layers + * will need to handle a NULL key for a successful + * decrypt. + */ + rxs = ieee80211_get_rx_params_ptr(m); + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) { + if (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) { + /* + * Hardware decrypted, IV stripped. + * We can't find a key with a stripped IV. + * Return successful. + */ + *key = NULL; + return (1); + } + } + /* NB: this minimum size data frame could be bigger */ if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: WEP data frame too short, len %u\n", __func__, m->m_pkthdr.len); vap->iv_stats.is_rx_tooshort++; /* XXX need unique stat? */ - return NULL; + *key = NULL; + return (0); } /* @@ -625,15 +648,29 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen) IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, "unable to pullup %s header", cip->ic_name); vap->iv_stats.is_rx_wepfail++; /* XXX */ - return NULL; + *key = NULL; + return (0); } - return (cip->ic_decap(k, m, hdrlen) ? k : NULL); + /* + * Attempt decryption. + * + * If we fail then don't return the key - return NULL + * and an error. + */ + if (cip->ic_decap(k, m, hdrlen)) { + /* success */ + *key = k; + return (1); + } + + /* Failure */ + *key = NULL; + return (0); #undef IEEE80211_WEP_MINLEN #undef IEEE80211_WEP_HDRLEN } - /* * Check and remove any MIC. */ diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h index 3d1f8cc5e00..c5d64bf91b6 100644 --- a/sys/net80211/ieee80211_crypto.h +++ b/sys/net80211/ieee80211_crypto.h @@ -114,7 +114,8 @@ struct ieee80211_key { #define IEEE80211_KEY_DEVICE /* flags owned by device driver */\ (IEEE80211_KEY_DEVKEY|IEEE80211_KEY_CIPHER0|IEEE80211_KEY_CIPHER1| \ - IEEE80211_KEY_SWCRYPT|IEEE80211_KEY_SWMIC) + IEEE80211_KEY_SWCRYPT|IEEE80211_KEY_SWMIC|IEEE80211_KEY_NOIV | \ + IEEE80211_KEY_NOIVMGT|IEEE80211_KEY_NOMIC|IEEE80211_KEY_NOMICMGT) #define IEEE80211_KEY_BITS \ "\20\1XMIT\2RECV\3GROUP\4SWENCRYPT\5SWDECRYPT\6SWENMIC\7SWDEMIC" \ @@ -207,8 +208,8 @@ struct ieee80211_key *ieee80211_crypto_get_txkey(struct ieee80211_node *, struct mbuf *); struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *, struct mbuf *); -struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *, - struct mbuf *, int); +int ieee80211_crypto_decap(struct ieee80211_node *, + struct mbuf *, int, struct ieee80211_key **); int ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k, struct mbuf *, int); /* diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c index 9fdd5e08ee9..90e1c0733d0 100644 --- a/sys/net80211/ieee80211_crypto_ccmp.c +++ b/sys/net80211/ieee80211_crypto_ccmp.c @@ -162,12 +162,27 @@ ccmp_setiv(struct ieee80211_key *k, uint8_t *ivp) static int ccmp_encap(struct ieee80211_key *k, struct mbuf *m) { + const struct ieee80211_frame *wh; struct ccmp_ctx *ctx = k->wk_private; struct ieee80211com *ic = ctx->cc_ic; uint8_t *ivp; int hdrlen; + int is_mgmt; hdrlen = ieee80211_hdrspace(ic, mtod(m, void *)); + wh = mtod(m, const struct ieee80211_frame *); + is_mgmt = IEEE80211_IS_MGMT(wh); + + /* + * Check to see if we need to insert IV/MIC. + * + * Some offload devices don't require the IV to be inserted + * as part of the hardware encryption. + */ + if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT)) + return 1; + if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOIV)) + return 1; /* * Copy down 802.11 header and add the IV, KeyID, and ExtIV. @@ -217,12 +232,18 @@ READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) static int ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) { + const struct ieee80211_rx_stats *rxs; struct ccmp_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->cc_vap; struct ieee80211_frame *wh; uint8_t *ivp, tid; uint64_t pn; + rxs = ieee80211_get_rx_params_ptr(m); + + if ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP)) + goto finish; + /* * Header should have extended IV and sequence number; * verify the former and validate the latter. @@ -261,17 +282,28 @@ ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) !ccmp_decrypt(k, pn, m, hdrlen)) return 0; +finish: /* * Copy up 802.11 header and strip crypto bits. */ - ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header, hdrlen); - m_adj(m, ccmp.ic_header); - m_adj(m, -ccmp.ic_trailer); + if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) { + ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header, + hdrlen); + m_adj(m, ccmp.ic_header); + } + + /* + * XXX TODO: see if MMIC_STRIP also covers CCMP MIC trailer. + */ + if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP))) + m_adj(m, -ccmp.ic_trailer); /* * Ok to update rsc now. */ - k->wk_keyrsc[tid] = pn; + if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) { + k->wk_keyrsc[tid] = pn; + } return 1; } diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c index 8b33a791976..20258fa05e3 100644 --- a/sys/net80211/ieee80211_crypto_tkip.c +++ b/sys/net80211/ieee80211_crypto_tkip.c @@ -177,8 +177,13 @@ tkip_encap(struct ieee80211_key *k, struct mbuf *m) struct tkip_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->tc_vap; struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_frame *wh; uint8_t *ivp; int hdrlen; + int is_mgmt; + + wh = mtod(m, struct ieee80211_frame *); + is_mgmt = IEEE80211_IS_MGMT(wh); /* * Handle TKIP counter measures requirement. @@ -193,6 +198,16 @@ tkip_encap(struct ieee80211_key *k, struct mbuf *m) vap->iv_stats.is_crypto_tkipcm++; return 0; } + + /* + * Check to see whether IV needs to be included. + */ + if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT)) + return 1; + if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOIV)) + return 1; + + hdrlen = ieee80211_hdrspace(ic, mtod(m, void *)); /* @@ -224,6 +239,19 @@ static int tkip_enmic(struct ieee80211_key *k, struct mbuf *m, int force) { struct tkip_ctx *ctx = k->wk_private; + struct ieee80211_frame *wh; + int is_mgmt; + + wh = mtod(m, struct ieee80211_frame *); + is_mgmt = IEEE80211_IS_MGMT(wh); + + /* + * Check to see whether MIC needs to be included. + */ + if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOMICMGT)) + return 1; + if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOMIC)) + return 1; if (force || (k->wk_flags & IEEE80211_KEY_SWENMIC)) { struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); @@ -259,11 +287,20 @@ READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) static int tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) { + const struct ieee80211_rx_stats *rxs; struct tkip_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->tc_vap; struct ieee80211_frame *wh; uint8_t *ivp, tid; + rxs = ieee80211_get_rx_params_ptr(m); + + /* + * If IV has been stripped, we skip most of the below. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP)) + goto finish; + /* * Header should have extended IV and sequence number; * verify the former and validate the latter. @@ -318,11 +355,22 @@ tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) !tkip_decrypt(ctx, k, m, hdrlen)) return 0; +finish: + /* - * Copy up 802.11 header and strip crypto bits. + * Copy up 802.11 header and strip crypto bits - but only if we + * are required to. + */ + if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) { + memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), + hdrlen); + m_adj(m, tkip.ic_header); + } + + /* + * XXX TODO: do we need an option to potentially not strip the + * WEP trailer? Does "MMIC_STRIP" also mean this? Or? */ - memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), hdrlen); - m_adj(m, tkip.ic_header); m_adj(m, -tkip.ic_trailer); return 1; @@ -334,11 +382,33 @@ tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) static int tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force) { + const struct ieee80211_rx_stats *rxs; struct tkip_ctx *ctx = k->wk_private; struct ieee80211_frame *wh; uint8_t tid; wh = mtod(m, struct ieee80211_frame *); + rxs = ieee80211_get_rx_params_ptr(m); + + /* + * If we are told about a MIC failure from the driver, + * directly notify as a michael failure to the upper + * layers. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_FAIL_MIC)) { + struct ieee80211vap *vap = ctx->tc_vap; + ieee80211_notify_michael_failure(vap, wh, + k->wk_rxkeyix != IEEE80211_KEYIX_NONE ? + k->wk_rxkeyix : k->wk_keyix); + return 0; + } + + /* + * If IV has been stripped, we skip most of the below. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP)) + goto finish; + if ((k->wk_flags & IEEE80211_KEY_SWDEMIC) || force) { struct ieee80211vap *vap = ctx->tc_vap; int hdrlen = ieee80211_hdrspace(vap->iv_ic, wh); @@ -371,6 +441,7 @@ tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force) tid = ieee80211_gettid(wh); k->wk_keyrsc[tid] = ctx->rx_rsc; +finish: return 1; } diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index 5a9a301e74b..9868f133bca 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -107,9 +107,8 @@ hostap_vattach(struct ieee80211vap *vap) static void sta_disassoc(void *arg, struct ieee80211_node *ni) { - struct ieee80211vap *vap = arg; - if (ni->ni_vap == vap && ni->ni_associd != 0) { + if (ni->ni_associd != 0) { IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC, IEEE80211_REASON_ASSOC_LEAVE); ieee80211_node_leave(ni); @@ -119,9 +118,9 @@ sta_disassoc(void *arg, struct ieee80211_node *ni) static void sta_csa(void *arg, struct ieee80211_node *ni) { - struct ieee80211vap *vap = arg; + struct ieee80211vap *vap = ni->ni_vap; - if (ni->ni_vap == vap && ni->ni_associd != 0) + if (ni->ni_associd != 0) if (ni->ni_inact > vap->iv_inact_init) { ni->ni_inact = vap->iv_inact_init; IEEE80211_NOTE(vap, IEEE80211_MSG_INACT, ni, @@ -132,9 +131,8 @@ sta_csa(void *arg, struct ieee80211_node *ni) static void sta_drop(void *arg, struct ieee80211_node *ni) { - struct ieee80211vap *vap = arg; - if (ni->ni_vap == vap && ni->ni_associd != 0) + if (ni->ni_associd != 0) ieee80211_node_leave(ni); } @@ -179,7 +177,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ieee80211_dfs_cac_stop(vap); break; case IEEE80211_S_RUN: - ieee80211_iterate_nodes(&ic->ic_sta, sta_disassoc, vap); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, + sta_disassoc, NULL); break; default: break; @@ -195,7 +194,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) switch (ostate) { case IEEE80211_S_CSA: case IEEE80211_S_RUN: - ieee80211_iterate_nodes(&ic->ic_sta, sta_disassoc, vap); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, + sta_disassoc, NULL); /* * Clear overlapping BSS state; the beacon frame * will be reconstructed on transition to the RUN @@ -289,7 +289,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * Shorten inactivity timer of associated stations * to weed out sta's that don't follow a CSA. */ - ieee80211_iterate_nodes(&ic->ic_sta, sta_csa, vap); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, + sta_csa, NULL); /* * Update bss node channel to reflect where * we landed after CSA. @@ -340,7 +341,8 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * such as capabilities and the negotiated rate * set may/will be wrong). */ - ieee80211_iterate_nodes(&ic->ic_sta, sta_drop, vap); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, + sta_drop, NULL); } break; default: @@ -477,6 +479,16 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; uint8_t *bssid; + int is_hw_decrypted = 0; + int has_decrypted = 0; + + /* + * Some devices do hardware decryption all the way through + * to pretending the frame wasn't encrypted in the first place. + * So, tag it appropriately so it isn't discarded inappropriately. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) + is_hw_decrypted = 1; if (m->m_flags & M_AMPDU_MPDU) { /* @@ -666,7 +678,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, * crypto cipher modules used to do delayed update * of replay sequence numbers. */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { /* * Discard encrypted frames when privacy is off. @@ -677,14 +689,14 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, IEEE80211_NODE_STAT(ni, rx_noprivacy); goto out; } - key = ieee80211_crypto_decap(ni, m, hdrspace); - if (key == NULL) { + if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) { /* NB: stats+msgs handled in crypto_decap */ IEEE80211_NODE_STAT(ni, rx_wepfail); goto out; } wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; + has_decrypted = 1; } else { /* XXX M_WEP and IEEE80211_F_PRIVACY */ key = NULL; @@ -767,7 +779,8 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, * any non-PAE frames received without encryption. */ if ((vap->iv_flags & IEEE80211_F_DROPUNENC) && - (key == NULL && (m->m_flags & M_WEP) == 0) && + ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) && + (is_hw_decrypted == 0) && eh->ether_type != htons(ETHERTYPE_PAE)) { /* * Drop unencrypted frames. @@ -849,13 +862,13 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, goto out; } hdrspace = ieee80211_hdrspace(ic, wh); - key = ieee80211_crypto_decap(ni, m, hdrspace); - if (key == NULL) { + if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) { /* NB: stats+msgs handled in crypto_decap */ goto out; } wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; + has_decrypted = 1; } /* * Pass the packet to radiotap before calling iv_recv_mgmt(). diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 5d323c05a53..3a797d8175a 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -347,7 +347,6 @@ ieee80211_ioctl_getscanresults(struct ieee80211vap *vap, } struct stainforeq { - struct ieee80211vap *vap; struct ieee80211req_sta_info *si; size_t space; }; @@ -366,8 +365,6 @@ get_sta_space(void *arg, struct ieee80211_node *ni) struct stainforeq *req = arg; size_t ielen; - if (req->vap != ni->ni_vap) - return; if (ni->ni_vap->iv_opmode == IEEE80211_M_HOSTAP && ni->ni_associd == 0) /* only associated stations */ return; @@ -383,8 +380,6 @@ get_sta_info(void *arg, struct ieee80211_node *ni) size_t ielen, len; uint8_t *cp; - if (req->vap != ni->ni_vap) - return; if (vap->iv_opmode == IEEE80211_M_HOSTAP && ni->ni_associd == 0) /* only associated stations */ return; @@ -472,10 +467,10 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq, error = 0; req.space = 0; - req.vap = vap; - if (ni == NULL) - ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); - else + if (ni == NULL) { + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_sta_space, + &req); + } else get_sta_space(&req, ni); if (req.space > ireq->i_len) req.space = ireq->i_len; @@ -489,9 +484,10 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq, goto bad; } req.si = p; - if (ni == NULL) - ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); - else + if (ni == NULL) { + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, + get_sta_info, &req); + } else get_sta_info(&req, ni); ireq->i_len = space - req.space; error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len); diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 80c61f169ec..05746ad9561 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -2717,7 +2717,6 @@ done: } struct rssiinfo { - struct ieee80211vap *vap; int rssi_samples; uint32_t rssi_total; }; @@ -2729,8 +2728,6 @@ get_hostap_rssi(void *arg, struct ieee80211_node *ni) struct ieee80211vap *vap = ni->ni_vap; int8_t rssi; - if (info->vap != vap) - return; /* only associated stations */ if (ni->ni_associd == 0) return; @@ -2748,8 +2745,6 @@ get_adhoc_rssi(void *arg, struct ieee80211_node *ni) struct ieee80211vap *vap = ni->ni_vap; int8_t rssi; - if (info->vap != vap) - return; /* only neighbors */ /* XXX check bssid */ if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) @@ -2769,8 +2764,6 @@ get_mesh_rssi(void *arg, struct ieee80211_node *ni) struct ieee80211vap *vap = ni->ni_vap; int8_t rssi; - if (info->vap != vap) - return; /* only neighbors that peered successfully */ if (ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) return; @@ -2791,18 +2784,20 @@ ieee80211_getrssi(struct ieee80211vap *vap) info.rssi_total = 0; info.rssi_samples = 0; - info.vap = vap; switch (vap->iv_opmode) { case IEEE80211_M_IBSS: /* average of all ibss neighbors */ case IEEE80211_M_AHDEMO: /* average of all neighbors */ - ieee80211_iterate_nodes(&ic->ic_sta, get_adhoc_rssi, &info); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_adhoc_rssi, + &info); break; case IEEE80211_M_HOSTAP: /* average of all associated stations */ - ieee80211_iterate_nodes(&ic->ic_sta, get_hostap_rssi, &info); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_hostap_rssi, + &info); break; #ifdef IEEE80211_SUPPORT_MESH case IEEE80211_M_MBSS: /* average of all mesh neighbors */ - ieee80211_iterate_nodes(&ic->ic_sta, get_mesh_rssi, &info); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, get_mesh_rssi, + &info); break; #endif case IEEE80211_M_MONITOR: /* XXX */ diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 5a6cce625b9..c71f8541085 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -2074,6 +2074,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni, { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; + struct ieee80211_node *bss; const struct ieee80211_txparam *tp; struct ieee80211_bpf_params params; const struct ieee80211_rateset *rs; @@ -2081,10 +2082,13 @@ ieee80211_send_probereq(struct ieee80211_node *ni, uint8_t *frm; int ret; + bss = ieee80211_ref_node(vap->iv_bss); + if (vap->iv_state == IEEE80211_S_CAC) { IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni, "block %s frame in CAC state", "probe request"); vap->iv_stats.is_tx_badstate++; + ieee80211_free_node(bss); return EIO; /* XXX */ } @@ -2106,6 +2110,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni, * [tlv] supported rates * [tlv] RSN (optional) * [tlv] extended supported rates + * [tlv] HT cap (optional) * [tlv] WPA (optional) * [tlv] user-specified ie's */ @@ -2113,6 +2118,8 @@ ieee80211_send_probereq(struct ieee80211_node *ni, ic->ic_headroom + sizeof(struct ieee80211_frame), 2 + IEEE80211_NWID_LEN + 2 + IEEE80211_RATE_SIZE + + sizeof(struct ieee80211_ie_htcap) + + sizeof(struct ieee80211_ie_htinfo) + sizeof(struct ieee80211_ie_wpa) + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + sizeof(struct ieee80211_ie_wpa) @@ -2122,6 +2129,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni, if (m == NULL) { vap->iv_stats.is_tx_nobuf++; ieee80211_free_node(ni); + ieee80211_free_node(bss); return ENOMEM; } @@ -2130,6 +2138,27 @@ ieee80211_send_probereq(struct ieee80211_node *ni, frm = ieee80211_add_rates(frm, rs); frm = ieee80211_add_rsn(frm, vap); frm = ieee80211_add_xrates(frm, rs); + + /* + * Note: we can't use bss; we don't have one yet. + * + * So, we should announce our capabilities + * in this channel mode (2g/5g), not the + * channel details itself. + */ + if ((vap->iv_opmode == IEEE80211_M_IBSS) && + (vap->iv_flags_ht & IEEE80211_FHT_HT)) { + struct ieee80211_channel *c; + + /* + * Get the HT channel that we should try upgrading to. + * If we can do 40MHz then this'll upgrade it appropriately. + */ + c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan, + vap->iv_flags_ht); + frm = ieee80211_add_htcap_ch(frm, vap, c); + } + frm = ieee80211_add_wpa(frm, vap); if (vap->iv_appie_probereq != NULL) frm = add_appie(frm, vap->iv_appie_probereq); @@ -2141,6 +2170,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni, if (m == NULL) { /* NB: cannot happen */ ieee80211_free_node(ni); + ieee80211_free_node(bss); return ENOMEM; } @@ -2157,8 +2187,11 @@ ieee80211_send_probereq(struct ieee80211_node *ni, IEEE80211_NODE_STAT(ni, tx_mgmt); IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS, - "send probe req on channel %u bssid %s ssid \"%.*s\"\n", - ieee80211_chan2ieee(ic, ic->ic_curchan), ether_sprintf(bssid), + "send probe req on channel %u bssid %s sa %6D da %6D ssid \"%.*s\"\n", + ieee80211_chan2ieee(ic, ic->ic_curchan), + ether_sprintf(bssid), + sa, ":", + da, ":", ssidlen, ssid); memset(¶ms, 0, sizeof(params)); @@ -2173,6 +2206,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni, params.ibp_power = ni->ni_txpower; ret = ieee80211_raw_output(vap, ni, m, ¶ms); IEEE80211_TX_UNLOCK(ic); + ieee80211_free_node(bss); return (ret); } diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index 47b0573639b..82d65c6ecf7 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -1336,7 +1336,8 @@ sta_roam_check(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) * XXX force immediate switch on scan complete */ if (!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) && - ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)) + ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) || + ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))) ieee80211_bg_scan(vap, 0); return; } diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 9100fb0817e..dd9ef6e4d21 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -546,6 +546,16 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; uint8_t *bssid; + int is_hw_decrypted = 0; + int has_decrypted = 0; + + /* + * Some devices do hardware decryption all the way through + * to pretending the frame wasn't encrypted in the first place. + * So, tag it appropriately so it isn't discarded inappropriately. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) + is_hw_decrypted = 1; if (m->m_flags & M_AMPDU_MPDU) { /* @@ -723,6 +733,21 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, goto out; } + /* + * Handle privacy requirements for hardware decryption + * devices. + * + * For those devices, a handful of things happen. + * + * + If IV has been stripped, then we can't run + * ieee80211_crypto_decap() - none of the key + * + If MIC has been stripped, we can't validate + * MIC here. + * + If MIC fails, then we need to communicate a + * MIC failure up to the stack - but we don't know + * which key was used. + */ + /* * Handle privacy requirements. Note that we * must not be preempted from here until after @@ -731,7 +756,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, * crypto cipher modules used to do delayed update * of replay sequence numbers. */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { /* * Discard encrypted frames when privacy is off. @@ -742,14 +767,14 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, IEEE80211_NODE_STAT(ni, rx_noprivacy); goto out; } - key = ieee80211_crypto_decap(ni, m, hdrspace); - if (key == NULL) { + if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) { /* NB: stats+msgs handled in crypto_decap */ IEEE80211_NODE_STAT(ni, rx_wepfail); goto out; } wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; + has_decrypted = 1; } else { /* XXX M_WEP and IEEE80211_F_PRIVACY */ key = NULL; @@ -779,8 +804,13 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, /* * Next strip any MSDU crypto bits. + * + * Note: we can't do MIC stripping/verification if the + * upper layer has stripped it. We have to check MIC + * ourselves. So, key may be NULL, but we have to check + * the RX status. */ - if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) { + if (!ieee80211_crypto_demic(vap, key, m, 0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, ni->ni_macaddr, "data", "%s", "demic error"); vap->iv_stats.is_rx_demicfail++; @@ -834,7 +864,8 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, * any non-PAE frames received without encryption. */ if ((vap->iv_flags & IEEE80211_F_DROPUNENC) && - (key == NULL && (m->m_flags & M_WEP) == 0) && + ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) && + (is_hw_decrypted == 0) && eh->ether_type != htons(ETHERTYPE_PAE)) { /* * Drop unencrypted frames. @@ -883,6 +914,16 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, ether_sprintf(wh->i_addr2), rssi); } #endif + + /* + * Note: See above for hardware offload privacy requirements. + * It also applies here. + */ + + /* + * Again, having encrypted flag set check would be good, but + * then we have to also handle crypto_decap() like above. + */ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { if (subtype != IEEE80211_FC0_SUBTYPE_AUTH) { /* @@ -905,11 +946,16 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, goto out; } hdrspace = ieee80211_hdrspace(ic, wh); - key = ieee80211_crypto_decap(ni, m, hdrspace); - if (key == NULL) { + + /* + * Again, if IV/MIC was stripped, then this whole + * setup will fail. That's going to need some poking. + */ + if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) { /* NB: stats+msgs handled in crypto_decap */ goto out; } + has_decrypted = 1; wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; } @@ -1230,6 +1276,7 @@ done: * o bg scan is active * o no channel switch is pending * o there has not been any traffic recently + * o no full-offload scan support (no need for explicitly continuing scan then) * * Note we do not check if there is an administrative enable; * this is only done to start the scan. We assume that any @@ -1243,6 +1290,7 @@ contbgscan(struct ieee80211vap *vap) return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) && (ic->ic_flags & IEEE80211_F_CSAPENDING) == 0 && + !(vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) && vap->iv_state == IEEE80211_S_RUN && /* XXX? */ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)); } @@ -1253,7 +1301,7 @@ contbgscan(struct ieee80211vap *vap) * o no channel switch is pending * o we are not boosted on a dynamic turbo channel * o there has not been a scan recently - * o there has not been any traffic recently + * o there has not been any traffic recently (don't check if full-offload scan) */ static __inline int startbgscan(struct ieee80211vap *vap) @@ -1266,7 +1314,8 @@ startbgscan(struct ieee80211vap *vap) !IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) && #endif ieee80211_time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) && - ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle)); + ((vap->iv_flags_ext & IEEE80211_FEXT_SCAN_OFFLOAD) || + ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))); } static void diff --git a/sys/net80211/ieee80211_tdma.c b/sys/net80211/ieee80211_tdma.c index e85cb9827de..aac8c7fd55c 100644 --- a/sys/net80211/ieee80211_tdma.c +++ b/sys/net80211/ieee80211_tdma.c @@ -209,9 +209,9 @@ tdma_vdetach(struct ieee80211vap *vap) static void sta_leave(void *arg, struct ieee80211_node *ni) { - struct ieee80211vap *vap = arg; + struct ieee80211vap *vap = ni->ni_vap; - if (ni->ni_vap == vap && ni != vap->iv_bss) + if (ni != vap->iv_bss) ieee80211_node_leave(ni); } @@ -246,7 +246,8 @@ tdma_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ieee80211_cancel_scan(vap); /* background scan */ if (ostate == IEEE80211_S_RUN) { /* purge station table; entries are stale */ - ieee80211_iterate_nodes(&ic->ic_sta, sta_leave, vap); + ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, + sta_leave, NULL); } if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) { ieee80211_check_scan(vap, diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 479a8d62a82..37f4f6dde7f 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -633,70 +633,6 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_FVEN_BITS "\20" -/* ic_caps/iv_caps: device driver capabilities */ -/* 0x2e available */ -#define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */ -#define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */ -#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */ -#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/ -#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */ -#define IEEE80211_C_PMGT 0x00000200 /* CAPABILITY: Power mgmt */ -#define IEEE80211_C_HOSTAP 0x00000400 /* CAPABILITY: HOSTAP avail */ -#define IEEE80211_C_AHDEMO 0x00000800 /* CAPABILITY: Old Adhoc Demo */ -#define IEEE80211_C_SWRETRY 0x00001000 /* CAPABILITY: sw tx retry */ -#define IEEE80211_C_TXPMGT 0x00002000 /* CAPABILITY: tx power mgmt */ -#define IEEE80211_C_SHSLOT 0x00004000 /* CAPABILITY: short slottime */ -#define IEEE80211_C_SHPREAMBLE 0x00008000 /* CAPABILITY: short preamble */ -#define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */ -#define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/ -#define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */ -#define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */ -#define IEEE80211_C_SWAMSDUTX 0x00100000 /* CAPABILITY: software A-MSDU TX */ -/* 0x7c0000 available */ -#define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ -#define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ -#define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/ -#define IEEE80211_C_BURST 0x02000000 /* CAPABILITY: frame bursting */ -#define IEEE80211_C_WME 0x04000000 /* CAPABILITY: WME avail */ -#define IEEE80211_C_WDS 0x08000000 /* CAPABILITY: 4-addr support */ -/* 0x10000000 reserved */ -#define IEEE80211_C_BGSCAN 0x20000000 /* CAPABILITY: bg scanning */ -#define IEEE80211_C_TXFRAG 0x40000000 /* CAPABILITY: tx fragments */ -#define IEEE80211_C_TDMA 0x80000000 /* CAPABILITY: TDMA avail */ -/* XXX protection/barker? */ - -#define IEEE80211_C_OPMODE \ - (IEEE80211_C_STA | IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | \ - IEEE80211_C_AHDEMO | IEEE80211_C_MONITOR | IEEE80211_C_WDS | \ - IEEE80211_C_TDMA | IEEE80211_C_MBSS) - -#define IEEE80211_C_BITS \ - "\20\1STA\002803ENCAP\7FF\10TURBOP\11IBSS\12PMGT" \ - "\13HOSTAP\14AHDEMO\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE" \ - "\21MONITOR\22DFS\23MBSS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \ - "\37TXFRAG\40TDMA" - -/* - * ic_htcaps/iv_htcaps: HT-specific device/driver capabilities - * - * NB: the low 16-bits are the 802.11 definitions, the upper - * 16-bits are used to define s/w/driver capabilities. - */ -#define IEEE80211_HTC_AMPDU 0x00010000 /* CAPABILITY: A-MPDU tx */ -#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */ -/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */ -#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */ -#define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/ -#define IEEE80211_HTC_RIFS 0x00100000 /* CAPABILITY: RIFS support */ -#define IEEE80211_HTC_RXUNEQUAL 0x00200000 /* CAPABILITY: RX unequal MCS */ -#define IEEE80211_HTC_RXMCS32 0x00400000 /* CAPABILITY: MCS32 support */ -#define IEEE80211_HTC_TXUNEQUAL 0x00800000 /* CAPABILITY: TX unequal MCS */ -#define IEEE80211_HTC_TXMCS32 0x01000000 /* CAPABILITY: MCS32 suport */ - -#define IEEE80211_C_HTCAP_BITS \ - "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \ - "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS" - int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3); void ieee80211_ifattach(struct ieee80211com *); void ieee80211_ifdetach(struct ieee80211com *); diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c index 05268e81d71..038f41292ed 100644 --- a/sys/net80211/ieee80211_wds.c +++ b/sys/net80211/ieee80211_wds.c @@ -417,6 +417,16 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, struct ether_header *eh; int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; + int is_hw_decrypted = 0; + int has_decrypted = 0; + + /* + * Some devices do hardware decryption all the way through + * to pretending the frame wasn't encrypted in the first place. + * So, tag it appropriately so it isn't discarded inappropriately. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) + is_hw_decrypted = 1; if (m->m_flags & M_AMPDU_MPDU) { /* @@ -544,7 +554,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, * crypto cipher modules used to do delayed update * of replay sequence numbers. */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) { /* * Discard encrypted frames when privacy is off. @@ -555,14 +565,14 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, IEEE80211_NODE_STAT(ni, rx_noprivacy); goto out; } - key = ieee80211_crypto_decap(ni, m, hdrspace); - if (key == NULL) { + if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) { /* NB: stats+msgs handled in crypto_decap */ IEEE80211_NODE_STAT(ni, rx_wepfail); goto out; } wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; + has_decrypted = 1; } else { /* XXX M_WEP and IEEE80211_F_PRIVACY */ key = NULL; @@ -593,7 +603,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, /* * Next strip any MSDU crypto bits. */ - if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) { + if (!ieee80211_crypto_demic(vap, key, m, 0)) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, ni->ni_macaddr, "data", "%s", "demic error"); vap->iv_stats.is_rx_demicfail++; @@ -647,7 +657,8 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, * any non-PAE frames received without encryption. */ if ((vap->iv_flags & IEEE80211_F_DROPUNENC) && - (key == NULL && (m->m_flags & M_WEP) == 0) && + ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) && + (is_hw_decrypted == 0) && eh->ether_type != htons(ETHERTYPE_PAE)) { /* * Drop unencrypted frames. diff --git a/sys/netgraph/ng_l2tp.c b/sys/netgraph/ng_l2tp.c index 85cd6c3e340..55fa2cd3106 100644 --- a/sys/netgraph/ng_l2tp.c +++ b/sys/netgraph/ng_l2tp.c @@ -1544,6 +1544,16 @@ ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns) priv->stats.memoryFailures++; return (ENOBUFS); } + + /* + * The below requires 12 contiguous bytes for the L2TP header + * to be written into. + */ + m = m_pullup(m, 12); + if (m == NULL) { + priv->stats.memoryFailures++; + return (ENOBUFS); + } } /* Fill in L2TP header */ diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 63038584274..dbd27ef1b25 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -2202,9 +2202,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: + case TCPS_CLOSING: + case TCPS_LAST_ACK: so->so_error = ECONNRESET; close: - tcp_state_change(tp, TCPS_CLOSED); /* FALLTHROUGH */ default: tp = tcp_close(tp); diff --git a/sys/netinet/tcp_stacks/fastpath.c b/sys/netinet/tcp_stacks/fastpath.c index 2d7db04fbc1..edf46c4f960 100644 --- a/sys/netinet/tcp_stacks/fastpath.c +++ b/sys/netinet/tcp_stacks/fastpath.c @@ -746,9 +746,10 @@ tcp_do_slowpath(struct mbuf *m, struct tcphdr *th, struct socket *so, case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: + case TCPS_CLOSING: + case TCPS_LAST_ACK: so->so_error = ECONNRESET; close: - tcp_state_change(tp, TCPS_CLOSED); /* FALLTHROUGH */ default: tp = tcp_close(tp); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index f0e76bf1847..c5d059a5fe6 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1502,6 +1502,7 @@ tcp_discardcb(struct tcpcb *tp) inp->inp_ppcb = NULL; if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on tcpcb, let's free it. */ + TCPSTATES_DEC(tp->t_state); if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); @@ -1531,6 +1532,7 @@ tcp_timer_discard(void *ptp) tp->t_timers->tt_draincnt--; if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on this tcpcb, let's free it. */ + TCPSTATES_DEC(tp->t_state); if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); @@ -1577,7 +1579,8 @@ tcp_close(struct tcpcb *tp) #endif in_pcbdrop(inp); TCPSTAT_INC(tcps_closed); - TCPSTATES_DEC(tp->t_state); + if (tp->t_state != TCPS_CLOSED) + tcp_state_change(tp, TCPS_CLOSED); KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL")); so = inp->inp_socket; soisdisconnected(so); diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 27b965ea265..0253ccbc8db 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -340,6 +340,7 @@ tcp_twstart(struct tcpcb *tp) tcp_twrespond(tw, TH_ACK); inp->inp_ppcb = tw; inp->inp_flags |= INP_TIMEWAIT; + TCPSTATES_INC(TCPS_TIME_WAIT); tcp_tw_2msl_reset(tw, 0); /* diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index a04aba89841..5faf8a8937c 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -872,10 +872,11 @@ pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, uint8_t flags) if (PTE_ISWIRED(pte)) pmap->pm_stats.wired_count--; + /* Get vm_page_t for mapped pte. */ + m = PHYS_TO_VM_PAGE(PTE_PA(pte)); + /* Handle managed entry. */ if (PTE_ISMANAGED(pte)) { - /* Get vm_page_t for mapped pte. */ - m = PHYS_TO_VM_PAGE(PTE_PA(pte)); if (PTE_ISMODIFIED(pte)) vm_page_dirty(m); @@ -884,6 +885,15 @@ pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, uint8_t flags) vm_page_aflag_set(m, PGA_REFERENCED); pv_remove(pmap, va, m); + } else if (m->md.pv_tracked) { + /* + * Always pv_insert()/pv_remove() on MPC85XX, in case DPAA is + * used. This is needed by the NCSW support code for fast + * VA<->PA translation. + */ + pv_remove(pmap, va, m); + if (TAILQ_EMPTY(&m->md.pv_list)) + m->md.pv_tracked = false; } mtx_lock_spin(&tlbivax_mutex); @@ -3466,6 +3476,33 @@ pmap_early_io_map(vm_paddr_t pa, vm_size_t size) return (va); } +void +pmap_track_page(pmap_t pmap, vm_offset_t va) +{ + vm_paddr_t pa; + vm_page_t page; + struct pv_entry *pve; + + va &= ~PAGE_MASK; + pa = pmap_kextract(va); + + rw_wlock(&pvh_global_lock); + PMAP_LOCK(pmap); + page = PHYS_TO_VM_PAGE(pa); + + TAILQ_FOREACH(pve, &page->md.pv_list, pv_link) { + if ((pmap == pve->pv_pmap) && (va == pve->pv_va)) { + goto out; + } + } + page->md.pv_tracked = true; + pv_insert(pmap, va, page); +out: + PMAP_UNLOCK(pmap); + rw_wunlock(&pvh_global_lock); +} + + /* * Setup MAS4 defaults. * These values are loaded to MAS0-2 on a TLB miss. diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX index b26340fe539..f3ae67d6a8f 100644 --- a/sys/powerpc/conf/MPC85XX +++ b/sys/powerpc/conf/MPC85XX @@ -75,12 +75,15 @@ device alc device ether device fxp device gpio +device gpiopower device iic device iicbus #device isa device loop device md device miibus +device mmc +device mmcsd device pass device pci device quicc diff --git a/sys/powerpc/conf/MPC85XXSPE b/sys/powerpc/conf/MPC85XXSPE index 15470d578be..f9a0bc982ab 100644 --- a/sys/powerpc/conf/MPC85XXSPE +++ b/sys/powerpc/conf/MPC85XXSPE @@ -75,12 +75,15 @@ device alc device ether device fxp device gpio +device gpiopower device iic device iicbus #device isa device loop device md device miibus +device mmc +device mmcsd device pass device pci device quicc @@ -88,6 +91,7 @@ device random #device rl device scbus device scc +device sdhci device sec device tsec device dpaa diff --git a/sys/powerpc/conf/dpaa/files.dpaa b/sys/powerpc/conf/dpaa/files.dpaa index 18c44f9df91..b4a6c1aa29b 100644 --- a/sys/powerpc/conf/dpaa/files.dpaa +++ b/sys/powerpc/conf/dpaa/files.dpaa @@ -69,8 +69,6 @@ contrib/ncsw/user/env/core.c optional dpaa \ no-depend compile-with "${DPAA_COMPILE_CMD}" # FreeBSD Wrappers -dev/dpaa/dpaa.c optional dpaa fdt \ - no-depend compile-with "${DPAA_COMPILE_CMD}" dev/dpaa/portals_common.c optional dpaa \ no-depend compile-with "${DPAA_COMPILE_CMD}" dev/dpaa/bman_portals.c optional dpaa fdt \ diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h index c6b819804b3..c6611233960 100644 --- a/sys/powerpc/include/pmap.h +++ b/sys/powerpc/include/pmap.h @@ -179,7 +179,7 @@ void slb_free_tree(pmap_t pm); struct slb **slb_alloc_user_cache(void); void slb_free_user_cache(struct slb **); -#else +#elif defined(BOOKE) struct pmap { struct mtx pm_mtx; /* pmap mutex */ @@ -204,6 +204,7 @@ typedef struct pv_entry *pv_entry_t; struct md_page { TAILQ_HEAD(, pv_entry) pv_list; + int pv_tracked; }; #define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT @@ -261,6 +262,7 @@ extern int pmap_bootstrapped; vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size); void pmap_early_io_unmap(vm_offset_t va, vm_size_t size); +void pmap_track_page(pmap_t pmap, vm_offset_t va); #endif diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h index 697533b40af..dd1f9b52ddb 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.h +++ b/sys/powerpc/mpc85xx/mpc85xx.h @@ -36,6 +36,8 @@ * Configuration control and status registers */ extern vm_offset_t ccsrbar_va; +extern vm_paddr_t ccsrbar_pa; +extern vm_size_t ccsrbar_size; #define CCSRBAR_VA ccsrbar_va #define OCP85XX_CCSRBAR (CCSRBAR_VA + 0x0) #define OCP85XX_BPTR (CCSRBAR_VA + 0x20) diff --git a/sys/powerpc/mpc85xx/platform_mpc85xx.c b/sys/powerpc/mpc85xx/platform_mpc85xx.c index 592fe961efd..39309f5271f 100644 --- a/sys/powerpc/mpc85xx/platform_mpc85xx.c +++ b/sys/powerpc/mpc85xx/platform_mpc85xx.c @@ -78,7 +78,9 @@ struct cpu_release { #endif extern uint32_t *bootinfo; +vm_paddr_t ccsrbar_pa; vm_offset_t ccsrbar_va; +vm_size_t ccsrbar_size; static int cpu, maxcpu; @@ -194,6 +196,8 @@ mpc85xx_attach(platform_t plat) ccsrsize |= ranges[i]; } ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); + ccsrbar_pa = ccsrbar; + ccsrbar_size = ccsrsize; #if 0 mpc85xx_fix_errata(ccsrbar_va); diff --git a/sys/powerpc/mpc85xx/qoriq_gpio.c b/sys/powerpc/mpc85xx/qoriq_gpio.c index d09719cc387..15e0a2cd325 100644 --- a/sys/powerpc/mpc85xx/qoriq_gpio.c +++ b/sys/powerpc/mpc85xx/qoriq_gpio.c @@ -173,7 +173,7 @@ qoriq_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) outvals = bus_read_4(sc->sc_mem, GPIO_GPDAT); outvals &= ~(1 << pinbit); outvals |= (value << pinbit); - bus_write_4(sc->sc_mem, 0, outvals); + bus_write_4(sc->sc_mem, GPIO_GPDAT, outvals); GPIO_UNLOCK(sc); @@ -208,7 +208,7 @@ qoriq_gpio_pin_toggle(device_t dev, uint32_t pin) val = bus_read_4(sc->sc_mem, GPIO_GPDAT); val ^= (1 << (31 - pin)); - bus_write_4(sc->sc_mem, 0, val); + bus_write_4(sc->sc_mem, GPIO_GPDAT, val); GPIO_UNLOCK(sc); diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC index ad23c6647e7..a9c3c6fbdad 100644 --- a/sys/riscv/conf/GENERIC +++ b/sys/riscv/conf/GENERIC @@ -69,7 +69,7 @@ options CAPABILITIES # Capsicum capabilities options MAC # TrustedBSD MAC Framework options KDTRACE_FRAME # Ensure frames are compiled in options KDTRACE_HOOKS # Kernel DTrace hooks -# options VFP # Floating-point support +options FPE # Floating-point extension support options RACCT # Resource accounting framework options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default options RCTL # Resource limits diff --git a/sys/arm/rockchip/rk30xx_common.c b/sys/riscv/include/fpe.h similarity index 65% rename from sys/arm/rockchip/rk30xx_common.c rename to sys/riscv/include/fpe.h index 826ebda7981..1294ab0de8f 100644 --- a/sys/arm/rockchip/rk30xx_common.c +++ b/sys/riscv/include/fpe.h @@ -1,7 +1,11 @@ /*- - * Copyright (c) 2013 Ganbold Tsagaankhuu + * Copyright (c) 2016 Ruslan Bukin * All rights reserved. * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -22,40 +26,13 @@ * 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 -__FBSDID("$FreeBSD$"); +#ifndef _MACHINE_FPE_H_ +#define _MACHINE_FPE_H_ -#include -#include -#include -#include +void fpe_state_save(struct thread *td); -#include -#include - -#include -#include - -#ifndef INTRNG -static int -fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, - int *pol) -{ - - if (!fdt_is_compatible(node, "arm,gic")) - return (ENXIO); - - *interrupt = fdt32_to_cpu(intr[0]); - *trig = INTR_TRIGGER_CONFORM; - *pol = INTR_POLARITY_CONFORM; - - return (0); -} - -fdt_pic_decode_t fdt_pic_table[] = { - &fdt_aintc_decode_ic, - NULL -}; -#endif +#endif /* !_MACHINE_FPE_H_ */ diff --git a/sys/riscv/include/pcb.h b/sys/riscv/include/pcb.h index a6cecb73434..27737a4bdf2 100644 --- a/sys/riscv/include/pcb.h +++ b/sys/riscv/include/pcb.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2016 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -42,16 +42,21 @@ struct trapframe; struct pcb { - uint64_t pcb_ra; - uint64_t pcb_sp; - uint64_t pcb_gp; - uint64_t pcb_tp; - uint64_t pcb_t[7]; - uint64_t pcb_s[12]; - uint64_t pcb_a[8]; - uint64_t pcb_sepc; + uint64_t pcb_ra; /* Return address */ + uint64_t pcb_sp; /* Stack pointer */ + uint64_t pcb_gp; /* Global pointer */ + uint64_t pcb_tp; /* Thread pointer */ + uint64_t pcb_t[7]; /* Temporary registers */ + uint64_t pcb_s[12]; /* Saved registers */ + uint64_t pcb_a[8]; /* Argument registers */ + uint64_t pcb_x[32][2]; /* Floating point registers */ + uint64_t pcb_fcsr; /* Floating point control reg */ + uint64_t pcb_fpflags; /* Floating point flags */ +#define PCB_FP_STARTED 0x1 +#define PCB_FP_USERMASK 0x1 + uint64_t pcb_sepc; /* Supervisor exception pc */ vm_offset_t pcb_l1addr; /* L1 page tables base address */ - vm_offset_t pcb_onfault; + vm_offset_t pcb_onfault; /* Copyinout fault handler */ }; #ifdef _KERNEL diff --git a/sys/riscv/include/reg.h b/sys/riscv/include/reg.h index 35d79f10a8f..9e94b4a5768 100644 --- a/sys/riscv/include/reg.h +++ b/sys/riscv/include/reg.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 Ruslan Bukin + * Copyright (c) 2015-2016 Ruslan Bukin * All rights reserved. * * Portions of this software were developed by SRI International and the @@ -50,7 +50,8 @@ struct reg { }; struct fpreg { - int dummy; + uint64_t fp_x[32][2]; /* Floating point registers */ + uint64_t fp_fcsr; /* Floating point control reg */ }; struct dbreg { diff --git a/sys/riscv/include/riscvreg.h b/sys/riscv/include/riscvreg.h index 2e3a4a2e9f5..77f35bfa64b 100644 --- a/sys/riscv/include/riscvreg.h +++ b/sys/riscv/include/riscvreg.h @@ -60,10 +60,14 @@ #define SSTATUS_SPIE_SHIFT 5 #define SSTATUS_SPP (1 << 8) #define SSTATUS_SPP_SHIFT 8 -#define SSTATUS_FS_MASK 0x3 #define SSTATUS_FS_SHIFT 13 -#define SSTATUS_XS_MASK 0x3 +#define SSTATUS_FS_OFF (0x0 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_INITIAL (0x1 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_CLEAN (0x2 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_DIRTY (0x3 << SSTATUS_FS_SHIFT) +#define SSTATUS_FS_MASK (0x3 << SSTATUS_FS_SHIFT) #define SSTATUS_XS_SHIFT 15 +#define SSTATUS_XS_MASK (0x3 << SSTATUS_XS_SHIFT) #define SSTATUS_PUM (1 << 18) #define SSTATUS32_SD (1 << 63) #define SSTATUS64_SD (1 << 31) diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c index c9e9bc1c991..33f1d41750a 100644 --- a/sys/riscv/riscv/genassym.c +++ b/sys/riscv/riscv/genassym.c @@ -72,6 +72,8 @@ ASSYM(PCB_TP, offsetof(struct pcb, pcb_tp)); ASSYM(PCB_T, offsetof(struct pcb, pcb_t)); ASSYM(PCB_S, offsetof(struct pcb, pcb_s)); ASSYM(PCB_A, offsetof(struct pcb, pcb_a)); +ASSYM(PCB_X, offsetof(struct pcb, pcb_x)); +ASSYM(PCB_FCSR, offsetof(struct pcb, pcb_fcsr)); ASSYM(SF_UC, offsetof(struct sigframe, sf_uc)); diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 7bc4402597d..f08527a7f2f 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -84,8 +84,8 @@ __FBSDID("$FreeBSD$"); #include -#ifdef VFP -#include +#ifdef FPE +#include #endif #ifdef FDT @@ -203,17 +203,39 @@ set_regs(struct thread *td, struct reg *regs) int fill_fpregs(struct thread *td, struct fpreg *regs) { +#ifdef FPE + struct pcb *pcb; + + pcb = td->td_pcb; + + if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) { + /* + * If we have just been running FPE instructions we will + * need to save the state to memcpy it below. + */ + fpe_state_save(td); + + memcpy(regs->fp_x, pcb->pcb_x, sizeof(regs->fp_x)); + regs->fp_fcsr = pcb->pcb_fcsr; + } else +#endif + memset(regs->fp_x, 0, sizeof(regs->fp_x)); - /* TODO */ - bzero(regs, sizeof(*regs)); return (0); } int set_fpregs(struct thread *td, struct fpreg *regs) { +#ifdef FPE + struct pcb *pcb; + + pcb = td->td_pcb; + + memcpy(pcb->pcb_x, regs->fp_x, sizeof(regs->fp_x)); + pcb->pcb_fcsr = regs->fp_fcsr; +#endif - /* TODO */ return (0); } @@ -259,8 +281,10 @@ void exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { struct trapframe *tf; + struct pcb *pcb; tf = td->td_frame; + pcb = td->td_pcb; memset(tf, 0, sizeof(struct trapframe)); @@ -273,6 +297,8 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) tf->tf_sp = STACKALIGN(stack); tf->tf_ra = imgp->entry_addr; tf->tf_sepc = imgp->entry_addr; + + pcb->pcb_fpflags &= ~PCB_FP_STARTED; } /* Sanity check these are the same size, they will be memcpy'd to and fro */ @@ -337,13 +363,54 @@ set_mcontext(struct thread *td, mcontext_t *mcp) static void get_fpcontext(struct thread *td, mcontext_t *mcp) { - /* TODO */ +#ifdef FPE + struct pcb *curpcb; + + critical_enter(); + + curpcb = curthread->td_pcb; + + KASSERT(td->td_pcb == curpcb, ("Invalid fpe pcb")); + + if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) { + /* + * If we have just been running FPE instructions we will + * need to save the state to memcpy it below. + */ + fpe_state_save(td); + + KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0, + ("Non-userspace FPE flags set in get_fpcontext")); + memcpy(mcp->mc_fpregs.fp_x, curpcb->pcb_x, + sizeof(mcp->mc_fpregs)); + mcp->mc_fpregs.fp_fcsr = curpcb->pcb_fcsr; + mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags; + mcp->mc_flags |= _MC_FP_VALID; + } + + critical_exit(); +#endif } static void set_fpcontext(struct thread *td, mcontext_t *mcp) { - /* TODO */ +#ifdef FPE + struct pcb *curpcb; + + critical_enter(); + + if ((mcp->mc_flags & _MC_FP_VALID) != 0) { + curpcb = curthread->td_pcb; + /* FPE usage is enabled, override registers. */ + memcpy(curpcb->pcb_x, mcp->mc_fpregs.fp_x, + sizeof(mcp->mc_fpregs)); + curpcb->pcb_fcsr = mcp->mc_fpregs.fp_fcsr; + curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags & PCB_FP_USERMASK; + } + + critical_exit(); +#endif } void @@ -572,6 +639,7 @@ init_proc0(vm_offset_t kstack) proc_linkup0(&proc0, &thread0); thread0.td_kstack = kstack; thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1; + thread0.td_pcb->pcb_fpflags = 0; thread0.td_frame = &proc0_tf; pcpup->pc_curpcb = thread0.td_pcb; } diff --git a/sys/riscv/riscv/mp_machdep.c b/sys/riscv/riscv/mp_machdep.c index 33353ac2a3c..adad7b4b533 100644 --- a/sys/riscv/riscv/mp_machdep.c +++ b/sys/riscv/riscv/mp_machdep.c @@ -62,9 +62,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef VFP -#include -#endif #ifdef FDT #include @@ -242,10 +239,6 @@ init_secondary(uint64_t cpu) /* Start per-CPU event timers. */ cpu_initclocks_ap(); -#ifdef VFP - /* TODO: init FPU */ -#endif - /* Enable interrupts */ intr_enable(); diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c index 472779c35ad..af8806d8eea 100644 --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -1992,6 +1992,8 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) l2 = pmap_l1_to_l2(l1, sva); if (l2 == NULL) continue; + if (pmap_load(l2) == 0) + continue; if ((pmap_load(l2) & PTE_RX) != 0) continue; diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S index b5cced30d8f..5cc1edd69a0 100644 --- a/sys/riscv/riscv/swtch.S +++ b/sys/riscv/riscv/swtch.S @@ -42,6 +42,117 @@ __FBSDID("$FreeBSD$"); +#ifdef FPE +.macro __fpe_state_save p + /* + * Enable FPE usage in supervisor mode, + * so we can access registers. + */ + li t0, SSTATUS_FS_INITIAL + csrs sstatus, t0 + + /* Store registers */ + frcsr t0 + sd t0, (PCB_FCSR)(\p) + fsd f0, (PCB_X + 0 * 16)(\p) + fsd f1, (PCB_X + 1 * 16)(\p) + fsd f2, (PCB_X + 2 * 16)(\p) + fsd f3, (PCB_X + 3 * 16)(\p) + fsd f4, (PCB_X + 4 * 16)(\p) + fsd f5, (PCB_X + 5 * 16)(\p) + fsd f6, (PCB_X + 6 * 16)(\p) + fsd f7, (PCB_X + 7 * 16)(\p) + fsd f8, (PCB_X + 8 * 16)(\p) + fsd f9, (PCB_X + 9 * 16)(\p) + fsd f10, (PCB_X + 10 * 16)(\p) + fsd f11, (PCB_X + 11 * 16)(\p) + fsd f12, (PCB_X + 12 * 16)(\p) + fsd f13, (PCB_X + 13 * 16)(\p) + fsd f14, (PCB_X + 14 * 16)(\p) + fsd f15, (PCB_X + 15 * 16)(\p) + fsd f16, (PCB_X + 16 * 16)(\p) + fsd f17, (PCB_X + 17 * 16)(\p) + fsd f18, (PCB_X + 18 * 16)(\p) + fsd f19, (PCB_X + 19 * 16)(\p) + fsd f20, (PCB_X + 20 * 16)(\p) + fsd f21, (PCB_X + 21 * 16)(\p) + fsd f22, (PCB_X + 22 * 16)(\p) + fsd f23, (PCB_X + 23 * 16)(\p) + fsd f24, (PCB_X + 24 * 16)(\p) + fsd f25, (PCB_X + 25 * 16)(\p) + fsd f26, (PCB_X + 26 * 16)(\p) + fsd f27, (PCB_X + 27 * 16)(\p) + fsd f28, (PCB_X + 28 * 16)(\p) + fsd f29, (PCB_X + 29 * 16)(\p) + fsd f30, (PCB_X + 30 * 16)(\p) + fsd f31, (PCB_X + 31 * 16)(\p) + + /* Disable FPE usage in supervisor mode. */ + li t0, SSTATUS_FS_MASK + csrc sstatus, t0 +.endm + +.macro __fpe_state_load p + /* + * Enable FPE usage in supervisor mode, + * so we can access registers. + */ + li t0, SSTATUS_FS_INITIAL + csrs sstatus, t0 + + /* Restore registers */ + ld t0, (PCB_FCSR)(\p) + fscsr t0 + fld f0, (PCB_X + 0 * 16)(\p) + fld f1, (PCB_X + 1 * 16)(\p) + fld f2, (PCB_X + 2 * 16)(\p) + fld f3, (PCB_X + 3 * 16)(\p) + fld f4, (PCB_X + 4 * 16)(\p) + fld f5, (PCB_X + 5 * 16)(\p) + fld f6, (PCB_X + 6 * 16)(\p) + fld f7, (PCB_X + 7 * 16)(\p) + fld f8, (PCB_X + 8 * 16)(\p) + fld f9, (PCB_X + 9 * 16)(\p) + fld f10, (PCB_X + 10 * 16)(\p) + fld f11, (PCB_X + 11 * 16)(\p) + fld f12, (PCB_X + 12 * 16)(\p) + fld f13, (PCB_X + 13 * 16)(\p) + fld f14, (PCB_X + 14 * 16)(\p) + fld f15, (PCB_X + 15 * 16)(\p) + fld f16, (PCB_X + 16 * 16)(\p) + fld f17, (PCB_X + 17 * 16)(\p) + fld f18, (PCB_X + 18 * 16)(\p) + fld f19, (PCB_X + 19 * 16)(\p) + fld f20, (PCB_X + 20 * 16)(\p) + fld f21, (PCB_X + 21 * 16)(\p) + fld f22, (PCB_X + 22 * 16)(\p) + fld f23, (PCB_X + 23 * 16)(\p) + fld f24, (PCB_X + 24 * 16)(\p) + fld f25, (PCB_X + 25 * 16)(\p) + fld f26, (PCB_X + 26 * 16)(\p) + fld f27, (PCB_X + 27 * 16)(\p) + fld f28, (PCB_X + 28 * 16)(\p) + fld f29, (PCB_X + 29 * 16)(\p) + fld f30, (PCB_X + 30 * 16)(\p) + fld f31, (PCB_X + 31 * 16)(\p) + + /* Disable FPE usage in supervisor mode. */ + li t0, SSTATUS_FS_MASK + csrc sstatus, t0 +.endm + +/* + * void + * fpe_state_save(struct thread *td) + */ +ENTRY(fpe_state_save) + /* Get pointer to PCB */ + ld a0, TD_PCB(a0) + __fpe_state_save a0 + ret +END(fpe_state_save) +#endif /* FPE */ + /* * void cpu_throw(struct thread *old, struct thread *new) */ @@ -81,8 +192,20 @@ ENTRY(cpu_throw) ld s10, (PCB_S + 10 * 8)(x13) ld s11, (PCB_S + 11 * 8)(x13) - ret +#ifdef FPE + /* Is FPE enabled for new thread? */ + ld t0, TD_FRAME(a1) + ld t1, (TF_SSTATUS)(t0) + li t2, SSTATUS_FS_MASK + and t3, t1, t2 + beqz t3, 1f /* No, skip. */ + /* Restore registers. */ + __fpe_state_load x13 +1: +#endif + + ret .Lcpu_throw_panic_str: .asciz "cpu_throw: %p\0" END(cpu_throw) @@ -123,6 +246,29 @@ ENTRY(cpu_switch) sd s10, (PCB_S + 10 * 8)(x13) sd s11, (PCB_S + 11 * 8)(x13) +#ifdef FPE + /* + * Is FPE enabled and is it in dirty state + * for the old thread? + */ + ld t0, TD_FRAME(a0) + ld t1, (TF_SSTATUS)(t0) + li t2, SSTATUS_FS_MASK + and t3, t1, t2 + li t2, SSTATUS_FS_DIRTY + bne t3, t2, 1f /* No, skip. */ + + /* Yes, mark FPE state clean and save registers. */ + li t2, ~SSTATUS_FS_MASK + and t3, t1, t2 + li t2, SSTATUS_FS_CLEAN + or t3, t3, t2 + sd t3, (TF_SSTATUS)(t0) + + __fpe_state_save x13 +1: +#endif + /* * Restore the saved context. */ @@ -171,6 +317,20 @@ ENTRY(cpu_switch) ld s9, (PCB_S + 9 * 8)(x13) ld s10, (PCB_S + 10 * 8)(x13) ld s11, (PCB_S + 11 * 8)(x13) + +#ifdef FPE + /* Is FPE enabled for new thread? */ + ld t0, TD_FRAME(a1) + ld t1, (TF_SSTATUS)(t0) + li t2, SSTATUS_FS_MASK + and t3, t1, t2 + beqz t3, 1f /* No, skip. */ + + /* Restore registers. */ + __fpe_state_load x13 +1: +#endif + ret .Lcpu_switch_panic_str: .asciz "cpu_switch: %p\0" @@ -269,9 +429,8 @@ ENTRY(savectx) sd s10, (PCB_S + 10 * 8)(a0) sd s11, (PCB_S + 11 * 8)(a0) - /* Store the VFP registers */ -#ifdef VFP - /* TODO */ +#ifdef FPE + __fpe_state_save a0 #endif ret END(savectx) diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c index 97d9a2c1efd..cd2b7c4bfb7 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -328,9 +328,11 @@ do_trap_user(struct trapframe *frame) uint64_t exception; struct thread *td; uint64_t sstatus; + struct pcb *pcb; td = curthread; td->td_frame = frame; + pcb = td->td_pcb; /* Ensure we came from usermode, interrupts disabled */ __asm __volatile("csrr %0, sstatus" : "=&r" (sstatus)); @@ -358,6 +360,17 @@ do_trap_user(struct trapframe *frame) svc_handler(frame); break; case EXCP_ILLEGAL_INSTRUCTION: +#ifdef FPE + if ((pcb->pcb_fpflags & PCB_FP_STARTED) == 0) { + /* + * May be a FPE trap. Enable FPE usage + * for this thread and try again. + */ + frame->tf_sstatus |= SSTATUS_FS_INITIAL; + pcb->pcb_fpflags |= PCB_FP_STARTED; + break; + } +#endif call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc); userret(td, frame); break; diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c index d2d4c6e3d3e..c5c62fe24db 100644 --- a/sys/riscv/riscv/vm_machdep.c +++ b/sys/riscv/riscv/vm_machdep.c @@ -87,8 +87,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) /* Arguments for child */ tf->tf_a[0] = 0; tf->tf_a[1] = 0; - tf->tf_sstatus = (SSTATUS_SPIE); - tf->tf_sstatus |= (MSTATUS_PRV_U << MSTATUS_SPP_SHIFT); + tf->tf_sstatus |= (SSTATUS_SPIE); /* Enable interrupts. */ + tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */ td2->td_frame = tf; diff --git a/sys/sys/kerneldump.h b/sys/sys/kerneldump.h index fd010181eb1..13bef698ffc 100644 --- a/sys/sys/kerneldump.h +++ b/sys/sys/kerneldump.h @@ -64,7 +64,8 @@ struct kerneldumpheader { #define KERNELDUMPMAGIC_CLEARED "Cleared Kernel Dump" char architecture[12]; uint32_t version; -#define KERNELDUMPVERSION 1 +#define KERNELDUMPVERSION 1 +#define KERNELDUMP_TEXT_VERSION 1 uint32_t architectureversion; #define KERNELDUMP_AARCH64_VERSION 1 #define KERNELDUMP_AMD64_VERSION 2 @@ -74,7 +75,6 @@ struct kerneldumpheader { #define KERNELDUMP_POWERPC_VERSION 1 #define KERNELDUMP_RISCV_VERSION 1 #define KERNELDUMP_SPARC64_VERSION 1 -#define KERNELDUMP_TEXT_VERSION 1 uint64_t dumplength; /* excl headers */ uint64_t dumptime; uint32_t blocksize; diff --git a/sys/sys/queue.h b/sys/sys/queue.h index 7bb604f3de2..cff8fabd7f6 100644 --- a/sys/sys/queue.h +++ b/sys/sys/queue.h @@ -472,6 +472,12 @@ struct { \ */ #if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) + * + * If the list is non-empty, validates that the first element of the list + * points back at 'head.' + */ #define QMD_LIST_CHECK_HEAD(head, field) do { \ if (LIST_FIRST((head)) != NULL && \ LIST_FIRST((head))->field.le_prev != \ @@ -479,6 +485,12 @@ struct { \ panic("Bad list head %p first->prev != head", (head)); \ } while (0) +/* + * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) + * + * If an element follows 'elm' in the list, validates that the next element + * points back at 'elm.' + */ #define QMD_LIST_CHECK_NEXT(elm, field) do { \ if (LIST_NEXT((elm), field) != NULL && \ LIST_NEXT((elm), field)->field.le_prev != \ @@ -486,6 +498,11 @@ struct { \ panic("Bad link elm %p next->prev != elm", (elm)); \ } while (0) +/* + * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) + * + * Validates that the previous element (or head of the list) points to 'elm.' + */ #define QMD_LIST_CHECK_PREV(elm, field) do { \ if (*(elm)->field.le_prev != (elm)) \ panic("Bad link elm %p prev->next != elm", (elm)); \ @@ -634,6 +651,12 @@ struct { \ * Tail queue functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * If the tailq is non-empty, validates that the first element of the tailq + * points back at 'head.' + */ #define QMD_TAILQ_CHECK_HEAD(head, field) do { \ if (!TAILQ_EMPTY(head) && \ TAILQ_FIRST((head))->field.tqe_prev != \ @@ -641,11 +664,22 @@ struct { \ panic("Bad tailq head %p first->prev != head", (head)); \ } while (0) +/* + * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * Validates that the tail of the tailq is a pointer to pointer to NULL. + */ #define QMD_TAILQ_CHECK_TAIL(head, field) do { \ if (*(head)->tqh_last != NULL) \ panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ } while (0) +/* + * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) + * + * If an element follows 'elm' in the tailq, validates that the next element + * points back at 'elm.' + */ #define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ if (TAILQ_NEXT((elm), field) != NULL && \ TAILQ_NEXT((elm), field)->field.tqe_prev != \ @@ -653,6 +687,11 @@ struct { \ panic("Bad link elm %p next->prev != elm", (elm)); \ } while (0) +/* + * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) + * + * Validates that the previous element (or head of the tailq) points to 'elm.' + */ #define QMD_TAILQ_CHECK_PREV(elm, field) do { \ if (*(elm)->field.tqe_prev != (elm)) \ panic("Bad link elm %p prev->next != elm", (elm)); \ diff --git a/sys/sys/sf_buf.h b/sys/sys/sf_buf.h index b5970d95fd8..6aebe430ab6 100644 --- a/sys/sys/sf_buf.h +++ b/sys/sys/sf_buf.h @@ -41,6 +41,7 @@ struct sfstat { /* sendfile statistics */ uint64_t sf_busy; /* times aborted on a busy page */ uint64_t sf_allocfail; /* times sfbuf allocation failed */ uint64_t sf_allocwait; /* times sfbuf allocation had to wait */ + uint64_t sf_pages_bogus; /* times bogus page was used */ }; #ifdef _KERNEL diff --git a/sys/sys/socket.h b/sys/sys/socket.h index f23b5f6994c..ea3d9b6bee3 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -590,6 +590,7 @@ struct sf_hdtr { #define SF_NODISKIO 0x00000001 #define SF_MNOWAIT 0x00000002 /* obsolete */ #define SF_SYNC 0x00000004 +#define SF_USER_READAHEAD 0x00000008 #define SF_NOCACHE 0x00000010 #define SF_FLAGS(rh, flags) (((rh) << 16) | (flags)) diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 2520f007ec6..c258a202920 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -147,7 +147,7 @@ ffs_mount(struct mount *mp) struct ufsmount *ump = NULL; struct fs *fs; pid_t fsckpid = 0; - int error, flags; + int error, error1, flags; uint64_t mntorflags; accmode_t accmode; struct nameidata ndp; @@ -453,6 +453,11 @@ ffs_mount(struct mount *mp) */ if (mp->mnt_flag & MNT_SNAPSHOT) return (ffs_snapshot(mp, fspec)); + + /* + * Must not call namei() while owning busy ref. + */ + vfs_unbusy(mp); } /* @@ -460,7 +465,18 @@ ffs_mount(struct mount *mp) * and verify that it refers to a sensible disk device. */ NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td); - if ((error = namei(&ndp)) != 0) + error = namei(&ndp); + if ((mp->mnt_flag & MNT_UPDATE) != 0) { + /* + * Unmount does not start if MNT_UPDATE is set. Mount + * update busies mp before setting MNT_UPDATE. We + * must be able to retain our busy ref succesfully, + * without sleep. + */ + error1 = vfs_busy(mp, MBF_NOWAIT); + MPASS(error1 == 0); + } + if (error != 0) return (error); NDFREE(&ndp, NDF_ONLY_PNBUF); devvp = ndp.ni_vp; diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 8f46cf38e7b..bf57203c119 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -1126,7 +1126,7 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, if (shift != 0) { for (i = 1; i <= shift; i++) { p = vm_page_alloc(object, m[0]->pindex - i, - VM_ALLOC_NORMAL | VM_ALLOC_IFNOTCACHED); + VM_ALLOC_NORMAL); if (p == NULL) { /* Shift allocated pages to the left. */ for (j = 0; j < i - 1; j++) @@ -1144,8 +1144,7 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, if (rahead != NULL) { for (i = 0; i < *rahead; i++) { p = vm_page_alloc(object, - m[reqcount - 1]->pindex + i + 1, - VM_ALLOC_NORMAL | VM_ALLOC_IFNOTCACHED); + m[reqcount - 1]->pindex + i + 1, VM_ALLOC_NORMAL); if (p == NULL) break; bp->b_pages[shift + reqcount + i] = p; diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index b73cf645918..41391eb7e2b 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -246,6 +246,48 @@ vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot, vm_pager_page_unswapped(m); } +static void +vm_fault_fill_hold(vm_page_t *m_hold, vm_page_t m) +{ + + if (m_hold != NULL) { + *m_hold = m; + vm_page_lock(m); + vm_page_hold(m); + vm_page_unlock(m); + } +} + +/* + * Unlocks fs.first_object and fs.map on success. + */ +static int +vm_fault_soft_fast(struct faultstate *fs, vm_offset_t vaddr, vm_prot_t prot, + int fault_type, int fault_flags, boolean_t wired, vm_page_t *m_hold) +{ + vm_page_t m; + int rv; + + MPASS(fs->vp == NULL); + m = vm_page_lookup(fs->first_object, fs->first_pindex); + /* A busy page can be mapped for read|execute access. */ + if (m == NULL || ((prot & VM_PROT_WRITE) != 0 && + vm_page_busied(m)) || m->valid != VM_PAGE_BITS_ALL) + return (KERN_FAILURE); + rv = pmap_enter(fs->map->pmap, vaddr, m, prot, fault_type | + PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED : 0), 0); + if (rv != KERN_SUCCESS) + return (rv); + vm_fault_fill_hold(m_hold, m); + vm_fault_dirty(fs->entry, m, prot, fault_type, fault_flags, false); + VM_OBJECT_RUNLOCK(fs->first_object); + if (!wired) + vm_fault_prefault(fs, vaddr, PFBAK, PFFOR); + vm_map_lookup_done(fs->map, fs->entry); + curthread->td_ru.ru_minflt++; + return (KERN_SUCCESS); +} + /* * vm_fault: * @@ -294,7 +336,6 @@ vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, struct vnode *vp; vm_object_t next_object, retry_object; vm_offset_t e_end, e_start; - vm_page_t m; vm_pindex_t retry_pindex; vm_prot_t prot, retry_prot; int ahead, alloc_req, behind, cluster_offset, error, era, faultcount; @@ -376,36 +417,15 @@ RetryFault:; (fs.first_object->flags & OBJ_TMPFS_NODE) == 0) || (fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0)) { VM_OBJECT_RLOCK(fs.first_object); - if ((prot & VM_PROT_WRITE) != 0 && - (fs.first_object->type == OBJT_VNODE || - (fs.first_object->flags & OBJ_TMPFS_NODE) != 0) && - (fs.first_object->flags & OBJ_MIGHTBEDIRTY) == 0) - goto fast_failed; - m = vm_page_lookup(fs.first_object, fs.first_pindex); - /* A busy page can be mapped for read|execute access. */ - if (m == NULL || ((prot & VM_PROT_WRITE) != 0 && - vm_page_busied(m)) || m->valid != VM_PAGE_BITS_ALL) - goto fast_failed; - result = pmap_enter(fs.map->pmap, vaddr, m, prot, - fault_type | PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED : - 0), 0); - if (result != KERN_SUCCESS) - goto fast_failed; - if (m_hold != NULL) { - *m_hold = m; - vm_page_lock(m); - vm_page_hold(m); - vm_page_unlock(m); + if ((prot & VM_PROT_WRITE) == 0 || + (fs.first_object->type != OBJT_VNODE && + (fs.first_object->flags & OBJ_TMPFS_NODE) == 0) || + (fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0) { + rv = vm_fault_soft_fast(&fs, vaddr, prot, fault_type, + fault_flags, wired, m_hold); + if (rv == KERN_SUCCESS) + return (rv); } - vm_fault_dirty(fs.entry, m, prot, fault_type, fault_flags, - false); - VM_OBJECT_RUNLOCK(fs.first_object); - if (!wired) - vm_fault_prefault(&fs, vaddr, PFBAK, PFFOR); - vm_map_lookup_done(fs.map, fs.entry); - curthread->td_ru.ru_minflt++; - return (KERN_SUCCESS); -fast_failed: if (!VM_OBJECT_TRYUPGRADE(fs.first_object)) { VM_OBJECT_RUNLOCK(fs.first_object); VM_OBJECT_WLOCK(fs.first_object); @@ -559,8 +579,7 @@ fast_failed: unlock_and_deallocate(&fs); VM_WAITPFAULT; goto RetryFault; - } else if (fs.m->valid == VM_PAGE_BITS_ALL) - break; + } } readrest: diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 1fd97d1f5aa..be84ec2167e 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -877,9 +877,6 @@ RestartScan: pindex = OFF_TO_IDX(current->offset + (addr - current->start)); m = vm_page_lookup(object, pindex); - if (m == NULL && - vm_page_is_cached(object, pindex)) - mincoreinfo = MINCORE_INCORE; if (m != NULL && m->valid == 0) m = NULL; if (m != NULL) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 0cf364fcaa4..676a6971f32 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -178,9 +178,6 @@ vm_object_zdtor(void *mem, int size, void *arg) ("object %p has reservations", object)); #endif - KASSERT(vm_object_cache_is_empty(object), - ("object %p has cached pages", - object)); KASSERT(object->paging_in_progress == 0, ("object %p paging_in_progress = %d", object, object->paging_in_progress)); @@ -212,8 +209,6 @@ vm_object_zinit(void *mem, int size, int flags) object->paging_in_progress = 0; object->resident_page_count = 0; object->shadow_count = 0; - object->cache.rt_root = 0; - object->cache.rt_flags = 0; mtx_lock(&vm_object_list_mtx); TAILQ_INSERT_TAIL(&vm_object_list, object, object_list); @@ -792,8 +787,6 @@ vm_object_terminate(vm_object_t object) if (__predict_false(!LIST_EMPTY(&object->rvq))) vm_reserv_break_all(object); #endif - if (__predict_false(!vm_object_cache_is_empty(object))) - vm_page_cache_free(object, 0, 0); KASSERT(object->cred == NULL || object->type == OBJT_DEFAULT || object->type == OBJT_SWAP, @@ -1135,13 +1128,6 @@ shadowlookup: } else if ((tobject->flags & OBJ_UNMANAGED) != 0) goto unlock_tobject; m = vm_page_lookup(tobject, tpindex); - if (m == NULL && advise == MADV_WILLNEED) { - /* - * If the page is cached, reactivate it. - */ - m = vm_page_alloc(tobject, tpindex, VM_ALLOC_IFCACHED | - VM_ALLOC_NOBUSY); - } if (m == NULL) { /* * There may be swap even if there is no backing page @@ -1406,19 +1392,6 @@ retry: swap_pager_copy(orig_object, new_object, offidxstart, 0); TAILQ_FOREACH(m, &new_object->memq, listq) vm_page_xunbusy(m); - - /* - * Transfer any cached pages from orig_object to new_object. - * If swap_pager_copy() found swapped out pages within the - * specified range of orig_object, then it changed - * new_object's type to OBJT_SWAP when it transferred those - * pages to new_object. Otherwise, new_object's type - * should still be OBJT_DEFAULT and orig_object should not - * contain any cached pages within the specified range. - */ - if (__predict_false(!vm_object_cache_is_empty(orig_object))) - vm_page_cache_transfer(orig_object, offidxstart, - new_object); } VM_OBJECT_WUNLOCK(orig_object); VM_OBJECT_WUNLOCK(new_object); @@ -1754,13 +1727,6 @@ vm_object_collapse(vm_object_t object) backing_object, object, OFF_TO_IDX(object->backing_object_offset), TRUE); - - /* - * Free any cached pages from backing_object. - */ - if (__predict_false( - !vm_object_cache_is_empty(backing_object))) - vm_page_cache_free(backing_object, 0, 0); } /* * Object now shadows whatever backing_object did. @@ -1889,7 +1855,7 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, (options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED, ("vm_object_page_remove: illegal options for object %p", object)); if (object->resident_page_count == 0) - goto skipmemq; + return; vm_object_pip_add(object, 1); again: p = vm_page_find_least(object, start); @@ -1946,9 +1912,6 @@ next: vm_page_unlock(p); } vm_object_pip_wakeup(object); -skipmemq: - if (__predict_false(!vm_object_cache_is_empty(object))) - vm_page_cache_free(object, start, end); } /* diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index 73998aae843..52bc44ce2b3 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -118,7 +118,6 @@ struct vm_object { vm_ooffset_t backing_object_offset;/* Offset in backing object */ TAILQ_ENTRY(vm_object) pager_object_list; /* list of all objects of this pager type */ LIST_HEAD(, vm_reserv) rvq; /* list of reservations */ - struct vm_radix cache; /* (o + f) root of the cache page radix trie */ void *handle; union { /* @@ -290,13 +289,6 @@ void vm_object_pip_wakeup(vm_object_t object); void vm_object_pip_wakeupn(vm_object_t object, short i); void vm_object_pip_wait(vm_object_t object, char *waitid); -static __inline boolean_t -vm_object_cache_is_empty(vm_object_t object) -{ - - return (vm_radix_is_empty(&object->cache)); -} - void umtx_shm_object_init(vm_object_t object); void umtx_shm_object_terminated(vm_object_t object); extern int umtx_shm_vnobj_persistent; diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 78bf98ae016..50c95bf5c40 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -154,8 +154,7 @@ static int vm_pageout_pages_needed; static uma_zone_t fakepg_zone; -static struct vnode *vm_page_alloc_init(vm_page_t m); -static void vm_page_cache_turn_free(vm_page_t m); +static void vm_page_alloc_check(vm_page_t m); static void vm_page_clear_dirty_mask(vm_page_t m, vm_page_bits_t pagebits); static void vm_page_enqueue(uint8_t queue, vm_page_t m); static void vm_page_free_wakeup(void); @@ -1118,9 +1117,7 @@ void vm_page_dirty_KBI(vm_page_t m) { - /* These assertions refer to this operation by its public name. */ - KASSERT((m->flags & PG_CACHED) == 0, - ("vm_page_dirty: page in cache!")); + /* Refer to this operation by its public name. */ KASSERT(m->valid == VM_PAGE_BITS_ALL, ("vm_page_dirty: page is invalid!")); m->dirty = VM_PAGE_BITS_ALL; @@ -1458,142 +1455,6 @@ vm_page_rename(vm_page_t m, vm_object_t new_object, vm_pindex_t new_pindex) return (0); } -/* - * Convert all of the given object's cached pages that have a - * pindex within the given range into free pages. If the value - * zero is given for "end", then the range's upper bound is - * infinity. If the given object is backed by a vnode and it - * transitions from having one or more cached pages to none, the - * vnode's hold count is reduced. - */ -void -vm_page_cache_free(vm_object_t object, vm_pindex_t start, vm_pindex_t end) -{ - vm_page_t m; - boolean_t empty; - - mtx_lock(&vm_page_queue_free_mtx); - if (__predict_false(vm_radix_is_empty(&object->cache))) { - mtx_unlock(&vm_page_queue_free_mtx); - return; - } - while ((m = vm_radix_lookup_ge(&object->cache, start)) != NULL) { - if (end != 0 && m->pindex >= end) - break; - vm_radix_remove(&object->cache, m->pindex); - vm_page_cache_turn_free(m); - } - empty = vm_radix_is_empty(&object->cache); - mtx_unlock(&vm_page_queue_free_mtx); - if (object->type == OBJT_VNODE && empty) - vdrop(object->handle); -} - -/* - * Returns the cached page that is associated with the given - * object and offset. If, however, none exists, returns NULL. - * - * The free page queue must be locked. - */ -static inline vm_page_t -vm_page_cache_lookup(vm_object_t object, vm_pindex_t pindex) -{ - - mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); - return (vm_radix_lookup(&object->cache, pindex)); -} - -/* - * Remove the given cached page from its containing object's - * collection of cached pages. - * - * The free page queue must be locked. - */ -static void -vm_page_cache_remove(vm_page_t m) -{ - - mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); - KASSERT((m->flags & PG_CACHED) != 0, - ("vm_page_cache_remove: page %p is not cached", m)); - vm_radix_remove(&m->object->cache, m->pindex); - m->object = NULL; - vm_cnt.v_cache_count--; -} - -/* - * Transfer all of the cached pages with offset greater than or - * equal to 'offidxstart' from the original object's cache to the - * new object's cache. However, any cached pages with offset - * greater than or equal to the new object's size are kept in the - * original object. Initially, the new object's cache must be - * empty. Offset 'offidxstart' in the original object must - * correspond to offset zero in the new object. - * - * The new object must be locked. - */ -void -vm_page_cache_transfer(vm_object_t orig_object, vm_pindex_t offidxstart, - vm_object_t new_object) -{ - vm_page_t m; - - /* - * Insertion into an object's collection of cached pages - * requires the object to be locked. In contrast, removal does - * not. - */ - VM_OBJECT_ASSERT_WLOCKED(new_object); - KASSERT(vm_radix_is_empty(&new_object->cache), - ("vm_page_cache_transfer: object %p has cached pages", - new_object)); - mtx_lock(&vm_page_queue_free_mtx); - while ((m = vm_radix_lookup_ge(&orig_object->cache, - offidxstart)) != NULL) { - /* - * Transfer all of the pages with offset greater than or - * equal to 'offidxstart' from the original object's - * cache to the new object's cache. - */ - if ((m->pindex - offidxstart) >= new_object->size) - break; - vm_radix_remove(&orig_object->cache, m->pindex); - /* Update the page's object and offset. */ - m->object = new_object; - m->pindex -= offidxstart; - if (vm_radix_insert(&new_object->cache, m)) - vm_page_cache_turn_free(m); - } - mtx_unlock(&vm_page_queue_free_mtx); -} - -/* - * Returns TRUE if a cached page is associated with the given object and - * offset, and FALSE otherwise. - * - * The object must be locked. - */ -boolean_t -vm_page_is_cached(vm_object_t object, vm_pindex_t pindex) -{ - vm_page_t m; - - /* - * Insertion into an object's collection of cached pages requires the - * object to be locked. Therefore, if the object is locked and the - * object's collection is empty, there is no need to acquire the free - * page queues lock in order to prove that the specified page doesn't - * exist. - */ - VM_OBJECT_ASSERT_WLOCKED(object); - if (__predict_true(vm_object_cache_is_empty(object))) - return (FALSE); - mtx_lock(&vm_page_queue_free_mtx); - m = vm_page_cache_lookup(object, pindex); - mtx_unlock(&vm_page_queue_free_mtx); - return (m != NULL); -} - /* * vm_page_alloc: * @@ -1610,9 +1471,6 @@ vm_page_is_cached(vm_object_t object, vm_pindex_t pindex) * optional allocation flags: * VM_ALLOC_COUNT(number) the number of additional pages that the caller * intends to allocate - * VM_ALLOC_IFCACHED return page only if it is cached - * VM_ALLOC_IFNOTCACHED return NULL, do not reactivate if the page - * is cached * VM_ALLOC_NOBUSY do not exclusive busy the page * VM_ALLOC_NODUMP do not include the page in a kernel core dump * VM_ALLOC_NOOBJ page is not associated with an object and @@ -1626,8 +1484,6 @@ vm_page_is_cached(vm_object_t object, vm_pindex_t pindex) vm_page_t vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) { - struct vnode *vp = NULL; - vm_object_t m_object; vm_page_t m, mpred; int flags, req_class; @@ -1670,31 +1526,12 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) * Allocate from the free queue if the number of free pages * exceeds the minimum for the request class. */ - if (object != NULL && - (m = vm_page_cache_lookup(object, pindex)) != NULL) { - if ((req & VM_ALLOC_IFNOTCACHED) != 0) { - mtx_unlock(&vm_page_queue_free_mtx); - return (NULL); - } - if (vm_phys_unfree_page(m)) - vm_phys_set_pool(VM_FREEPOOL_DEFAULT, m, 0); #if VM_NRESERVLEVEL > 0 - else if (!vm_reserv_reactivate_page(m)) -#else - else -#endif - panic("vm_page_alloc: cache page %p is missing" - " from the free queue", m); - } else if ((req & VM_ALLOC_IFCACHED) != 0) { - mtx_unlock(&vm_page_queue_free_mtx); - return (NULL); -#if VM_NRESERVLEVEL > 0 - } else if (object == NULL || (object->flags & (OBJ_COLORED | + if (object == NULL || (object->flags & (OBJ_COLORED | OBJ_FICTITIOUS)) != OBJ_COLORED || (m = - vm_reserv_alloc_page(object, pindex, mpred)) == NULL) { -#else - } else { + vm_reserv_alloc_page(object, pindex, mpred)) == NULL) #endif + { m = vm_phys_alloc_pages(object != NULL ? VM_FREEPOOL_DEFAULT : VM_FREEPOOL_DIRECT, 0); #if VM_NRESERVLEVEL > 0 @@ -1720,33 +1557,9 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) * At this point we had better have found a good page. */ KASSERT(m != NULL, ("vm_page_alloc: missing page")); - KASSERT(m->queue == PQ_NONE, - ("vm_page_alloc: page %p has unexpected queue %d", m, m->queue)); - KASSERT(m->wire_count == 0, ("vm_page_alloc: page %p is wired", m)); - KASSERT(m->hold_count == 0, ("vm_page_alloc: page %p is held", m)); - KASSERT(!vm_page_busied(m), ("vm_page_alloc: page %p is busy", m)); - KASSERT(m->dirty == 0, ("vm_page_alloc: page %p is dirty", m)); - KASSERT(pmap_page_get_memattr(m) == VM_MEMATTR_DEFAULT, - ("vm_page_alloc: page %p has unexpected memattr %d", m, - pmap_page_get_memattr(m))); - if ((m->flags & PG_CACHED) != 0) { - KASSERT((m->flags & PG_ZERO) == 0, - ("vm_page_alloc: cached page %p is PG_ZERO", m)); - KASSERT(m->valid != 0, - ("vm_page_alloc: cached page %p is invalid", m)); - if (m->object != object || m->pindex != pindex) - m->valid = 0; - m_object = m->object; - vm_page_cache_remove(m); - if (m_object->type == OBJT_VNODE && - vm_object_cache_is_empty(m_object)) - vp = m_object->handle; - } else { - KASSERT(m->valid == 0, - ("vm_page_alloc: free page %p is valid", m)); - vm_phys_freecnt_adj(m, -1); - } + vm_phys_freecnt_adj(m, -1); mtx_unlock(&vm_page_queue_free_mtx); + vm_page_alloc_check(m); /* * Initialize the page. Only the PG_ZERO flag is inherited. @@ -1778,9 +1591,6 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) if (object != NULL) { if (vm_page_insert_after(m, object, pindex, mpred)) { - /* See the comment below about hold count. */ - if (vp != NULL) - vdrop(vp); pagedaemon_wakeup(); if (req & VM_ALLOC_WIRED) { atomic_subtract_int(&vm_cnt.v_wire_count, 1); @@ -1800,15 +1610,6 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) } else m->pindex = pindex; - /* - * The following call to vdrop() must come after the above call - * to vm_page_insert() in case both affect the same object and - * vnode. Otherwise, the affected vnode's hold count could - * temporarily become zero. - */ - if (vp != NULL) - vdrop(vp); - /* * Don't wakeup too often - wakeup the pageout daemon when * we would be nearly out of memory. @@ -1819,16 +1620,6 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) return (m); } -static void -vm_page_alloc_contig_vdrop(struct spglist *lst) -{ - - while (!SLIST_EMPTY(lst)) { - vdrop((struct vnode *)SLIST_FIRST(lst)-> plinks.s.pv); - SLIST_REMOVE_HEAD(lst, plinks.s.ss); - } -} - /* * vm_page_alloc_contig: * @@ -1873,8 +1664,6 @@ vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr) { - struct vnode *drop; - struct spglist deferred_vdrop_list; vm_page_t m, m_tmp, m_ret; u_int flags; int req_class; @@ -1900,7 +1689,6 @@ vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req, if (curproc == pageproc && req_class != VM_ALLOC_INTERRUPT) req_class = VM_ALLOC_SYSTEM; - SLIST_INIT(&deferred_vdrop_list); mtx_lock(&vm_page_queue_free_mtx); if (vm_cnt.v_free_count + vm_cnt.v_cache_count >= npages + vm_cnt.v_free_reserved || (req_class == VM_ALLOC_SYSTEM && @@ -1922,17 +1710,7 @@ retry: return (NULL); } if (m_ret != NULL) - for (m = m_ret; m < &m_ret[npages]; m++) { - drop = vm_page_alloc_init(m); - if (drop != NULL) { - /* - * Enqueue the vnode for deferred vdrop(). - */ - m->plinks.s.pv = drop; - SLIST_INSERT_HEAD(&deferred_vdrop_list, m, - plinks.s.ss); - } - } + vm_phys_freecnt_adj(m_ret, -npages); else { #if VM_NRESERVLEVEL > 0 if (vm_reserv_reclaim_contig(npages, low, high, alignment, @@ -1943,6 +1721,8 @@ retry: mtx_unlock(&vm_page_queue_free_mtx); if (m_ret == NULL) return (NULL); + for (m = m_ret; m < &m_ret[npages]; m++) + vm_page_alloc_check(m); /* * Initialize the pages. Only the PG_ZERO flag is inherited. @@ -1975,8 +1755,6 @@ retry: m->oflags = VPO_UNMANAGED; if (object != NULL) { if (vm_page_insert(m, object, pindex)) { - vm_page_alloc_contig_vdrop( - &deferred_vdrop_list); if (vm_paging_needed()) pagedaemon_wakeup(); if ((req & VM_ALLOC_WIRED) != 0) @@ -2001,57 +1779,28 @@ retry: pmap_page_set_memattr(m, memattr); pindex++; } - vm_page_alloc_contig_vdrop(&deferred_vdrop_list); if (vm_paging_needed()) pagedaemon_wakeup(); return (m_ret); } /* - * Initialize a page that has been freshly dequeued from a freelist. - * The caller has to drop the vnode returned, if it is not NULL. - * - * This function may only be used to initialize unmanaged pages. - * - * To be called with vm_page_queue_free_mtx held. + * Check a page that has been freshly dequeued from a freelist. */ -static struct vnode * -vm_page_alloc_init(vm_page_t m) +static void +vm_page_alloc_check(vm_page_t m) { - struct vnode *drop; - vm_object_t m_object; KASSERT(m->queue == PQ_NONE, - ("vm_page_alloc_init: page %p has unexpected queue %d", - m, m->queue)); - KASSERT(m->wire_count == 0, - ("vm_page_alloc_init: page %p is wired", m)); - KASSERT(m->hold_count == 0, - ("vm_page_alloc_init: page %p is held", m)); - KASSERT(!vm_page_busied(m), - ("vm_page_alloc_init: page %p is busy", m)); - KASSERT(m->dirty == 0, - ("vm_page_alloc_init: page %p is dirty", m)); + ("page %p has unexpected queue %d", m, m->queue)); + KASSERT(m->wire_count == 0, ("page %p is wired", m)); + KASSERT(m->hold_count == 0, ("page %p is held", m)); + KASSERT(!vm_page_busied(m), ("page %p is busy", m)); + KASSERT(m->dirty == 0, ("page %p is dirty", m)); KASSERT(pmap_page_get_memattr(m) == VM_MEMATTR_DEFAULT, - ("vm_page_alloc_init: page %p has unexpected memattr %d", + ("page %p has unexpected memattr %d", m, pmap_page_get_memattr(m))); - mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); - drop = NULL; - if ((m->flags & PG_CACHED) != 0) { - KASSERT((m->flags & PG_ZERO) == 0, - ("vm_page_alloc_init: cached page %p is PG_ZERO", m)); - m->valid = 0; - m_object = m->object; - vm_page_cache_remove(m); - if (m_object->type == OBJT_VNODE && - vm_object_cache_is_empty(m_object)) - drop = m_object->handle; - } else { - KASSERT(m->valid == 0, - ("vm_page_alloc_init: free page %p is valid", m)); - vm_phys_freecnt_adj(m, -1); - } - return (drop); + KASSERT(m->valid == 0, ("free page %p is valid", m)); } /* @@ -2077,7 +1826,6 @@ vm_page_alloc_init(vm_page_t m) vm_page_t vm_page_alloc_freelist(int flind, int req) { - struct vnode *drop; vm_page_t m; u_int flags; int req_class; @@ -2111,8 +1859,9 @@ vm_page_alloc_freelist(int flind, int req) mtx_unlock(&vm_page_queue_free_mtx); return (NULL); } - drop = vm_page_alloc_init(m); + vm_phys_freecnt_adj(m, -1); mtx_unlock(&vm_page_queue_free_mtx); + vm_page_alloc_check(m); /* * Initialize the page. Only the PG_ZERO flag is inherited. @@ -2132,8 +1881,6 @@ vm_page_alloc_freelist(int flind, int req) } /* Unmanaged pages don't use "act_count". */ m->oflags = VPO_UNMANAGED; - if (drop != NULL) - vdrop(drop); if (vm_paging_needed()) pagedaemon_wakeup(); return (m); @@ -2259,38 +2006,8 @@ retry: /* Don't care: PG_NODUMP, PG_ZERO. */ if (object->type != OBJT_DEFAULT && object->type != OBJT_SWAP && - object->type != OBJT_VNODE) + object->type != OBJT_VNODE) { run_ext = 0; - else if ((m->flags & PG_CACHED) != 0 || - m != vm_page_lookup(object, m->pindex)) { - /* - * The page is cached or recently converted - * from cached to free. - */ -#if VM_NRESERVLEVEL > 0 - if (level >= 0) { - /* - * The page is reserved. Extend the - * current run by one page. - */ - run_ext = 1; - } else -#endif - if ((order = m->order) < VM_NFREEORDER) { - /* - * The page is enqueued in the - * physical memory allocator's cache/ - * free page queues. Moreover, it is - * the first page in a power-of-two- - * sized run of contiguous cache/free - * pages. Add these pages to the end - * of the current run, and jump - * ahead. - */ - run_ext = 1 << order; - m_inc = 1 << order; - } else - run_ext = 0; #if VM_NRESERVLEVEL > 0 } else if ((options & VPSC_NOSUPER) != 0 && (level = vm_reserv_level_iffullpop(m)) >= 0) { @@ -2457,15 +2174,7 @@ retry: object->type != OBJT_SWAP && object->type != OBJT_VNODE) error = EINVAL; - else if ((m->flags & PG_CACHED) != 0 || - m != vm_page_lookup(object, m->pindex)) { - /* - * The page is cached or recently converted - * from cached to free. - */ - VM_OBJECT_WUNLOCK(object); - goto cached; - } else if (object->memattr != VM_MEMATTR_DEFAULT) + else if (object->memattr != VM_MEMATTR_DEFAULT) error = EINVAL; else if (m->queue != PQ_NONE && !vm_page_busied(m)) { KASSERT(pmap_page_get_memattr(m) == @@ -2566,7 +2275,6 @@ retry: unlock: VM_OBJECT_WUNLOCK(object); } else { -cached: mtx_lock(&vm_page_queue_free_mtx); order = m->order; if (order < VM_NFREEORDER) { @@ -2963,27 +2671,6 @@ vm_page_free_wakeup(void) } } -/* - * Turn a cached page into a free page, by changing its attributes. - * Keep the statistics up-to-date. - * - * The free page queue must be locked. - */ -static void -vm_page_cache_turn_free(vm_page_t m) -{ - - mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); - - m->object = NULL; - m->valid = 0; - KASSERT((m->flags & PG_CACHED) != 0, - ("vm_page_cache_turn_free: page %p is not cached", m)); - m->flags &= ~PG_CACHED; - vm_cnt.v_cache_count--; - vm_phys_freecnt_adj(m, 1); -} - /* * vm_page_free_toq: * @@ -3383,8 +3070,7 @@ retrylookup: VM_WAIT; VM_OBJECT_WLOCK(object); goto retrylookup; - } else if (m->valid != 0) - return (m); + } if (allocflags & VM_ALLOC_ZERO && (m->flags & PG_ZERO) == 0) pmap_zero_page(m); return (m); diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 417d9d87a72..8d44e65c53a 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -326,7 +326,6 @@ extern struct mtx_padalign pa_lock[]; * Page flags. If changed at any other time than page allocation or * freeing, the modification must be protected by the vm_page lock. */ -#define PG_CACHED 0x0001 /* page is cached */ #define PG_FICTITIOUS 0x0004 /* physical page doesn't exist */ #define PG_ZERO 0x0008 /* page is zeroed */ #define PG_MARKER 0x0010 /* special queue marker page */ @@ -409,8 +408,6 @@ vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa); #define VM_ALLOC_ZERO 0x0040 /* (acfg) Try to obtain a zeroed page */ #define VM_ALLOC_NOOBJ 0x0100 /* (acg) No associated object */ #define VM_ALLOC_NOBUSY 0x0200 /* (acg) Do not busy the page */ -#define VM_ALLOC_IFCACHED 0x0400 /* (ag) Fail if page is not cached */ -#define VM_ALLOC_IFNOTCACHED 0x0800 /* (ag) Fail if page is cached */ #define VM_ALLOC_IGN_SBUSY 0x1000 /* (g) Ignore shared busy flag */ #define VM_ALLOC_NODUMP 0x2000 /* (ag) don't include in dump */ #define VM_ALLOC_SBUSY 0x4000 /* (acg) Shared busy the page */ @@ -453,8 +450,6 @@ vm_page_t vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req, vm_paddr_t boundary, vm_memattr_t memattr); vm_page_t vm_page_alloc_freelist(int, int); vm_page_t vm_page_grab (vm_object_t, vm_pindex_t, int); -void vm_page_cache_free(vm_object_t, vm_pindex_t, vm_pindex_t); -void vm_page_cache_transfer(vm_object_t, vm_pindex_t, vm_object_t); int vm_page_try_to_free (vm_page_t); void vm_page_deactivate (vm_page_t); void vm_page_deactivate_noreuse(vm_page_t); @@ -464,7 +459,6 @@ vm_page_t vm_page_find_least(vm_object_t, vm_pindex_t); vm_page_t vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr); void vm_page_initfake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr); int vm_page_insert (vm_page_t, vm_object_t, vm_pindex_t); -boolean_t vm_page_is_cached(vm_object_t object, vm_pindex_t pindex); void vm_page_launder(vm_page_t m); vm_page_t vm_page_lookup (vm_object_t, vm_pindex_t); vm_page_t vm_page_next(vm_page_t m); diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c index 8bb178817e6..5519d2fc1a0 100644 --- a/sys/vm/vm_reserv.c +++ b/sys/vm/vm_reserv.c @@ -907,45 +907,6 @@ vm_reserv_level_iffullpop(vm_page_t m) return (rv->popcnt == VM_LEVEL_0_NPAGES ? 0 : -1); } -/* - * Prepare for the reactivation of a cached page. - * - * First, suppose that the given page "m" was allocated individually, i.e., not - * as part of a reservation, and cached. Then, suppose a reservation - * containing "m" is allocated by the same object. Although "m" and the - * reservation belong to the same object, "m"'s pindex may not match the - * reservation's. - * - * The free page queue must be locked. - */ -boolean_t -vm_reserv_reactivate_page(vm_page_t m) -{ - vm_reserv_t rv; - int index; - - mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); - rv = vm_reserv_from_page(m); - if (rv->object == NULL) - return (FALSE); - KASSERT((m->flags & PG_CACHED) != 0, - ("vm_reserv_reactivate_page: page %p is not cached", m)); - if (m->object == rv->object && - m->pindex - rv->pindex == (index = VM_RESERV_INDEX(m->object, - m->pindex))) - vm_reserv_populate(rv, index); - else { - KASSERT(rv->inpartpopq, - ("vm_reserv_reactivate_page: reserv %p's inpartpopq is FALSE", - rv)); - TAILQ_REMOVE(&vm_rvq_partpop, rv, partpopq); - rv->inpartpopq = FALSE; - /* Don't release "m" to the physical memory allocator. */ - vm_reserv_break(rv, m); - } - return (TRUE); -} - /* * Breaks the given partially-populated reservation, releasing its cached and * free pages to the physical memory allocator. diff --git a/sys/vm/vm_reserv.h b/sys/vm/vm_reserv.h index 52f6ab25477..1a3c0a1d491 100644 --- a/sys/vm/vm_reserv.h +++ b/sys/vm/vm_reserv.h @@ -56,7 +56,6 @@ void vm_reserv_init(void); bool vm_reserv_is_page_free(vm_page_t m); int vm_reserv_level(vm_page_t m); int vm_reserv_level_iffullpop(vm_page_t m); -boolean_t vm_reserv_reactivate_page(vm_page_t m); boolean_t vm_reserv_reclaim_contig(u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary); boolean_t vm_reserv_reclaim_inactive(void); diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 92c28f3098a..b466d32e11a 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -466,10 +466,6 @@ vnode_pager_setsize(struct vnode *vp, vm_ooffset_t nsize) * replacement from working properly. */ vm_page_clear_dirty(m, base, PAGE_SIZE - base); - } else if ((nsize & PAGE_MASK) && - vm_page_is_cached(object, OFF_TO_IDX(nsize))) { - vm_page_cache_free(object, OFF_TO_IDX(nsize), - nobjsize); } } object->un_pager.vnp.vnp_size = nsize; @@ -747,6 +743,9 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count, struct bufobj *bo; struct buf *bp; off_t foff; +#ifdef INVARIANTS + off_t blkno0; +#endif int bsize, pagesperblock, *freecnt; int error, before, after, rbehind, rahead, poff, i; int bytecount, secmask; @@ -847,6 +846,9 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count, return (VM_PAGER_OK); } +#ifdef INVARIANTS + blkno0 = bp->b_blkno; +#endif bp->b_blkno += (foff % bsize) / DEV_BSIZE; /* Recalculate blocks available after/before to pages. */ @@ -868,7 +870,25 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count, rbehind = min(rbehind, m[0]->pindex); rahead = min(rahead, after); rahead = min(rahead, object->size - m[count - 1]->pindex); - KASSERT(rbehind + rahead + count <= sizeof(bp->b_pages), + /* + * Check that total amount of pages fit into buf. Trim rbehind and + * rahead evenly if not. + */ + if (rbehind + rahead + count > nitems(bp->b_pages)) { + int trim, sum; + + trim = rbehind + rahead + count - nitems(bp->b_pages) + 1; + sum = rbehind + rahead; + if (rbehind == before) { + /* Roundup rbehind trim to block size. */ + rbehind -= roundup(trim * rbehind / sum, pagesperblock); + if (rbehind < 0) + rbehind = 0; + } else + rbehind -= trim * rbehind / sum; + rahead -= trim * rahead / sum; + } + KASSERT(rbehind + rahead + count <= nitems(bp->b_pages), ("%s: behind %d ahead %d count %d", __func__, rbehind, rahead, count)); @@ -894,8 +914,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count, for (tpindex = m[0]->pindex - 1; tpindex >= startpindex && tpindex < m[0]->pindex; tpindex--, i++) { - p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL | - VM_ALLOC_IFNOTCACHED); + p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL); if (p == NULL) { /* Shift the array. */ for (int j = 0; j < i; j++) @@ -932,8 +951,7 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count, for (tpindex = m[count - 1]->pindex + 1; tpindex < endpindex; i++, tpindex++) { - p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL | - VM_ALLOC_IFNOTCACHED); + p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL); if (p == NULL) break; bp->b_pages[i] = p; @@ -953,8 +971,14 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count, if (a_rahead) *a_rahead = bp->b_pgafter; +#ifdef INVARIANTS KASSERT(bp->b_npages <= nitems(bp->b_pages), ("%s: buf %p overflowed", __func__, bp)); + for (int j = 1; j < bp->b_npages; j++) + KASSERT(bp->b_pages[j]->pindex - 1 == + bp->b_pages[j - 1]->pindex, + ("%s: pages array not consecutive, bp %p", __func__, bp)); +#endif /* * Recalculate first offset and bytecount with regards to read behind. @@ -993,6 +1017,13 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count, bp->b_vp = vp; bp->b_bcount = bp->b_bufsize = bp->b_runningbufspace = bytecount; bp->b_iooffset = dbtob(bp->b_blkno); + KASSERT(IDX_TO_OFF(m[0]->pindex - bp->b_pages[0]->pindex) == + (blkno0 - bp->b_blkno) * DEV_BSIZE + + IDX_TO_OFF(m[0]->pindex) % bsize, + ("wrong offsets bsize %d m[0] %ju b_pages[0] %ju " + "blkno0 %ju b_blkno %ju", bsize, + (uintmax_t)m[0]->pindex, (uintmax_t)bp->b_pages[0]->pindex, + (uintmax_t)blkno0, (uintmax_t)bp->b_blkno)); atomic_add_long(&runningbufspace, bp->b_runningbufspace); PCPU_INC(cnt.v_vnodein); diff --git a/targets/pseudo/userland/gnu/Makefile.depend b/targets/pseudo/userland/gnu/Makefile.depend index 5c6581b8f2d..cb9bda628cf 100644 --- a/targets/pseudo/userland/gnu/Makefile.depend +++ b/targets/pseudo/userland/gnu/Makefile.depend @@ -111,10 +111,6 @@ DIRDEPS = \ gnu/usr.bin/texinfo/makeinfo \ gnu/usr.bin/texinfo/texindex \ -.if ${MK_ELFCOPY_AS_OBJCOPY} == "no" -DIRDEPS+= gnu/usr.bin/binutils/objcopy -.endif - .if ${MK_GPL_DTC} != "no" DIRDEPS+= gnu/usr.bin/dtc .endif diff --git a/targets/pseudo/userland/misc/Makefile.depend b/targets/pseudo/userland/misc/Makefile.depend index a4091cc1d76..fc2a9ca01be 100644 --- a/targets/pseudo/userland/misc/Makefile.depend +++ b/targets/pseudo/userland/misc/Makefile.depend @@ -58,6 +58,9 @@ DIRDEPS.x86sys+= \ sys/boot/i386/zfsboot \ sys/boot/i386/zfsloader \ +DIRDEPS+= \ + sbin/zfsbootcfg \ + .endif DIRDEPS.amd64= \ @@ -75,6 +78,12 @@ DIRDEPS.amd64+= \ .endif +.if ${MK_EFI} != "no" +DIRDEPS+= \ + usr.sbin/efivar \ + +.endif + DIRDEPS.arm= ${_sys_boot_fdt} ${_sys_boot_efi} DIRDEPS.arm64= ${_sys_boot_fdt} ${_sys_boot_efi} DIRDEPS.i386= ${DIRDEPS.x86sys} ${_sys_boot_efi} diff --git a/tools/sched/make_ktr.sh b/tools/sched/make_ktr.sh new file mode 100755 index 00000000000..44aff7b37b1 --- /dev/null +++ b/tools/sched/make_ktr.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# Copyright (c) 2012 Ryan Stone +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +if [ "$#" -ne 2 ] +then + echo "Usage: make_ktr input output" >&2 + exit 1 +fi + +sort -k 2nrb $1 | cat -n > $2 + diff --git a/tools/sched/schedgraph.d b/tools/sched/schedgraph.d new file mode 100755 index 00000000000..129c50d2532 --- /dev/null +++ b/tools/sched/schedgraph.d @@ -0,0 +1,135 @@ +#!/usr/sbin/dtrace -s + +/*- + * Copyright (c) 2012-2016 Ryan Stone + * 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$ + */ + +/* + * DTrace script for collecting schedgraph data. Run the output + * of this script through make_ktr before feeding it into + * schedgraph.py + * + * e.g. + * # ./schedgraph.d > /tmp/sched.out + * # ./make_ktr.sh /tmp/sched.out /tmp/sched.ktr + * # python schedgraph.py /tmp/sched.ktr 1 + */ + +#pragma D option quiet +#pragma D option bufpolicy=ring + +inline int TDF_IDLETD = 0x00000020; + +/* + * Reasons that the current thread can not be run yet. + * More than one may apply. + */ +inline int TDI_SUSPENDED = 0x0001; /* On suspension queue. */ +inline int TDI_SLEEPING = 0x0002; /* Actually asleep! (tricky). */ +inline int TDI_SWAPPED = 0x0004; /* Stack not in mem. Bad juju if run. */ +inline int TDI_LOCK = 0x0008; /* Stopped on a lock. */ +inline int TDI_IWAIT = 0x0010; /* Awaiting interrupt. */ + +inline string KTDSTATE[struct thread * td] = \ + (((td)->td_inhibitors & TDI_SLEEPING) != 0 ? "sleep" : \ + ((td)->td_inhibitors & TDI_SUSPENDED) != 0 ? "suspended" : \ + ((td)->td_inhibitors & TDI_SWAPPED) != 0 ? "swapped" : \ + ((td)->td_inhibitors & TDI_LOCK) != 0 ? "blocked" : \ + ((td)->td_inhibitors & TDI_IWAIT) != 0 ? "iwait" : "yielding"); + +/* + * NOCPU changed from 255 to -1 at some point. This hacky test will work on a + * kernel compiled with either version. + */ +inline int is_nocpu[int cpu] = cpu < 0 || cpu > `mp_maxid; + +sched:::load-change +/ is_nocpu[args[0]] / +{ + printf("%d %d KTRGRAPH group:\"load\", id:\"global load\", counter:\"%d\", attributes: \"none\"\n", cpu, timestamp, args[1]); +} + +sched:::load-change +/ !is_nocpu[args[0]] / +{ + printf("%d %d KTRGRAPH group:\"load\", id:\"CPU %d load\", counter:\"%d\", attributes: \"none\"\n", cpu, timestamp, args[0], args[1]); + +} + +proc:::exit +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"proc exit\", attributes: prio:td\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid); +} + +proc:::lwp-exit +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"exit\", attributes: prio:td\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid); +} + +sched:::change-pri +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"priority change\", attributes: prio:%d, new prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, arg2, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid); +} + +sched:::lend-pri +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"lend prio\", attributes: prio:%d, new prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, args[0]->td_priority, arg2, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid); +} + +sched:::enqueue +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"runq add\", attributes: prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid); + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"wokeup\", attributes: linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid); +} + +sched:::dequeue +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"runq rem\", attributes: prio:%d, linkedto:\"%s/%s tid %d\"\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid); +} + +sched:::tick +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", point:\"statclock\", attributes: prio:%d, stathz:%d\n", cpu, timestamp, args[0]->td_proc->p_comm, args[0]->td_name, args[0]->td_tid, args[0]->td_priority, `stathz ? `stathz : `hz); +} + +sched:::off-cpu +/ curthread->td_flags & TDF_IDLETD / +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"idle\", attributes: prio:%d\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, curthread->td_priority); +} + +sched:::off-cpu +/ (curthread->td_flags & TDF_IDLETD) == 0 / +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"%s\", attributes: prio:%d, wmesg:\"%s\", lockname:\"%s\"\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, KTDSTATE[curthread], curthread->td_priority, curthread->td_wmesg ? stringof(curthread->td_wmesg) : "(null)", curthread->td_lockname ? stringof(curthread->td_lockname) : "(null)"); +} + +sched:::on-cpu +{ + printf("%d %d KTRGRAPH group:\"thread\", id:\"%s/%s tid %d\", state:\"running\", attributes: prio:%d\n", cpu, timestamp, curthread->td_proc->p_comm, curthread->td_name, curthread->td_tid, curthread->td_priority); +} + diff --git a/tools/tools/git/arcgit b/tools/tools/git/arcgit index 4b98042edd4..60d9abe5859 100755 --- a/tools/tools/git/arcgit +++ b/tools/tools/git/arcgit @@ -69,7 +69,7 @@ create_review() git checkout $commit > /dev/null || error "Could not checkout $commit" - arc_dir="$(git rev-parse --show-toplevel)/.git/arc" + arc_dir="$(git rev-parse --git-dir)/arc" arc_msg="$arc_dir/create-message" mkdir -p $arc_dir git show -s --format='%B' HEAD > $arc_msg diff --git a/tools/tools/git/importgit b/tools/tools/git/importgit index 786930bc524..5149f2d9e15 100755 --- a/tools/tools/git/importgit +++ b/tools/tools/git/importgit @@ -50,7 +50,7 @@ error() exit 1 } -unset git range commit dry_run +unset git_repo range commit dry_run while getopts ":c:g:nr:" o do @@ -95,18 +95,18 @@ then error -u "-g argument is mandatory" fi -git="$git_repo/.git" - -if [ ! -d "$git" ] -then - error "$git_repo does not seem to be a git repo" -fi - if ! type git > /dev/null 2> /dev/null then error "Install devel/git first" fi +GIT="git -C $git_repo" + +if ! $GIT rev-parse --git-dir 2> /dev/null > /dev/null +then + error "$git_repo does not seem to be a git repo" +fi + if ! type svn > /dev/null 2> /dev/null then error "Install devel/subversion first" @@ -122,21 +122,21 @@ then error "Could not communicate with svn server. Is your ssh key loaded?" fi -git --git-dir=$git log --format=%H $range | tail -r | while read -r commit +$GIT log --format=%H $range | tail -r | while read -r commit do - echo "Applying `git --git-dir=$git show -s --oneline $commit`" + echo "Applying `$GIT show -s --oneline $commit`" - if [ -n "$(git --git-dir=$git show --diff-filter=CDRTUXB $commit)" ] + if [ -n "$($GIT show --diff-filter=CDRTUXB $commit)" ] then error "Commit performed unsupported change (e.g. delete/rename)" fi - if [ "$(git --git-dir=$git show -s --format=%P $commit | wc -w)" -ne 1 ] + if [ "$($GIT show -s --format=%P $commit | wc -w)" -ne 1 ] then error "Cannot import merge commits" fi - git --git-dir=$git diff --diff-filter=A --name-only \ + $GIT diff --diff-filter=A --name-only \ ${commit}~..$commit | while read -r newfile do if [ -f "$newfile" ] @@ -158,10 +158,10 @@ do continue fi - git --git-dir=$git show $commit | patch -p 1 -s || \ + $GIT show $commit | patch -p 1 -s || \ error "Failed to apply patch" - git --git-dir=$git diff --diff-filter=A --name-only \ + $GIT diff --diff-filter=A --name-only \ ${commit}~..$commit | while read -r newfile do svn add --parents --depth=infinity $newfile || \ @@ -176,7 +176,7 @@ do exit $ret fi - git --git-dir=$git show -s --format='%B' $commit | svn commit -F - || \ + $GIT show -s --format='%B' $commit | svn commit -F - || \ error "Failed to commit" done diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh index a5984b784f5..362e5aa8d34 100755 --- a/tools/tools/nanobsd/defaults.sh +++ b/tools/tools/nanobsd/defaults.sh @@ -132,10 +132,6 @@ NANO_RAM_ETCSIZE=10240 # Size of the /tmp+/var ramdisk in 512 bytes sectors NANO_RAM_TMPVARSIZE=10240 -# Media geometry, only relevant if bios doesn't understand LBA. -NANO_SECTS=63 -NANO_HEADS=16 - # boot0 flags/options and configuration NANO_BOOT0CFG="-o packet -s 1 -m 3" NANO_BOOTLOADER="boot/boot0sio" @@ -652,173 +648,6 @@ populate_data_slice ( ) ( populate_slice "$1" "$2" "$3" "$4" ) -create_diskimage ( ) ( - pprint 2 "build diskimage" - pprint 3 "log: ${NANO_LOG}/_.di" - - ( - echo $NANO_MEDIASIZE $NANO_IMAGES \ - $NANO_SECTS $NANO_HEADS \ - $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | - awk ' - { - printf "# %s\n", $0 - - # size of cylinder in sectors - cs = $3 * $4 - - # number of full cylinders on media - cyl = int ($1 / cs) - - # output fdisk geometry spec, truncate cyls to 1023 - if (cyl <= 1023) - print "g c" cyl " h" $4 " s" $3 - else - print "g c" 1023 " h" $4 " s" $3 - - if ($7 > 0) { - # size of data partition in full cylinders - dsl = int (($7 + cs - 1) / cs) - } else { - dsl = 0; - } - - # size of config partition in full cylinders - csl = int (($6 + cs - 1) / cs) - - if ($5 == 0) { - # size of image partition(s) in full cylinders - isl = int ((cyl - dsl - csl) / $2) - } else { - isl = int (($5 + cs - 1) / cs) - } - - # First image partition start at second track - print "p 1 165 " $3, isl * cs - $3 - c = isl * cs; - - # Second image partition (if any) also starts offset one - # track to keep them identical. - if ($2 > 1) { - print "p 2 165 " $3 + c, isl * cs - $3 - c += isl * cs; - } - - # Config partition starts at cylinder boundary. - print "p 3 165 " c, csl * cs - c += csl * cs - - # Data partition (if any) starts at cylinder boundary. - if ($7 > 0) { - print "p 4 165 " c, dsl * cs - } else if ($7 < 0 && $1 > c) { - print "p 4 165 " c, $1 - c - } else if ($1 < c) { - print "Disk space overcommitted by", \ - c - $1, "sectors" > "/dev/stderr" - exit 2 - } - - # Force slice 1 to be marked active. This is necessary - # for booting the image from a USB device to work. - print "a 1" - } - ' > ${NANO_LOG}/_.fdisk - - IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} - MNT=${NANO_OBJ}/_.mnt - mkdir -p ${MNT} - - if [ "${NANO_MD_BACKING}" = "swap" ] ; then - MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \ - -y ${NANO_HEADS}` - else - echo "Creating md backing file..." - rm -f ${IMG} - dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0 - MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ - -y ${NANO_HEADS}` - fi - - trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT - - fdisk -i -f ${NANO_LOG}/_.fdisk ${MD} - fdisk ${MD} - # XXX: params - # XXX: pick up cached boot* files, they may not be in image anymore. - if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then - boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD} - fi - if [ -f ${NANO_WORLDDIR}/boot/boot ]; then - bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}${NANO_SLICE_ROOT} - else - bsdlabel -w ${MD}${NANO_SLICE_ROOT} - fi - bsdlabel ${MD}${NANO_SLICE_ROOT} - - # Create first image - populate_slice /dev/${MD}${NANO_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}" - mount /dev/${MD}${NANO_ROOT} ${MNT} - echo "Generating mtree..." - ( cd "${MNT}" && mtree -c ) > ${NANO_LOG}/_.mtree - ( cd "${MNT}" && du -k ) > ${NANO_LOG}/_.du - nano_umount "${MNT}" - - if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then - # Duplicate to second image (if present) - echo "Duplicating to second image..." - dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=/dev/${MD}${NANO_SLICE_ALTROOT} bs=64k - mount /dev/${MD}${NANO_ALTROOT} ${MNT} - for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab - do - sed -i "" "s=${NANO_DRIVE}${NANO_SLICE_ROOT}=${NANO_DRIVE}${NANO_SLICE_ALTROOT}=g" $f - done - nano_umount ${MNT} - # Override the label from the first partition so we - # don't confuse glabel with duplicates. - if [ -n "${NANO_LABEL}" ]; then - tunefs -L ${NANO_LABEL}"${NANO_ALTROOT}" /dev/${MD}${NANO_ALTROOT} - fi - fi - - # Create Config slice - populate_cfg_slice /dev/${MD}${NANO_SLICE_CFG} "${NANO_CFGDIR}" ${MNT} "${NANO_SLICE_CFG}" - - # Create Data slice, if any. - if [ -n "$NANO_SLICE_DATA" -a "$NANO_SLICE_CFG" = "$NANO_SLICE_DATA" -a \ - "$NANO_DATASIZE" -ne 0 ]; then - pprint 2 "NANO_SLICE_DATA is the same as NANO_SLICE_CFG, fix." - exit 2 - fi - if [ $NANO_DATASIZE -ne 0 -a -n "$NANO_SLICE_DATA" ] ; then - populate_data_slice /dev/${MD}${NANO_SLICE_DATA} "${NANO_DATADIR}" ${MNT} "${NANO_SLICE_DATA}" - fi - - if [ "${NANO_MD_BACKING}" = "swap" ] ; then - if [ ${NANO_IMAGE_MBRONLY} ]; then - echo "Writing out _.disk.mbr..." - dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1 - else - echo "Writing out ${NANO_IMGNAME}..." - dd if=/dev/${MD} of=${IMG} bs=64k - fi - - echo "Writing out ${NANO_IMGNAME}..." - dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k - fi - - if ${do_copyout_partition} ; then - echo "Writing out _.disk.image..." - dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=${NANO_DISKIMGDIR}/_.disk.image bs=64k - fi - mdconfig -d -u $MD - - trap - 1 2 15 - trap nano_cleanup EXIT - - ) > ${NANO_LOG}/_.di 2>&1 -) - last_orders ( ) ( # Redefine this function with any last orders you may have # after the build completed, for instance to copy the finished diff --git a/tools/tools/nanobsd/legacy.sh b/tools/tools/nanobsd/legacy.sh new file mode 100644 index 00000000000..f0d79fab2fa --- /dev/null +++ b/tools/tools/nanobsd/legacy.sh @@ -0,0 +1,203 @@ +#!/bin/sh +# +# Copyright (c) 2005 Poul-Henning Kamp. +# Copyright (c) 2016 M. Warner Losh. +# 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$ +# + +# Media geometry, only relevant if bios doesn't understand LBA. +[ -z "$NANO_SECTS" ] || NANO_SECTS=63 +[ -z "$NANO_HEADS" ] || NANO_HEADS=16 + +# Functions and variable definitions used by the legacy nanobsd +# image building system. + +create_diskimage ( ) ( + pprint 2 "build diskimage" + pprint 3 "log: ${NANO_LOG}/_.di" + + ( + echo $NANO_MEDIASIZE $NANO_IMAGES \ + $NANO_SECTS $NANO_HEADS \ + $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | + awk ' + { + printf "# %s\n", $0 + + # size of cylinder in sectors + cs = $3 * $4 + + # number of full cylinders on media + cyl = int ($1 / cs) + + # output fdisk geometry spec, truncate cyls to 1023 + if (cyl <= 1023) + print "g c" cyl " h" $4 " s" $3 + else + print "g c" 1023 " h" $4 " s" $3 + + if ($7 > 0) { + # size of data partition in full cylinders + dsl = int (($7 + cs - 1) / cs) + } else { + dsl = 0; + } + + # size of config partition in full cylinders + csl = int (($6 + cs - 1) / cs) + + if ($5 == 0) { + # size of image partition(s) in full cylinders + isl = int ((cyl - dsl - csl) / $2) + } else { + isl = int (($5 + cs - 1) / cs) + } + + # First image partition start at second track + print "p 1 165 " $3, isl * cs - $3 + c = isl * cs; + + # Second image partition (if any) also starts offset one + # track to keep them identical. + if ($2 > 1) { + print "p 2 165 " $3 + c, isl * cs - $3 + c += isl * cs; + } + + # Config partition starts at cylinder boundary. + print "p 3 165 " c, csl * cs + c += csl * cs + + # Data partition (if any) starts at cylinder boundary. + if ($7 > 0) { + print "p 4 165 " c, dsl * cs + } else if ($7 < 0 && $1 > c) { + print "p 4 165 " c, $1 - c + } else if ($1 < c) { + print "Disk space overcommitted by", \ + c - $1, "sectors" > "/dev/stderr" + exit 2 + } + + # Force slice 1 to be marked active. This is necessary + # for booting the image from a USB device to work. + print "a 1" + } + ' > ${NANO_LOG}/_.fdisk + + IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} + MNT=${NANO_OBJ}/_.mnt + mkdir -p ${MNT} + + if [ "${NANO_MD_BACKING}" = "swap" ] ; then + MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \ + -y ${NANO_HEADS}` + else + echo "Creating md backing file..." + rm -f ${IMG} + dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0 + MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ + -y ${NANO_HEADS}` + fi + + trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT + + fdisk -i -f ${NANO_LOG}/_.fdisk ${MD} + fdisk ${MD} + # XXX: params + # XXX: pick up cached boot* files, they may not be in image anymore. + if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then + boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD} + fi + if [ -f ${NANO_WORLDDIR}/boot/boot ]; then + bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}${NANO_SLICE_ROOT} + else + bsdlabel -w ${MD}${NANO_SLICE_ROOT} + fi + bsdlabel ${MD}${NANO_SLICE_ROOT} + + # Create first image + populate_slice /dev/${MD}${NANO_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}" + mount /dev/${MD}${NANO_ROOT} ${MNT} + echo "Generating mtree..." + ( cd "${MNT}" && mtree -c ) > ${NANO_LOG}/_.mtree + ( cd "${MNT}" && du -k ) > ${NANO_LOG}/_.du + nano_umount "${MNT}" + + if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then + # Duplicate to second image (if present) + echo "Duplicating to second image..." + dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=/dev/${MD}${NANO_SLICE_ALTROOT} bs=64k + mount /dev/${MD}${NANO_ALTROOT} ${MNT} + for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab + do + sed -i "" "s=${NANO_DRIVE}${NANO_SLICE_ROOT}=${NANO_DRIVE}${NANO_SLICE_ALTROOT}=g" $f + done + nano_umount ${MNT} + # Override the label from the first partition so we + # don't confuse glabel with duplicates. + if [ -n "${NANO_LABEL}" ]; then + tunefs -L ${NANO_LABEL}"${NANO_ALTROOT}" /dev/${MD}${NANO_ALTROOT} + fi + fi + + # Create Config slice + populate_cfg_slice /dev/${MD}${NANO_SLICE_CFG} "${NANO_CFGDIR}" ${MNT} "${NANO_SLICE_CFG}" + + # Create Data slice, if any. + if [ -n "$NANO_SLICE_DATA" -a "$NANO_SLICE_CFG" = "$NANO_SLICE_DATA" -a \ + "$NANO_DATASIZE" -ne 0 ]; then + pprint 2 "NANO_SLICE_DATA is the same as NANO_SLICE_CFG, fix." + exit 2 + fi + if [ $NANO_DATASIZE -ne 0 -a -n "$NANO_SLICE_DATA" ] ; then + populate_data_slice /dev/${MD}${NANO_SLICE_DATA} "${NANO_DATADIR}" ${MNT} "${NANO_SLICE_DATA}" + fi + + if [ "${NANO_MD_BACKING}" = "swap" ] ; then + if [ ${NANO_IMAGE_MBRONLY} ]; then + echo "Writing out _.disk.mbr..." + dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1 + else + echo "Writing out ${NANO_IMGNAME}..." + dd if=/dev/${MD} of=${IMG} bs=64k + fi + + echo "Writing out ${NANO_IMGNAME}..." + dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k + fi + + if ${do_copyout_partition} ; then + echo "Writing out _.disk.image..." + dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=${NANO_DISKIMGDIR}/_.disk.image bs=64k + fi + mdconfig -d -u $MD + + trap - 1 2 15 + trap nano_cleanup EXIT + + ) > ${NANO_LOG}/_.di 2>&1 +) diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh index 02c84cd1afb..918dd6b5015 100755 --- a/tools/tools/nanobsd/nanobsd.sh +++ b/tools/tools/nanobsd/nanobsd.sh @@ -40,12 +40,16 @@ do_clean=true do_kernel=true do_installkernel=true do_world=true +do_installworld=true do_image=true do_copyout_partition=true do_native_xtools=false +# Don't do the legacy build unless we detect 'old' variables being +# set. +do_legacy=false set +e -args=`getopt KXbc:fhiknqvw $*` +args=`getopt BKXWbc:fhiknqvw $*` if [ $? -ne 0 ] ; then usage exit 2 @@ -57,6 +61,11 @@ for i do case "$i" in + -B) + do_installworld=false + do_installkernel=false + shift + ;; -K) do_installkernel=false shift @@ -65,6 +74,10 @@ do do_native_xtools=true shift ;; + -W) + do_installworld=false + shift + ;; -b) do_world=false do_kernel=false @@ -121,6 +134,15 @@ if [ $# -gt 0 ] ; then usage fi +if [ -n "$NANO_HEADS" -o -n "$NANO_SECTS" ]; then + do_legacy=true +fi + +# If this uses the old, legacy image system, pull that in as well +if $do_legacy ; then + . "${topdir}/legacy.sh" +fi + ####################################################################### # And then it is as simple as that... @@ -162,10 +184,15 @@ else pprint 2 "Skipping buildkernel (as instructed)" fi -clean_world -make_conf_install -install_world -install_etc +if $do_installworld ; then + clean_world + make_conf_install + install_world + install_etc +else + pprint 2 "Skipping installworld (as instructed)" +fi + if $do_native_xtools ; then native_xtools fi diff --git a/tools/tools/nanobsd/pcengines/common.conf b/tools/tools/nanobsd/pcengines/common.conf index 687fd74eec9..c23293d8fd8 100644 --- a/tools/tools/nanobsd/pcengines/common.conf +++ b/tools/tools/nanobsd/pcengines/common.conf @@ -21,7 +21,7 @@ NO_CLEAN=YES # Options to put in make.conf during installworld only CONF_INSTALL=' ' -# Options to put in make.conf during both build- & installworld. +# Options to put in make.conf during both build- & installworld. CONF_WORLD=' CFLAGS=-O -pipe WITHOUT_ACPI= diff --git a/usr.bin/basename/Makefile.depend b/usr.bin/basename/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/basename/Makefile.depend +++ b/usr.bin/basename/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/cmp/Makefile.depend b/usr.bin/cmp/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/cmp/Makefile.depend +++ b/usr.bin/cmp/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/col/Makefile.depend b/usr.bin/col/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/col/Makefile.depend +++ b/usr.bin/col/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/dc/Makefile.depend b/usr.bin/dc/Makefile.depend index 9d5105e918d..7e1b62db9b9 100644 --- a/usr.bin/dc/Makefile.depend +++ b/usr.bin/dc/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ secure/lib/libcrypto \ secure/lib/libssl \ diff --git a/usr.bin/dirname/Makefile.depend b/usr.bin/dirname/Makefile.depend index 9cb890b5836..4def626103c 100644 --- a/usr.bin/dirname/Makefile.depend +++ b/usr.bin/dirname/Makefile.depend @@ -5,8 +5,10 @@ DIRDEPS = \ gnu/lib/csu \ gnu/lib/libgcc \ include \ + include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/elfdump/Makefile.depend b/usr.bin/elfdump/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/elfdump/Makefile.depend +++ b/usr.bin/elfdump/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/fold/Makefile.depend b/usr.bin/fold/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/fold/Makefile.depend +++ b/usr.bin/fold/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/fold/fold.c b/usr.bin/fold/fold.c index 7eedfe252c0..1ce9b5eb3a9 100644 --- a/usr.bin/fold/fold.c +++ b/usr.bin/fold/fold.c @@ -45,7 +45,6 @@ static char sccsid[] = "@(#)fold.c 8.1 (Berkeley) 6/6/93"; #include __FBSDID("$FreeBSD$"); -#include #include #include #include @@ -73,9 +72,6 @@ main(int argc, char **argv) (void) setlocale(LC_CTYPE, ""); - if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS)) - err(1, "capsicum"); - width = -1; previous_ch = 0; while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) { diff --git a/usr.bin/gcore/gcore.c b/usr.bin/gcore/gcore.c index 3d4c5052eb7..6932cc3c666 100644 --- a/usr.bin/gcore/gcore.c +++ b/usr.bin/gcore/gcore.c @@ -143,21 +143,6 @@ main(int argc, char *argv[]) fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE); if (fd < 0) err(1, "%s", corefile); - /* - * The semantics of the 's' flag is to stop the target process. - * Previous versions of gcore would manage this by trapping SIGHUP, - * SIGINT and SIGTERM (to be passed to the target pid), and then - * signal the child to stop. - * - * However, this messes up if the selected dumper uses ptrace calls - * that leave the child already stopped. The waitpid call in elfcore - * never returns. - * - * The best thing to do here is to externalize the 's' flag and let - * each dumper dispose of what that means, if anything. For the elfcore - * dumper, the 's' flag is a no-op since the ptrace attach stops the - * process in question already. - */ dumper->dump(efd, fd, pid); (void)close(fd); @@ -169,6 +154,6 @@ void usage(void) { - (void)fprintf(stderr, "usage: gcore [-s] [-c core] [executable] pid\n"); + (void)fprintf(stderr, "usage: gcore [-c core] [executable] pid\n"); exit(1); } diff --git a/usr.bin/getopt/Makefile.depend b/usr.bin/getopt/Makefile.depend index 9cb890b5836..4def626103c 100644 --- a/usr.bin/getopt/Makefile.depend +++ b/usr.bin/getopt/Makefile.depend @@ -5,8 +5,10 @@ DIRDEPS = \ gnu/lib/csu \ gnu/lib/libgcc \ include \ + include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/jot/Makefile.depend b/usr.bin/jot/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/jot/Makefile.depend +++ b/usr.bin/jot/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/kdump/Makefile.depend b/usr.bin/kdump/Makefile.depend index 71c82136392..59ec51a9b1d 100644 --- a/usr.bin/kdump/Makefile.depend +++ b/usr.bin/kdump/Makefile.depend @@ -9,6 +9,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcasper/libcasper \ lib/libcasper/services/cap_grp \ lib/libcasper/services/cap_pwd \ diff --git a/usr.bin/locale/locale.c b/usr.bin/locale/locale.c index b295b176c88..2c3e61eb529 100644 --- a/usr.bin/locale/locale.c +++ b/usr.bin/locale/locale.c @@ -50,6 +50,7 @@ #include "setlocale.h" /* Local prototypes */ +char *format_grouping(const char *); void init_locales_list(void); void list_charmaps(void); void list_locales(void); @@ -283,8 +284,9 @@ main(int argc, char *argv[]) /* process '-c', '-k', or command line arguments. */ if (prt_categories || prt_keywords || argc > 0) { - if (argc > 0) { + if (prt_keywords || argc > 0) setlocale(LC_ALL, ""); + if (argc > 0) { while (argc > 0) { showdetails(*argv); argv++; @@ -487,6 +489,34 @@ showlocale(void) printf("LC_ALL=%s\n", vval); } +char * +format_grouping(const char *binary) +{ + static char rval[64]; + const char *cp; + size_t len; + + rval[0] = '\0'; + for (cp = binary; *cp != '\0'; ++cp) { + char group[sizeof("127;")]; + snprintf(group, sizeof(group), "%hhd;", *cp); + len = strlcat(rval, group, sizeof(rval)); + if (len >= sizeof(rval)) { + len = sizeof(rval) - 1; + break; + } + if (*cp == CHAR_MAX) { + break; + } + } + + /* Remove the trailing ';'. */ + rval[len - 1] = '\0'; + + return (rval); +} + + /* * keyword value lookup helper (via localeconv()) */ @@ -500,7 +530,7 @@ kwval_lconv(int id) lc = localeconv(); switch (id) { case KW_GROUPING: - rval = lc->grouping; + rval = format_grouping(lc->grouping); break; case KW_INT_CURR_SYMBOL: rval = lc->int_curr_symbol; @@ -515,7 +545,7 @@ kwval_lconv(int id) rval = lc->mon_thousands_sep; break; case KW_MON_GROUPING: - rval = lc->mon_grouping; + rval = format_grouping(lc->mon_grouping); break; case KW_POSITIVE_SIGN: rval = lc->positive_sign; diff --git a/usr.bin/locate/bigram/Makefile.depend b/usr.bin/locate/bigram/Makefile.depend index 9cb890b5836..4def626103c 100644 --- a/usr.bin/locate/bigram/Makefile.depend +++ b/usr.bin/locate/bigram/Makefile.depend @@ -5,8 +5,10 @@ DIRDEPS = \ gnu/lib/csu \ gnu/lib/libgcc \ include \ + include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/logname/Makefile.depend b/usr.bin/logname/Makefile.depend index 9cb890b5836..4def626103c 100644 --- a/usr.bin/logname/Makefile.depend +++ b/usr.bin/logname/Makefile.depend @@ -5,8 +5,10 @@ DIRDEPS = \ gnu/lib/csu \ gnu/lib/libgcc \ include \ + include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/netstat/mbuf.c b/usr.bin/netstat/mbuf.c index 8b95ddddd04..c1d0dd35376 100644 --- a/usr.bin/netstat/mbuf.c +++ b/usr.bin/netstat/mbuf.c @@ -340,6 +340,9 @@ mbpr(void *kvmd, u_long mbaddr) xo_emit("{:sendfile-pages-valid/%ju} " "{N:pages were valid at time of a sendfile request}\n", (uintmax_t)sfstat.sf_pages_valid); + xo_emit("{:sendfile-pages-bogus/%ju} " + "{N:pages were valid and substituted to bogus page}\n", + (uintmax_t)sfstat.sf_pages_bogus); xo_emit("{:sendfile-requested-readahead/%ju} " "{N:pages were requested for read ahead by applications}\n", (uintmax_t)sfstat.sf_rhpages_requested); diff --git a/usr.bin/printenv/Makefile.depend b/usr.bin/printenv/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/printenv/Makefile.depend +++ b/usr.bin/printenv/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/tee/Makefile.depend b/usr.bin/tee/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/tee/Makefile.depend +++ b/usr.bin/tee/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/tr/Makefile.depend b/usr.bin/tr/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/tr/Makefile.depend +++ b/usr.bin/tr/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index 14fad8ca392..40c6f54451b 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -1085,8 +1085,6 @@ dosum(void) sum.v_vforkpages); xo_emit("{:pages-rfork/%9u} {N:pages affected by rfork}()\n", sum.v_rforkpages); - xo_emit("{:pages-total-cached/%9u} {N:pages cached}\n", - sum.v_tcached); xo_emit("{:pages-freed/%9u} {N:pages freed}\n", sum.v_tfree); xo_emit("{:pages-freed-by-daemon/%9u} {N:pages freed by daemon}\n", diff --git a/usr.bin/whois/whois.c b/usr.bin/whois/whois.c index 4f4062b7c7f..de3b946def4 100644 --- a/usr.bin/whois/whois.c +++ b/usr.bin/whois/whois.c @@ -119,12 +119,38 @@ static struct { { NULL, 0 } }; +/* + * We have a list of patterns for RIRs that assert ignorance rather than + * providing referrals. If that happens, we guess that ARIN will be more + * helpful. But, before following a referral to an RIR, we check if we have + * asked that RIR already, and if so we make another guess. + */ static const char *actually_arin[] = { "netname: ERX-NETBLOCK\n", /* APNIC */ "netname: NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK\n", NULL }; +static struct { + int loop; + const char *host; +} try_rir[] = { + { 0, ANICHOST }, + { 0, RNICHOST }, + { 0, PNICHOST }, + { 0, FNICHOST }, + { 0, LNICHOST }, + { 0, NULL } +}; + +static void +reset_rir(void) { + int i; + + for (i = 0; try_rir[i].host != NULL; i++) + try_rir[i].loop = 0; +} + static const char *port = DEFAULT_PORT; static const char *choose_server(char *); @@ -232,6 +258,7 @@ main(int argc, char *argv[]) } else whois(*argv, host != NULL ? host : choose_server(*argv), flags); + reset_rir(); argv++; } exit(0); @@ -420,7 +447,7 @@ whois(const char *query, const char *hostname, int flags) FILE *fp; struct addrinfo *hostres; char *buf, *host, *nhost, *p; - int s, f; + int comment, s, f; size_t len, i; hostres = gethostinfo(hostname, 1); @@ -467,12 +494,28 @@ whois(const char *query, const char *hostname, int flags) fprintf(fp, "%s\r\n", query); fflush(fp); + comment = 0; + if (!(flags & WHOIS_SPAM_ME) && + (strcasecmp(hostname, ANICHOST) == 0 || + strcasecmp(hostname, RNICHOST) == 0)) { + comment = 2; + } + nhost = NULL; while ((buf = fgetln(fp, &len)) != NULL) { /* Nominet */ if (!(flags & WHOIS_SPAM_ME) && len == 5 && strncmp(buf, "-- \r\n", 5) == 0) break; + /* RIRs */ + if (comment == 1 && buf[0] == '#') + break; + else if (comment == 2) { + if (strchr("#%\r\n", buf[0]) != NULL) + continue; + else + comment = 1; + } printf("%.*s", (int)len, buf); @@ -487,8 +530,7 @@ whois(const char *query, const char *hostname, int flags) SCAN(p, buf+len, *p == ' '); host = p; SCAN(p, buf+len, ishost(*p)); - /* avoid loops */ - if (strncmp(hostname, host, p - host) != 0) + if (p > host) s_asprintf(&nhost, "%.*s", (int)(p - host), host); break; @@ -511,8 +553,37 @@ whois(const char *query, const char *hostname, int flags) } fclose(fp); freeaddrinfo(hostres); + + f = 0; + for (i = 0; try_rir[i].host != NULL; i++) { + /* Remember visits to RIRs */ + if (try_rir[i].loop == 0 && + strcasecmp(try_rir[i].host, hostname) == 0) + try_rir[i].loop = 1; + /* Do we need to find an alternative RIR? */ + if (try_rir[i].loop != 0 && nhost != NULL && + strcasecmp(try_rir[i].host, nhost) == 0) { + free(nhost); + nhost = NULL; + f = 1; + } + } + if (f) { + /* Find a replacement RIR */ + for (i = 0; try_rir[i].host != NULL; i++) { + if (try_rir[i].loop == 0) { + s_asprintf(&nhost, "%s", + try_rir[i].host); + break; + } + } + } if (nhost != NULL) { - whois(query, nhost, flags); + /* Ignore self-referrals */ + if (strcasecmp(hostname, nhost) != 0) { + printf("# %s\n\n", nhost); + whois(query, nhost, flags); + } free(nhost); } } diff --git a/usr.bin/write/Makefile.depend b/usr.bin/write/Makefile.depend index 3646e2e2b1a..4def626103c 100644 --- a/usr.bin/write/Makefile.depend +++ b/usr.bin/write/Makefile.depend @@ -8,6 +8,7 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.bin/yes/Makefile.depend b/usr.bin/yes/Makefile.depend index 9cb890b5836..4def626103c 100644 --- a/usr.bin/yes/Makefile.depend +++ b/usr.bin/yes/Makefile.depend @@ -5,8 +5,10 @@ DIRDEPS = \ gnu/lib/csu \ gnu/lib/libgcc \ include \ + include/xlocale \ lib/${CSU_DIR} \ lib/libc \ + lib/libcapsicum \ lib/libcompiler_rt \ diff --git a/usr.sbin/amd/amd/Makefile b/usr.sbin/amd/amd/Makefile index 8f14259fca5..aebd3f17cd0 100644 --- a/usr.sbin/amd/amd/Makefile +++ b/usr.sbin/amd/amd/Makefile @@ -12,27 +12,51 @@ PROG= amd MAN= amd.8 -SRCS= conf_parse.y conf_tok.l -SRCS+= am_ops.c amd.c amfs_auto.c amfs_direct.c amfs_error.c amfs_generic.c +SRCS= am_ops.c amd.c amfs_auto.c amfs_direct.c amfs_error.c amfs_generic.c SRCS+= amfs_host.c amfs_link.c amfs_linkx.c amfs_nfsl.c SRCS+= amfs_nfsx.c amfs_program.c amfs_root.c amfs_toplvl.c SRCS+= amfs_union.c amq_subr.c amq_svc.c autil.c clock.c conf.c SRCS+= get_args.c info_exec.c info_file.c info_ndbm.c info_passwd.c +SRCS+= info_sun.c SRCS+= info_union.c map.c mapc.c mntfs.c nfs_prot_svc.c nfs_start.c -SRCS+= nfs_subr.c ops_cdfs.c ops_mfs.c ops_nfs.c ops_nfs3.c -SRCS+= ops_nullfs.c ops_pcfs.c ops_tfs.c ops_ufs.c ops_umapfs.c +SRCS+= nfs_subr.c ops_cdfs.c ops_lustre.c ops_mfs.c ops_nfs.c +SRCS+= ops_nfs3.c ops_nfs4.c +SRCS+= ops_nullfs.c ops_pcfs.c ops_tfs.c ops_tmpfs.c ops_udf.c ops_ufs.c +SRCS+= ops_umapfs.c SRCS+= ops_unionfs.c opts.c readdir.c restart.c rpc_fwd.c sched.c -SRCS+= srvr_amfs_auto.c srvr_nfs.c +SRCS+= srvr_amfs_auto.c srvr_nfs.c sun_map.c CFLAGS+= -I${SRCTOP}/contrib/amd/amd \ + -I${SRCTOP}/contrib/amd/include \ -I${.OBJDIR}/../../../include/rpcsvc LIBADD= amu wrap +SRCS+= conf_parse.c conf_parse.h conf_tok.c +SRCS+= sun_map_parse.c sun_map_parse.h sun_map_tok.c CLEANFILES+= conf_parse.c conf_parse.h conf_tok.c +CLEANFILES+= sun_map_parse.c sun_map_parse.h sun_map_tok.c + +conf_tok.c: conf_tok.l + ${LEX} ${LFLAGS} -Pconf_ -o${.TARGET} ${.ALLSRC} + +.ORDER: conf_parse.c conf_parse.h +conf_parse.h: .NOMETA +conf_parse.c conf_parse.h: conf_parse.y + ${YACC} ${YFLAGS} -pconf_ -oconf_parse.c ${.ALLSRC} + +sun_map_tok.c: sun_map_tok.l + ${LEX} ${LFLAGS} -Psun_map_ -o${.TARGET} ${.ALLSRC} + +.ORDER: sun_map_parse.c sun_map_parse.h +sun_map_parse.h: .NOMETA +sun_map_parse.c sun_map_parse.h: sun_map_parse.y + ${YACC} ${YFLAGS} -psun_map_ -osun_map_parse.c ${.ALLSRC} conf_tok.o: conf_parse.h +sun_map_tok.o: sun_map_parse.h + # These are generated at compile time SRCS+= mount_xdr.c CLEANFILES+= mount_xdr.c diff --git a/usr.sbin/amd/fsinfo/Makefile b/usr.sbin/amd/fsinfo/Makefile index a3f4ce2a3fa..4890f5c09c2 100644 --- a/usr.sbin/amd/fsinfo/Makefile +++ b/usr.sbin/amd/fsinfo/Makefile @@ -9,16 +9,37 @@ PROG= fsinfo MAN= fsinfo.8 -SRCS= fsi_gram.y fsi_lex.l -SRCS+= fsi_analyze.c fsi_dict.c fsi_util.c fsinfo.c wr_atab.c -SRCS+= wr_bparam.c wr_dumpset.c wr_exportfs.c wr_fstab.c +SRCS= fsi_analyze.c fsi_dict.c fsi_util.c fsinfo.c +SRCS+= wr_atab.c wr_bparam.c wr_dumpset.c wr_exportfs.c wr_fstab.c -CFLAGS+= -I${SRCTOP}/contrib/amd/fsinfo +CFLAGS+= -I${SRCTOP}/contrib/amd/fsinfo \ + -I${SRCTOP}/contrib/amd/inculde LIBADD= amu +SRCS+= fsi_gram.c fsi_gram.h fsi_lex.c +SRCS+= null_gram.c null_gram.h null_lex.c CLEANFILES+= fsi_gram.c fsi_gram.h fsi_lex.c +CLEANFILES+= null_gram.c null_gram.h null_lex.c + +fsi_lex.c: fsi_lex.l + ${LEX} ${LFLAGS} -Pfsi_ -o${.TARGET} ${.ALLSRC} + +.ORDER: fsi_gram.c fsi_gram.h +fsi_gram.h: .NOMETA +fsi_gram.c fsi_gram.h: fsi_gram.y + ${YACC} ${YFLAGS} -pfsi_ -ofsi_gram.c ${.ALLSRC} + +null_lex.c: null_lex.l + ${LEX} ${LFLAGS} -Pnull_ -o${.TARGET} ${.ALLSRC} + +.ORDER: null_gram.c null_gram.h +null_gram.h: .NOMETA +null_gram.c null_gram.h: null_gram.y + ${YACC} ${YFLAGS} -pnull_ -onull_gram.c ${.ALLSRC} fsi_lex.o: fsi_gram.h +null_gram.o: null_gram.h + .include diff --git a/usr.sbin/amd/include/config.h b/usr.sbin/amd/include/config.h index cffb82ad71f..58b822edc92 100644 --- a/usr.sbin/amd/include/config.h +++ b/usr.sbin/amd/include/config.h @@ -3,6 +3,9 @@ * * portions derived from * $NetBSD: config.h,v 1.11 1998/08/08 22:33:37 christos Exp $ + * + * Additional portions derived from ports/sysutils/am-utils r416941 + * make configure config.h output. */ #ifndef _CONFIG_H @@ -11,6 +14,9 @@ /* We [FREEBSD-NATIVE] pick some parameters from our local config file */ #include "config_local.h" +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + /* define name of am-utils' NFS protocol header */ #define AMU_NFS_PROTOCOL_HEADER "./conf/nfs_prot/nfs_prot_freebsd3.h" @@ -18,7 +24,7 @@ #define AUTH_CREATE_GIDLIST_TYPE gid_t /* Define configuration date */ -/* #define CONFIG_DATE "Tue Dec 4 21:39:00 PST 2007" */ +/* #define CONFIG_DATE "Mon Oct 3 21:58:39 PDT 2016" */ /* Turn off general debugging by default */ /* #undef DEBUG */ @@ -176,9 +182,15 @@ /* Define to 1 if `flags' is member of `efs_args_t'. */ /* #undef HAVE_EFS_ARGS_T_FLAGS */ +/* Define to 1 if `version' is member of `efs_args_t'. */ +/* #undef HAVE_EFS_ARGS_T_VERSION */ + /* Define to 1 if `fspec' is member of `efs_args_t'. */ /* #undef HAVE_EFS_ARGS_T_FSPEC */ +/* Define to 1 if `version' is member of `efs_args_t'. */ +/* #undef HAVE_EFS_ARGS_T_VERSION */ + /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 @@ -320,6 +332,12 @@ /* Define if have EFS filesystem (irix) */ /* #undef HAVE_FS_EFS */ +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FS_EFS_EFS_MOUNT_H */ + +/* Define if have EXT{2,3,4} filesystem (linux) */ +/* #undef HAVE_FS_EXT */ + /* Define if have FFS filesystem */ /* #undef HAVE_FS_FFS */ @@ -329,8 +347,14 @@ /* Define if have LOFS filesystem */ /* #undef HAVE_FS_LOFS */ +/* Define if have LUSTRE filesystem */ +/* #undef HAVE_FS_LUSTRE */ + /* Define if have MFS filesystem */ -/* #undef HAVE_FS_MFS */ +#define HAVE_FS_MFS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */ /* Define if have NFS filesystem */ #define HAVE_FS_NFS 1 @@ -338,6 +362,9 @@ /* Define if have NFS3 filesystem */ #define HAVE_FS_NFS3 1 +/* Define if have NFS4 filesystem */ +/* #undef HAVE_FS_NFS4 */ + /* Define if have NULLFS (loopback on bsd44) filesystem */ #define HAVE_FS_NULLFS 1 @@ -348,7 +375,16 @@ /* #undef HAVE_FS_TFS */ /* Define if have TMPFS filesystem */ -/* #undef HAVE_FS_TMPFS */ +#define HAVE_FS_TMPFS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FS_TMPFS_TMPFS_ARGS_H */ + +/* Define if have UDF filesystem */ +#define HAVE_FS_UDF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FS_UDF_UDF_MOUNT_H 1 /* Define if have UFS filesystem */ #define HAVE_FS_UFS 1 @@ -520,6 +556,9 @@ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_NFS2_H */ +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_NFS4_H */ + /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_NFS_H */ @@ -575,6 +614,9 @@ /* Define if have PASSWD maps */ #define HAVE_MAP_PASSWD 1 +/* Define if have Sun-syntax maps */ +#define HAVE_MAP_SUN 1 + /* Define if have UNION maps */ #define HAVE_MAP_UNION 1 @@ -668,6 +710,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_NET_IF_H 1 +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NET_IF_VAR_H */ + /* Define to 1 if you have the header file. */ #define HAVE_NET_ROUTE_H 1 @@ -692,6 +737,9 @@ /* Define to 1 if `bsize' is member of `nfs_args_t'. */ /* #undef HAVE_NFS_ARGS_T_BSIZE */ +/* Define to 1 if `context' is member of `nfs_args_t'. */ +/* #undef HAVE_NFS_ARGS_T_CONTEXT */ + /* Define to 1 if `fhsize' is member of `nfs_args_t'. */ #define HAVE_NFS_ARGS_T_FHSIZE 1 @@ -707,9 +755,15 @@ /* Define to 1 if `optstr' is member of `nfs_args_t'. */ /* #undef HAVE_NFS_ARGS_T_OPTSTR */ +/* Define to 1 if `pathconf' is member of `nfs_args_t'. */ +/* #undef HAVE_NFS_ARGS_T_PATHCONF */ + /* Define to 1 if `proto' is member of `nfs_args_t'. */ #define HAVE_NFS_ARGS_T_PROTO 1 +/* Define to 1 if `pseudoflavor' is member of `nfs_args_t'. */ +/* #undef HAVE_NFS_ARGS_T_PSEUDOFLAVOR */ + /* Define to 1 if `sotype' is member of `nfs_args_t'. */ #define HAVE_NFS_ARGS_T_SOTYPE 1 @@ -760,6 +814,7 @@ /* Define to 1 if you have the `opendir' function. */ #define HAVE_OPENDIR 1 + /* Define to 1 if `dsttime' is member of `pcfs_args_t'. */ /* #undef HAVE_PCFS_ARGS_T_DSTTIME */ @@ -830,6 +885,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_RPC_AUTH_DES_H 1 +/* Define to 1 if you have the header file. */ +#define HAVE_RPC_AUTH_H 1 + /* Define to 1 if you have the header file. */ #define HAVE_RPC_PMAP_CLNT_H 1 @@ -1157,6 +1215,24 @@ /* Define to 1 if you have the header file. */ /* #undef HAVE_TIUSER_H */ +/* Define to 1 if `ta_nodes_max' is member of `tmpfs_args_t'. */ +/* #undef HAVE_TMPFS_ARGS_T_TA_NODES_MAX */ + +/* Define to 1 if `ta_root_gid' is member of `tmpfs_args_t'. */ +/* #undef HAVE_TMPFS_ARGS_T_TA_ROOT_GID */ + +/* Define to 1 if `ta_root_mode' is member of `tmpfs_args_t'. */ +/* #undef HAVE_TMPFS_ARGS_T_TA_ROOT_MODE */ + +/* Define to 1 if `ta_root_uid' is member of `tmpfs_args_t'. */ +/* #undef HAVE_TMPFS_ARGS_T_TA_ROOT_UID */ + +/* Define to 1 if `ta_size_max' is member of `tmpfs_args_t'. */ +/* #undef HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */ + +/* Define to 1 if `ta_version' is member of `tmpfs_args_t'. */ +/* #undef HAVE_TMPFS_ARGS_T_TA_VERSION */ + /* Define to 1 if you have the header file. */ /* #undef HAVE_TMPFS_TMP_H */ @@ -1166,6 +1242,36 @@ /* Define to 1 if you have the `ualarm' function. */ #define HAVE_UALARM 1 +/* Define to 1 if `anon_gid' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_ANON_GID */ + +/* Define to 1 if `anon_uid' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_ANON_UID */ + +/* Define to 1 if `fspec' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_FSPEC */ + +/* Define to 1 if `gmtoff' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_GMTOFF */ + +/* Define to 1 if `nobody_gid' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_NOBODY_GID */ + +/* Define to 1 if `nobody_uid' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_NOBODY_UID */ + +/* Define to 1 if `sector_size' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_SECTOR_SIZE */ + +/* Define to 1 if `sessionnr' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_SESSIONNR */ + +/* Define to 1 if `udfmflags' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_UDFMFLAGS */ + +/* Define to 1 if `version' is member of `udf_args_t'. */ +/* #undef HAVE_UDF_ARGS_T_VERSION */ + /* Define to 1 if `flags' is member of `ufs_args_t'. */ /* #undef HAVE_UFS_ARGS_T_FLAGS */ @@ -1352,6 +1458,9 @@ /* Define to 1 if you have the `xdr_symlinkargs' function. */ #define HAVE_XDR_SYMLINKARGS 1 +/* Define to 1 if you have the `xdr_u_int64_t' function. */ +#define HAVE_XDR_U_INT64_T 1 + /* Define to 1 if you have the `xdr_writeargs' function. */ #define HAVE_XDR_WRITEARGS 1 @@ -1392,26 +1501,49 @@ /* #define HOST_NAME "trang.nuxi.org" */ /* Define name and version of host machine (eg. solaris2.5.1) */ -/* #define HOST_OS "freebsd8.0" */ +/* #define HOST_OS "freebsd12.0" */ /* Define only name of host machine OS (eg. solaris2) */ -/* #define HOST_OS_NAME "freebsd8" */ +/* #define HOST_OS_NAME "freebsd12" */ /* Define only version of host machine (eg. 2.5.1) */ -/* #define HOST_OS_VERSION "8.0" */ +/* #define HOST_OS_VERSION "12.0" */ /* Define name of host machine's vendor (eg. sun) */ #define HOST_VENDOR "undermydesk" +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + /* Ignore permission bits */ /* #undef MNT2_CDFS_OPT_DEFPERM */ +/* Enable external attributes */ +#define MNT2_CDFS_OPT_EXTATT 0x4 + +/* Show file generations */ +#define MNT2_CDFS_OPT_GENS 0x2 + +/* Disable filename case translation */ +/* #undef MNT2_CDFS_OPT_NOCASETRANS */ + /* Use on-disk permission bits */ /* #undef MNT2_CDFS_OPT_NODEFPERM */ +/* Disable Joliet extensions */ +#define MNT2_CDFS_OPT_NOJOLIET 0x8 + +/* Disable Rock Ridge Interchange Protocol (RRIP) extensions */ +#define MNT2_CDFS_OPT_NORRIP 0x1 + /* Strip off extension from version string */ /* #undef MNT2_CDFS_OPT_NOVERSION */ +/* Enable Rock Ridge Interchange Protocol (RRIP) case insensitive filename + extensions */ +/* #undef MNT2_CDFS_OPT_RRCASEINS */ + /* Use Rock Ridge Interchange Protocol (RRIP) extensions */ /* #undef MNT2_CDFS_OPT_RRIP */ @@ -1451,6 +1583,9 @@ /* journaling filesystem (AIX's UFS/FFS) */ /* #undef MNT2_GEN_OPT_JFS */ +/* honor mandatory locking requests */ +/* #undef MNT2_GEN_OPT_MANDLOCK */ + /* do multi-component lookup on files */ /* #undef MNT2_GEN_OPT_MULTI */ @@ -1460,12 +1595,18 @@ /* NFS mount */ /* #undef MNT2_GEN_OPT_NFS */ +/* don't update access times */ +#define MNT2_GEN_OPT_NOATIME 0x10000000 + /* nocache (what?) */ /* #undef MNT2_GEN_OPT_NOCACHE */ /* do not interpret special device files */ #define MNT2_GEN_OPT_NODEV 0x0 +/* don't update directory access times */ +/* #undef MNT2_GEN_OPT_NODIRATIME */ + /* no exec calls allowed */ #define MNT2_GEN_OPT_NOEXEC 0x4 @@ -1509,7 +1650,7 @@ /* #undef MNT2_GEN_OPT_SYS5 */ /* Union mount */ -/* #undef MNT2_GEN_OPT_UNION */ +#define MNT2_GEN_OPT_UNION 0x20 /* set max secs for dir attr cache */ #define MNT2_NFS_OPT_ACDIRMAX 0x200000 @@ -1529,6 +1670,9 @@ /* hide mount type from df(1) */ /* #undef MNT2_NFS_OPT_AUTO */ +/* Linux broken setuid */ +/* #undef MNT2_NFS_OPT_BROKEN_SUID */ + /* set dead server retry thresh */ #define MNT2_NFS_OPT_DEADTHRESH 0x4000 @@ -1595,11 +1739,14 @@ /* don't cache attributes */ /* #undef MNT2_NFS_OPT_NOAC */ +/* does not support Access Control Lists */ +/* #undef MNT2_NFS_OPT_NOACL */ + /* Don't Connect the socket */ #define MNT2_NFS_OPT_NOCONN 0x80 /* no close-to-open consistency */ -/* #undef MNT2_NFS_OPT_NOCTO */ +#define MNT2_NFS_OPT_NOCTO 0x20000000 /* disallow interrupts on hard mounts */ /* #undef MNT2_NFS_OPT_NOINT */ @@ -1607,6 +1754,9 @@ /* Don't use locking */ /* #undef MNT2_NFS_OPT_NONLM */ +/* does not support readdir+ */ +/* #undef MNT2_NFS_OPT_NORDIRPLUS */ + /* Get lease for lookup */ /* #undef MNT2_NFS_OPT_NQLOOKLEASE */ @@ -1667,6 +1817,9 @@ /* spongy mount */ /* #undef MNT2_NFS_OPT_SPONGY */ +/* Reserved for nfsv4 */ +/* #undef MNT2_NFS_OPT_STRICTLOCK */ + /* set symlink cache time-to-live */ /* #undef MNT2_NFS_OPT_SYMTTL */ @@ -1676,6 +1829,9 @@ /* set initial timeout */ #define MNT2_NFS_OPT_TIMEO 0x8 +/* do not use shared cache for all mountpoints */ +/* #undef MNT2_NFS_OPT_UNSHARED */ + /* linux NFSv3 */ /* #undef MNT2_NFS_OPT_VER3 */ @@ -1778,6 +1934,9 @@ /* Mount Table option string: Don't cache attributes at all */ /* #undef MNTTAB_OPT_NOAC */ +/* Access Control Lists are not supported */ +/* #undef MNTTAB_OPT_NOACL */ + /* Mount Table option string: No auto (what?) */ /* #undef MNTTAB_OPT_NOAUTO */ @@ -1898,20 +2057,35 @@ /* Mount-table entry name for EFS filesystem (irix) */ /* #undef MNTTAB_TYPE_EFS */ +/* Mount-table entry name for EXT2 filesystem (linux) */ +/* #undef MNTTAB_TYPE_EXT2 */ + +/* Mount-table entry name for EXT3 filesystem (linux) */ +/* #undef MNTTAB_TYPE_EXT3 */ + +/* Mount-table entry name for EXT4 filesystem (linux) */ +/* #undef MNTTAB_TYPE_EXT4 */ + /* Mount-table entry name for FFS filesystem */ /* #undef MNTTAB_TYPE_FFS */ /* Mount-table entry name for LOFS filesystem */ /* #undef MNTTAB_TYPE_LOFS */ +/* Mount-table entry name for LUSTRE filesystem */ +/* #undef MNTTAB_TYPE_LUSTRE */ + /* Mount-table entry name for MFS filesystem */ -/* #undef MNTTAB_TYPE_MFS */ +#define MNTTAB_TYPE_MFS "mfs" /* Mount-table entry name for NFS filesystem */ #define MNTTAB_TYPE_NFS "nfs" /* Mount-table entry name for NFS3 filesystem */ -#define MNTTAB_TYPE_NFS3 "nfs3" +#define MNTTAB_TYPE_NFS3 "nfs" + +/* Mount-table entry name for NFS4 filesystem */ +#define MNTTAB_TYPE_NFS4 "nfs" /* Mount-table entry name for NULLFS (loopback on bsd44) filesystem */ #define MNTTAB_TYPE_NULLFS "nullfs" @@ -1922,8 +2096,11 @@ /* Mount-table entry name for TFS filesystem */ /* #undef MNTTAB_TYPE_TFS */ -/* Mount-table entry name for TMPFS filesystem */ -/* #undef MNTTAB_TYPE_TMPFS */ +/* Mount(2) type/name for TMPFS filesystem */ +#define MNTTAB_TYPE_TMPFS "tmpfs" + +/* Mount(2) type/name for UDF filesystem */ +#define MNTTAB_TYPE_UDF "udf" /* Mount-table entry name for UFS filesystem */ #define MNTTAB_TYPE_UFS "ufs" @@ -1955,6 +2132,15 @@ /* Mount(2) type/name for EFS filesystem (irix) */ /* #undef MOUNT_TYPE_EFS */ +/* Mount(2) type/name for EXT2 filesystem (linux) */ +/* #undef MOUNT_TYPE_EXT2 */ + +/* Mount(2) type/name for EXT3 filesystem (linux) */ +/* #undef MOUNT_TYPE_EXT3 */ + +/* Mount(2) type/name for EXT4 filesystem (linux) */ +/* #undef MOUNT_TYPE_EXT4 */ + /* Mount(2) type/name for FFS filesystem */ /* #undef MOUNT_TYPE_FFS */ @@ -1965,7 +2151,7 @@ /* #undef MOUNT_TYPE_LOFS */ /* Mount(2) type/name for MFS filesystem */ -/* #undef MOUNT_TYPE_MFS */ +#define MOUNT_TYPE_MFS "mfs" /* Mount(2) type/name for NFS filesystem */ #define MOUNT_TYPE_NFS "nfs" @@ -1973,6 +2159,9 @@ /* Mount(2) type/name for NFS3 filesystem */ #define MOUNT_TYPE_NFS3 MOUNT_NFS3 +/* Mount(2) type/name for NFS4 filesystem */ +/* #undef MOUNT_TYPE_NFS4 */ + /* Mount(2) type/name for NULLFS (loopback on bsd44) filesystem */ #define MOUNT_TYPE_NULLFS "nullfs" @@ -1981,7 +2170,10 @@ #define MOUNT_TYPE_PCFS "msdosfs" /* Mount(2) type/name for TFS filesystem */ -/* #undef MOUNT_TYPE_TFS */ +#define MOUNT_TYPE_TMPFS "tmpfs" + +/* Mount(2) type/name for UDF filesystem */ +#define MOUNT_TYPE_UDF "udf" /* Mount(2) type/name for TMPFS filesystem */ /* #undef MOUNT_TYPE_TMPFS */ @@ -2027,16 +2219,19 @@ #define PACKAGE_NAME "am-utils" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "am-utils 6.1.5" +#define PACKAGE_STRING "am-utils 6.2" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "am-utils" +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + /* Define to the version of this package. */ -#define PACKAGE_VERSION "6.1.5" +#define PACKAGE_VERSION "6.2" /* Type of the 6th argument to recvfrom() */ -#define RECVFROM_FROMLEN_TYPE int +#define RECVFROM_FROMLEN_TYPE socklen_t /* should signal handlers be reinstalled? */ /* #undef REINSTALL_SIGNAL_HANDLER */ @@ -2063,20 +2258,49 @@ /* #undef TM_IN_SYS_TIME */ /* Define user name */ -/* #define USER_NAME "obrien" */ +/* #define USER_NAME "cy" */ /* define if must NOT use NFS "noconn" option */ #define USE_CONNECTED_NFS_SOCKETS 1 +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + /* define if must use NFS "noconn" option */ /* #undef USE_UNCONNECTED_NFS_SOCKETS */ /* Version number of package */ -#define VERSION "6.1.5" +#define VERSION "6.2" -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif /* Define to the type of xdr procedure type */ #define XDRPROC_T_TYPE xdrproc_t @@ -2088,13 +2312,27 @@ `char[]'. */ #define YYTEXT_POINTER 1 -/* Define to 1 if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -/* # undef _ALL_SOURCE */ +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 #endif +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + /* Define a type/structure for an NFS V2 filehandle */ #define am_nfs_fh nfs_fh @@ -2152,7 +2390,7 @@ /* Check if rpcvers_t is defined in */ /* #undef rpcvers_t */ -/* Define to `unsigned' if does not define. */ +/* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define to `long' if does not define. */ @@ -2161,6 +2399,9 @@ /* Define a type for the tmpfs_args structure */ /* #undef tmpfs_args_t */ +/* Define a type for the udf_args structure */ +/* #undef udf_args_t */ + /* Define a type for the ufs_args structure */ #define ufs_args_t struct ufs_args diff --git a/usr.sbin/bhyvectl/bhyvectl.8 b/usr.sbin/bhyvectl/bhyvectl.8 index d72a795f383..035f9f6c758 100644 --- a/usr.sbin/bhyvectl/bhyvectl.8 +++ b/usr.sbin/bhyvectl/bhyvectl.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 12, 2016 +.Dd November 13, 2016 .Dt BHYVECTL 8 .Os .Sh NAME @@ -64,7 +64,7 @@ Operate on the virtual machine Create the specified VM. .It Fl -destroy Destroy the specified VM. -.It Fl -get-state +.It Fl -get-stats Retrieve statistics for the specified VM. .It Fl -inject-nmi Inject a non-maskable interrupt (NMI) into the VM. diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c index e5f5c504d9c..1fcd18d7eba 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c @@ -356,7 +356,7 @@ bridge_get_time_since_tc(struct bridge_if *bif, uint32_t *ticks) if (gettimeofday(&ct, NULL) < 0) { syslog(LOG_ERR, "bridge get time since last TC:" - "getttimeofday failed: %s", strerror(errno)); + "gettimeofday failed: %s", strerror(errno)); return (-1); } diff --git a/usr.sbin/crunch/crunchide/crunchide.c b/usr.sbin/crunch/crunchide/crunchide.c index 8665a14a734..b7eba399517 100644 --- a/usr.sbin/crunch/crunchide/crunchide.c +++ b/usr.sbin/crunch/crunchide/crunchide.c @@ -26,7 +26,7 @@ * University of Maryland at College Park */ /* - * crunchide.c - tiptoes through an a.out symbol table, hiding all defined + * crunchide.c - tiptoes through a symbol table, hiding all defined * global symbols. Allows the user to supply a "keep list" of symbols * that are not to be hidden. This program relies on the use of the * linker's -dc flag to actually put global bss data into the file's @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include "extern.h" diff --git a/usr.sbin/crunch/crunchide/exec_elf32.c b/usr.sbin/crunch/crunchide/exec_elf32.c index 6d94429f7e9..9aa29fd8a97 100644 --- a/usr.sbin/crunch/crunchide/exec_elf32.c +++ b/usr.sbin/crunch/crunchide/exec_elf32.c @@ -279,6 +279,10 @@ ELFNAMEEND(hide)(int fd, const char *fn) weird = 1; weirdreason = "section header string table does not exist"; } + if (strtabshdr == shstrtabshdr) { + weird = 1; + weirdreason = "combined strtab and shstrtab not supported"; + } if (weirdreason == NULL) weirdreason = "unsupported"; if (weird) { diff --git a/usr.sbin/daemon/Makefile.depend b/usr.sbin/daemon/Makefile.depend index 0f77a15a871..58f9a3347b0 100644 --- a/usr.sbin/daemon/Makefile.depend +++ b/usr.sbin/daemon/Makefile.depend @@ -5,6 +5,7 @@ DIRDEPS = \ gnu/lib/csu \ gnu/lib/libgcc \ include \ + include/xlocale \ lib/${CSU_DIR} \ lib/libc \ lib/libcompiler_rt \ diff --git a/usr.sbin/efivar/Makefile.depend b/usr.sbin/efivar/Makefile.depend new file mode 100644 index 00000000000..8af72d7991a --- /dev/null +++ b/usr.sbin/efivar/Makefile.depend @@ -0,0 +1,19 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + gnu/lib/libgcc \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + lib/libefivar \ + + +.include + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/hyperv/Makefile b/usr.sbin/hyperv/Makefile index c11b3417c19..d42817f4a74 100644 --- a/usr.sbin/hyperv/Makefile +++ b/usr.sbin/hyperv/Makefile @@ -2,6 +2,8 @@ .include -SUBDIR = tools +SUBDIR= \ + tools/kvp \ + tools/vss .include diff --git a/usr.sbin/hyperv/tools/Makefile.inc b/usr.sbin/hyperv/tools/Makefile.inc new file mode 100644 index 00000000000..7e09f324e3e --- /dev/null +++ b/usr.sbin/hyperv/tools/Makefile.inc @@ -0,0 +1,4 @@ +# $FreeBSD$ + +CFLAGS.gcc+= -Wno-uninitialized +.include "../../Makefile.inc" diff --git a/usr.sbin/hyperv/tools/Makefile b/usr.sbin/hyperv/tools/kvp/Makefile similarity index 52% rename from usr.sbin/hyperv/tools/Makefile rename to usr.sbin/hyperv/tools/kvp/Makefile index 3cfc0013cf5..e1bc47c0011 100644 --- a/usr.sbin/hyperv/tools/Makefile +++ b/usr.sbin/hyperv/tools/kvp/Makefile @@ -2,12 +2,12 @@ .include -HV_KVP_DAEMON_DISTDIR?= ${.CURDIR}/../../../contrib/hyperv/tools +HV_KVP_DAEMON_DISTDIR?= ${.CURDIR}/../../../../contrib/hyperv/tools .PATH: ${HV_KVP_DAEMON_DISTDIR} PROG= hv_kvp_daemon MAN= hv_kvp_daemon.8 -CFLAGS+= -I${.CURDIR}/../../../sys/dev/hyperv/utilities +CFLAGS+= -I${.CURDIR}/../../../../sys/dev/hyperv/utilities .include diff --git a/usr.sbin/hyperv/tools/Makefile.depend b/usr.sbin/hyperv/tools/kvp/Makefile.depend similarity index 100% rename from usr.sbin/hyperv/tools/Makefile.depend rename to usr.sbin/hyperv/tools/kvp/Makefile.depend diff --git a/usr.sbin/hyperv/tools/vss/Makefile b/usr.sbin/hyperv/tools/vss/Makefile new file mode 100644 index 00000000000..c9a2e6a9610 --- /dev/null +++ b/usr.sbin/hyperv/tools/vss/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ +DIRDEPS = lib/libc + +.include + +HV_VSS_DAEMON_DISTDIR?= ${.CURDIR}/../../../../contrib/hyperv/tools +.PATH: ${HV_VSS_DAEMON_DISTDIR} + +PROG= hv_vss_daemon +MAN= hv_vss_daemon.8 + +CFLAGS+= -I${.CURDIR}/../../../../sys/dev/hyperv/utilities + +.include diff --git a/usr.sbin/hyperv/tools/vss/Makefile.depend b/usr.sbin/hyperv/tools/vss/Makefile.depend new file mode 100644 index 00000000000..3646e2e2b1a --- /dev/null +++ b/usr.sbin/hyperv/tools/vss/Makefile.depend @@ -0,0 +1,18 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + gnu/lib/libgcc \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + + +.include + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/pw/grupd.c b/usr.sbin/pw/grupd.c index 38d5e5bc956..5d0df0263e4 100644 --- a/usr.sbin/pw/grupd.c +++ b/usr.sbin/pw/grupd.c @@ -77,6 +77,7 @@ gr_update(struct group * grp, char const * group) close(tfd); err(1, "gr_copy()"); } + fsync(tfd); close(tfd); if (gr_mkdb() == -1) { gr_fini(); diff --git a/usr.sbin/pw/pw_nis.c b/usr.sbin/pw/pw_nis.c index 35b26ea5224..087c9460f3f 100644 --- a/usr.sbin/pw/pw_nis.c +++ b/usr.sbin/pw/pw_nis.c @@ -67,6 +67,7 @@ pw_nisupdate(const char * path, struct passwd * pwd, char const * user) close(tfd); err(1, "pw_copy()"); } + fsync(tfd); close(tfd); if (chmod(pw_tempname(), 0644) == -1) err(1, "chmod()"); diff --git a/usr.sbin/pw/pwupd.c b/usr.sbin/pw/pwupd.c index 3bcb95f8c46..87c3c994bad 100644 --- a/usr.sbin/pw/pwupd.c +++ b/usr.sbin/pw/pwupd.c @@ -114,6 +114,7 @@ pw_update(struct passwd * pwd, char const * user) close(tfd); err(1, "pw_copy()"); } + fsync(tfd); close(tfd); /* * in case of deletion of a user, the whole database diff --git a/usr.sbin/smbmsg/smbmsg.c b/usr.sbin/smbmsg/smbmsg.c index 4e7e609a7b0..1472651b813 100644 --- a/usr.sbin/smbmsg/smbmsg.c +++ b/usr.sbin/smbmsg/smbmsg.c @@ -61,7 +61,7 @@ static int wflag; /* word IO */ static unsigned char ibuf[SMB_MAXBLOCKSIZE]; static unsigned char obuf[SMB_MAXBLOCKSIZE]; -static unsigned short oword, iword; +static unsigned short oword; /* * The I2C specs say that all addresses below 16 and above or equal @@ -135,6 +135,8 @@ do_io(void) c.slave = slave; c.cmd = cflag; + c.rcount = 0; + c.wcount = 0; if (fmt == NULL && iflag > 0) fmt = wflag? wordfmt: bytefmt; @@ -163,11 +165,9 @@ do_io(void) } if (iflag == 1 && oflag == -1) { /* command + 1 byte input: read byte op. */ - c.rbuf = ibuf; - c.rcount = iflag; if (ioctl(fd, SMB_READB, &c) == -1) return (-1); - printf(fmt, (int)(unsigned char)ibuf[0]); + printf(fmt, (unsigned char)c.rdata.byte); putchar('\n'); return (0); } else if (iflag == -1 && oflag == 1) { @@ -176,11 +176,9 @@ do_io(void) return (ioctl(fd, SMB_WRITEB, &c)); } else if (wflag && iflag == 2 && oflag == -1) { /* command + 2 bytes input: read word op. */ - c.rbuf = (char*) &iword; - c.rcount = iflag; if (ioctl(fd, SMB_READW, &c) == -1) return (-1); - printf(fmt, (int)(unsigned short)iword); + printf(fmt, (unsigned short)c.rdata.word); putchar('\n'); return (0); } else if (wflag && iflag == -1 && oflag == 2) { @@ -193,11 +191,9 @@ do_io(void) * "process call" op. */ c.wdata.word = oword; - c.rbuf = (char*) &iword; - c.rcount = iflag; if (ioctl(fd, SMB_PCALL, &c) == -1) return (-1); - printf(fmt, (int)(unsigned short)iword); + printf(fmt, (unsigned short)c.rdata.word); putchar('\n'); return (0); } else if (iflag > 1 && oflag == -1) { @@ -206,7 +202,7 @@ do_io(void) c.rcount = iflag; if (ioctl(fd, SMB_BREAD, &c) == -1) return (-1); - for (i = 0; i < iflag; i++) { + for (i = 0; i < c.rcount; i++) { if (i != 0) putchar(' '); printf(fmt, ibuf[i]);