summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.inc123
-rw-r--r--ObsoleteFiles.inc1
-rw-r--r--UPDATING5
-rw-r--r--bin/sh/eval.c12
-rw-r--r--bin/sh/expand.c15
-rw-r--r--bin/sh/jobs.c8
-rw-r--r--bin/sh/parser.c7
-rw-r--r--bin/sh/redir.c29
-rw-r--r--bin/sh/tests/builtins/Makefile1
-rw-r--r--bin/sh/tests/builtins/lineno3.06
-rw-r--r--bin/sh/tests/builtins/lineno3.0.stdout2
-rw-r--r--bin/sh/trap.c35
-rw-r--r--bin/sleep/Makefile6
-rw-r--r--bin/sleep/tests/Makefile12
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/lockstat/lockstat.111
-rw-r--r--cddl/contrib/opensolaris/cmd/zdb/zdb.c41
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool_main.c83
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y23
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c20
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c16
-rw-r--r--cddl/lib/libdtrace/libproc_compat.h6
-rw-r--r--cddl/lib/libzfs/Makefile7
-rw-r--r--cddl/lib/libzpool/Makefile5
-rwxr-xr-xcontrib/binutils/bfd/config.bfd12
-rw-r--r--contrib/binutils/bfd/elf32-arm.c3
-rw-r--r--contrib/binutils/gas/config/tc-arm.c6
-rw-r--r--contrib/binutils/include/elf/arm.h2
-rw-r--r--contrib/bsnmp/snmp_target/target_snmp.c11
-rw-r--r--contrib/byacc/CHANGES142
-rw-r--r--contrib/byacc/MANIFEST2
-rw-r--r--contrib/byacc/VERSION2
-rw-r--r--contrib/byacc/aclocal.m419
-rw-r--r--contrib/byacc/btyaccpar.c106
-rw-r--r--contrib/byacc/closure.c8
-rwxr-xr-xcontrib/byacc/config.sub12
-rwxr-xr-xcontrib/byacc/configure1083
-rw-r--r--contrib/byacc/configure.in6
-rw-r--r--contrib/byacc/defs.h4
-rw-r--r--contrib/byacc/lalr.c13
-rw-r--r--contrib/byacc/main.c9
-rw-r--r--contrib/byacc/output.c164
-rw-r--r--contrib/byacc/package/byacc.spec4
-rw-r--r--contrib/byacc/package/debian/changelog12
-rw-r--r--contrib/byacc/package/debian/source/format2
-rw-r--r--contrib/byacc/package/mingw-byacc.spec4
-rw-r--r--contrib/byacc/package/pkgsrc/Makefile2
-rw-r--r--contrib/byacc/reader.c408
-rw-r--r--contrib/byacc/test/btyacc/btyacc_calc1.tab.c75
-rw-r--r--contrib/byacc/test/btyacc/btyacc_demo.tab.c197
-rw-r--r--contrib/byacc/test/btyacc/btyacc_demo2.error1
-rw-r--r--contrib/byacc/test/btyacc/btyacc_demo2.output0
-rw-r--r--contrib/byacc/test/btyacc/btyacc_demo2.tab.c15
-rw-r--r--contrib/byacc/test/btyacc/btyacc_demo2.tab.h0
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy1.error0
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy1.output247
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy1.tab.c1451
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy1.tab.h25
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy2.error0
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy2.output247
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy2.tab.c1451
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy2.tab.h25
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy3.error0
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy3.output247
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy3.tab.c1451
-rw-r--r--contrib/byacc/test/btyacc/btyacc_destroy3.tab.h25
-rw-r--r--contrib/byacc/test/btyacc/calc.tab.c80
-rw-r--r--contrib/byacc/test/btyacc/calc1.tab.c81
-rw-r--r--contrib/byacc/test/btyacc/calc2.tab.c86
-rw-r--r--contrib/byacc/test/btyacc/calc3.tab.c86
-rw-r--r--contrib/byacc/test/btyacc/code_calc.code.c50
-rw-r--r--contrib/byacc/test/btyacc/code_calc.tab.c26
-rw-r--r--contrib/byacc/test/btyacc/code_error.code.c50
-rw-r--r--contrib/byacc/test/btyacc/code_error.tab.c4
-rw-r--r--contrib/byacc/test/btyacc/empty.tab.c56
-rw-r--r--contrib/byacc/test/btyacc/err_inherit1.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_inherit2.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_inherit3.tab.c65
-rw-r--r--contrib/byacc/test/btyacc/err_inherit4.tab.c65
-rw-r--r--contrib/byacc/test/btyacc/err_inherit5.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax1.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax10.tab.c56
-rw-r--r--contrib/byacc/test/btyacc/err_syntax11.tab.c56
-rw-r--r--contrib/byacc/test/btyacc/err_syntax12.tab.c56
-rw-r--r--contrib/byacc/test/btyacc/err_syntax13.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax14.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax15.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax16.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax17.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax18.tab.c59
-rw-r--r--contrib/byacc/test/btyacc/err_syntax19.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax2.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax20.tab.c59
-rw-r--r--contrib/byacc/test/btyacc/err_syntax21.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax22.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax23.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax24.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax25.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax26.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax27.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax3.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax4.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax5.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax6.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax7.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax7a.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax7b.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax8.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax8a.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/err_syntax9.tab.c2
-rw-r--r--contrib/byacc/test/btyacc/error.tab.c56
-rw-r--r--contrib/byacc/test/btyacc/grammar.tab.c151
-rw-r--r--contrib/byacc/test/btyacc/inherit0.tab.c59
-rw-r--r--contrib/byacc/test/btyacc/inherit1.tab.c59
-rw-r--r--contrib/byacc/test/btyacc/inherit2.tab.c66
-rw-r--r--contrib/byacc/test/btyacc/ok_syntax1.tab.c86
-rw-r--r--contrib/byacc/test/btyacc/pure_calc.tab.c80
-rw-r--r--contrib/byacc/test/btyacc/pure_error.tab.c56
-rw-r--r--contrib/byacc/test/btyacc/quote_calc-s.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/quote_calc.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/quote_calc2-s.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/quote_calc2.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/quote_calc3-s.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/quote_calc3.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/quote_calc4-s.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/quote_calc4.tab.c84
-rw-r--r--contrib/byacc/test/btyacc/rename_debug.c56
-rw-r--r--contrib/byacc/test/btyacc/varsyntax_calc1.tab.c81
-rw-r--r--contrib/byacc/test/btyacc_destroy1.y91
-rw-r--r--contrib/byacc/test/btyacc_destroy2.y91
-rw-r--r--contrib/byacc/test/btyacc_destroy3.y94
-rw-r--r--contrib/byacc/test/yacc/calc2.tab.c6
-rw-r--r--contrib/byacc/test/yacc/calc3.tab.c6
-rw-r--r--contrib/byacc/test/yacc/ok_syntax1.tab.c6
-rw-r--r--contrib/byacc/yacc.121
-rw-r--r--contrib/libpcap/inet.c4
-rw-r--r--contrib/libpcap/pcap.c7
-rw-r--r--contrib/tcpdump/tcpdump.c8
-rw-r--r--etc/devd/Makefile2
-rw-r--r--etc/devd/ulpt.conf18
-rw-r--r--etc/mtree/BSD.tests.dist20
-rw-r--r--gnu/usr.bin/Makefile2
-rw-r--r--gnu/usr.bin/diff/Makefile6
-rw-r--r--gnu/usr.bin/diff/tests/Makefile17
-rw-r--r--include/rpcsvc/nis.x11
-rw-r--r--include/strings.h3
-rw-r--r--lib/libc/gen/dl_iterate_phdr.34
-rw-r--r--lib/libc/stdtime/strptime.33
-rw-r--r--lib/libc/stdtime/strptime.c11
-rw-r--r--lib/libc/string/Makefile.inc4
-rw-r--r--lib/libc/string/Symbol.map4
-rw-r--r--lib/libc/string/bzero.320
-rw-r--r--lib/libc/string/explicit_bzero.c22
-rw-r--r--lib/libc/sys/accept.24
-rw-r--r--lib/libcrypt/crypt.c17
-rw-r--r--lib/libnv/nvlist.c28
-rw-r--r--lib/libnv/nvlist_impl.h2
-rw-r--r--lib/libnv/nvpair.c32
-rw-r--r--lib/libnv/nvpair_impl.h18
-rw-r--r--lib/libpcap/Makefile1
-rw-r--r--lib/libpcap/config.h3
-rw-r--r--lib/libpcap/pcap-netmap.c283
-rw-r--r--lib/libproc/Makefile13
-rw-r--r--lib/libproc/libproc.h13
-rw-r--r--lib/libproc/proc_sym.c39
-rw-r--r--lib/libproc/tests/proc_test.c10
-rw-r--r--lib/librtld_db/rtld_db.c4
-rw-r--r--lib/msun/ld128/e_lgammal_r.c73
-rw-r--r--lib/msun/ld80/e_lgammal_r.c85
-rw-r--r--lib/msun/src/e_lgamma_r.c47
-rw-r--r--lib/msun/src/e_lgammaf_r.c43
-rw-r--r--libexec/rtld-elf/rtld.c3
-rw-r--r--release/doc/en_US.ISO8859-1/hardware/article.xml2
-rw-r--r--sbin/dumpon/dumpon.816
-rw-r--r--sbin/ifconfig/iflagg.c17
-rw-r--r--sbin/ipfw/Makefile2
-rw-r--r--sbin/ipfw/ipfw.8388
-rw-r--r--sbin/ipfw/ipfw2.c1524
-rw-r--r--sbin/ipfw/ipfw2.h43
-rw-r--r--sbin/ipfw/main.c4
-rw-r--r--sbin/ipfw/nat.c357
-rw-r--r--sbin/ipfw/tables.c2012
-rw-r--r--sbin/swapon/swapon.c9
-rw-r--r--share/man/man4/alc.424
-rw-r--r--share/man/man5/rc.conf.52
-rw-r--r--share/man/man9/timeout.9714
-rw-r--r--share/mk/sys.mk4
-rw-r--r--sys/amd64/amd64/minidump_machdep.c5
-rw-r--r--sys/amd64/amd64/pmap.c22
-rw-r--r--sys/amd64/include/md_var.h2
-rw-r--r--sys/amd64/include/pmap.h3
-rw-r--r--sys/amd64/include/vmm.h2
-rw-r--r--sys/amd64/vmm/intel/vmx.c8
-rw-r--r--sys/amd64/vmm/intel/vmx_msr.c100
-rw-r--r--sys/amd64/vmm/vmm.c4
-rw-r--r--sys/arm/altera/socfpga/files.socfpga1
-rw-r--r--sys/arm/altera/socfpga/socfpga_machdep.c3
-rw-r--r--sys/arm/arm/dump_machdep.c6
-rw-r--r--sys/arm/arm/minidump_machdep.c5
-rw-r--r--sys/arm/conf/EXYNOS5.common2
-rw-r--r--sys/arm/conf/SOCKIT2
-rw-r--r--sys/arm/include/md_var.h2
-rw-r--r--sys/arm/samsung/exynos/exynos5_machdep.c3
-rw-r--r--sys/arm/samsung/exynos/files.exynos52
-rw-r--r--sys/boot/common/disk.c4
-rw-r--r--sys/boot/common/disk.h6
-rw-r--r--sys/boot/common/part.c8
-rw-r--r--sys/boot/fdt/dts/arm/exynos5420-arndale-octa.dts15
-rw-r--r--sys/boot/fdt/dts/arm/exynos5420-peach-pit.dts15
-rw-r--r--sys/boot/fdt/dts/arm/exynos5420.dtsi27
-rw-r--r--sys/boot/fdt/dts/arm/socfpga-sockit.dts13
-rw-r--r--sys/boot/fdt/dts/arm/socfpga.dtsi9
-rw-r--r--sys/boot/i386/gptboot/gptboot.c8
-rw-r--r--sys/cam/cam_xpt.c4
-rw-r--r--sys/cam/ctl/ctl.c93
-rw-r--r--sys/cam/ctl/ctl_backend.h3
-rw-r--r--sys/cam/ctl/ctl_backend_block.c3
-rw-r--r--sys/cam/ctl/ctl_backend_ramdisk.c1
-rw-r--r--sys/cam/ctl/ctl_cmd_table.c7
-rw-r--r--sys/cam/ctl/ctl_frontend_cam_sim.c6
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c81
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.h1
-rw-r--r--sys/cam/ctl/ctl_private.h3
-rw-r--r--sys/cam/ctl/scsi_ctl.c1
-rw-r--r--sys/cam/scsi/scsi_all.h9
-rw-r--r--sys/cddl/compat/opensolaris/kern/opensolaris_kmem.c43
-rw-r--r--sys/cddl/compat/opensolaris/sys/assfail.h12
-rw-r--r--sys/cddl/compat/opensolaris/sys/kmem.h14
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c128
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c84
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c42
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c121
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c10
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c80
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c24
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/range_tree.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c22
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c128
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h7
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h11
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c13
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c14
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c20
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h2
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h2
-rw-r--r--sys/compat/freebsd32/freebsd32_syscalls.c2
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c10
-rw-r--r--sys/compat/freebsd32/syscalls.master8
-rw-r--r--sys/conf/Makefile.arm3
-rw-r--r--sys/conf/NOTES1
-rw-r--r--sys/conf/files5
-rw-r--r--sys/conf/files.pc988
-rw-r--r--sys/conf/kern.mk8
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/conf/options1
-rw-r--r--sys/conf/options.pc9816
-rw-r--r--sys/contrib/ipfilter/netinet/fil.c57
-rw-r--r--sys/contrib/ipfilter/netinet/ip_dns_pxy.c5
-rw-r--r--sys/contrib/ipfilter/netinet/ip_dstlist.c6
-rw-r--r--sys/contrib/ipfilter/netinet/ip_nat.c6
-rw-r--r--sys/dev/acpica/acpi.c31
-rw-r--r--sys/dev/acpica/acpi_pci.c1
-rw-r--r--sys/dev/acpica/acpivar.h11
-rw-r--r--sys/dev/ahci/ahci.c2
-rw-r--r--sys/dev/alc/if_alc.c1243
-rw-r--r--sys/dev/alc/if_alcreg.h311
-rw-r--r--sys/dev/alc/if_alcvar.h7
-rw-r--r--sys/dev/ale/if_ale.c16
-rw-r--r--sys/dev/ale/if_alereg.h1
-rw-r--r--sys/dev/cxgbe/common/t4_msg.h1
-rw-r--r--sys/dev/cxgbe/tom/t4_connect.c40
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.c52
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.h6
-rw-r--r--sys/dev/cxgbe/tom/t4_tom_l2t.c28
-rw-r--r--sys/dev/drm2/i915/intel_ringbuffer.c4
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c2
-rw-r--r--sys/dev/iscsi/icl.c35
-rw-r--r--sys/dev/iscsi/icl.h1
-rw-r--r--sys/dev/iscsi/iscsi.c1
-rw-r--r--sys/dev/mmc/host/dwmmc.c1101
-rw-r--r--sys/dev/mmc/host/dwmmc.h150
-rw-r--r--sys/dev/mmc/mmc.c1
-rw-r--r--sys/dev/mpr/mpr_sas.c3
-rw-r--r--sys/dev/mpr/mpr_table.c1
-rw-r--r--sys/dev/mrsas/mrsas.c6462
-rw-r--r--sys/dev/mrsas/mrsas.h3827
-rw-r--r--sys/dev/mrsas/mrsas_cam.c2023
-rw-r--r--sys/dev/mrsas/mrsas_fp.c2523
-rw-r--r--sys/dev/mrsas/mrsas_ioctl.c921
-rw-r--r--sys/dev/mrsas/mrsas_ioctl.h153
-rw-r--r--sys/dev/mrsas/mrsas_linux.c137
-rw-r--r--sys/dev/pci/pci.c21
-rw-r--r--sys/dev/uart/uart_bus_fdt.c2
-rw-r--r--sys/dev/usb/usb_freebsd.h1
-rw-r--r--sys/dev/usb/usb_freebsd_loader.h1
-rw-r--r--sys/dev/usb/usb_hub.c80
-rw-r--r--sys/dev/usb/usbdevs2
-rw-r--r--sys/dev/vt/vt_core.c10
-rw-r--r--sys/fs/autofs/autofs.c2
-rw-r--r--sys/fs/autofs/autofs.h2
-rw-r--r--sys/fs/autofs/autofs_vfsops.c6
-rw-r--r--sys/fs/autofs/autofs_vnops.c21
-rw-r--r--sys/fs/devfs/devfs_vnops.c29
-rw-r--r--sys/geom/geom_dev.c76
-rw-r--r--sys/i386/i386/machdep.c310
-rw-r--r--sys/i386/i386/minidump_machdep.c5
-rw-r--r--sys/i386/i386/pmap.c22
-rw-r--r--sys/i386/i386/vm_machdep.c2
-rw-r--r--sys/i386/include/md_var.h2
-rw-r--r--sys/i386/include/pmap.h3
-rw-r--r--sys/kern/bus_if.m13
-rw-r--r--sys/kern/imgact_elf.c8
-rw-r--r--sys/kern/init_sysent.c10
-rw-r--r--sys/kern/kern_descrip.c61
-rw-r--r--sys/kern/kern_event.c14
-rw-r--r--sys/kern/kern_exit.c22
-rw-r--r--sys/kern/kern_intr.c5
-rw-r--r--sys/kern/kern_proc.c22
-rw-r--r--sys/kern/kern_prot.c12
-rw-r--r--sys/kern/kern_racct.c84
-rw-r--r--sys/kern/kern_sig.c29
-rw-r--r--sys/kern/kern_timeout.c14
-rw-r--r--sys/kern/subr_bus.c31
-rw-r--r--sys/kern/syscalls.c2
-rw-r--r--sys/kern/syscalls.master8
-rw-r--r--sys/kern/tty.c43
-rw-r--r--sys/kern/uipc_syscalls.c491
-rw-r--r--sys/kern/vfs_bio.c9
-rw-r--r--sys/kern/vfs_vnops.c26
-rw-r--r--sys/libkern/explicit_bzero.c24
-rw-r--r--sys/mips/include/md_var.h2
-rw-r--r--sys/mips/mips/dump_machdep.c6
-rw-r--r--sys/mips/mips/minidump_machdep.c5
-rw-r--r--sys/modules/Makefile323
-rw-r--r--sys/modules/ipfw/Makefile3
-rw-r--r--sys/modules/mrsas/Makefile20
-rw-r--r--sys/modules/mrsas/mrsas_linux/Makefile10
-rw-r--r--sys/net/ieee8023ad_lacp.c7
-rw-r--r--sys/net/ieee8023ad_lacp.h2
-rw-r--r--sys/net/if_bridge.c198
-rw-r--r--sys/net/if_disc.c34
-rw-r--r--sys/net/if_edsc.c51
-rw-r--r--sys/net/if_enc.c4
-rw-r--r--sys/net/if_gif.c1
-rw-r--r--sys/net/if_lagg.c50
-rw-r--r--sys/net/if_lagg.h4
-rw-r--r--sys/netgraph/ng_ipfw.c2
-rw-r--r--sys/netinet/ip6.h6
-rw-r--r--sys/netinet/ip_fw.h415
-rw-r--r--sys/netinet/ip_gre.c2
-rw-r--r--sys/netinet/sctp_input.c2
-rw-r--r--sys/netinet/sctp_output.c68
-rw-r--r--sys/netinet/sctp_output.h4
-rw-r--r--sys/netinet/sctp_syscalls.c588
-rw-r--r--sys/netinet/sctp_usrreq.c6
-rw-r--r--sys/netinet/sctputil.c7
-rw-r--r--sys/netinet/tcp_output.c45
-rw-r--r--sys/netinet/tcp_timer.c148
-rw-r--r--sys/netinet/tcp_var.h9
-rw-r--r--sys/netinet/udp_usrreq.c18
-rw-r--r--sys/netinet/udp_var.h7
-rw-r--r--sys/netinet6/udp6_usrreq.c49
-rw-r--r--sys/netpfil/ipfw/ip_dummynet.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c198
-rw-r--r--sys/netpfil/ipfw/ip_fw_dynamic.c172
-rw-r--r--sys/netpfil/ipfw/ip_fw_iface.c537
-rw-r--r--sys/netpfil/ipfw/ip_fw_log.c19
-rw-r--r--sys/netpfil/ipfw/ip_fw_nat.c667
-rw-r--r--sys/netpfil/ipfw/ip_fw_private.h370
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c2759
-rw-r--r--sys/netpfil/ipfw/ip_fw_table.c3910
-rw-r--r--sys/netpfil/ipfw/ip_fw_table.h246
-rw-r--r--sys/netpfil/ipfw/ip_fw_table_algo.c3827
-rw-r--r--sys/netpfil/ipfw/ip_fw_table_value.c812
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4.h1
-rw-r--r--sys/ofed/include/linux/mlx4/device.h1
-rw-r--r--sys/pc98/pc98/machdep.c2999
-rw-r--r--sys/sys/bus.h2
-rw-r--r--sys/sys/cdefs.h2
-rw-r--r--sys/sys/event.h1
-rw-r--r--sys/sys/filedesc.h10
-rw-r--r--sys/sys/mbuf.h2
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/racct.h87
-rw-r--r--sys/sys/seq.h146
-rw-r--r--sys/sys/socketvar.h5
-rw-r--r--sys/sys/syscall.h2
-rw-r--r--sys/sys/syscall.mk2
-rw-r--r--sys/sys/sysproto.h2
-rw-r--r--sys/sys/systm.h3
-rw-r--r--sys/sys/ucred.h1
-rw-r--r--sys/sys/vnode.h1
-rw-r--r--sys/ufs/ufs/dir.h2
-rw-r--r--sys/vm/uma_core.c42
-rw-r--r--sys/vm/vm_glue.c49
-rw-r--r--sys/vm/vm_pageout.c8
-rw-r--r--sys/x86/acpica/srat.c36
-rw-r--r--sys/x86/include/specialreg.h4
-rw-r--r--sys/x86/x86/dump_machdep.c7
-rw-r--r--sys/x86/x86/local_apic.c2
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc7
-rw-r--r--tools/sched/schedgraph.py3
-rw-r--r--tools/tools/ath/athalq/ar9300_ds.c74
-rw-r--r--tools/tools/bootparttest/Makefile13
-rw-r--r--tools/tools/bootparttest/bootparttest.c174
-rw-r--r--tools/tools/bootparttest/stub.c (renamed from tools/tools/bootparttest/malloc.c)8
-rw-r--r--usr.bin/basename/Makefile6
-rw-r--r--usr.bin/basename/tests/Makefile12
-rw-r--r--usr.bin/cmp/Makefile6
-rw-r--r--usr.bin/cmp/tests/Makefile12
-rw-r--r--usr.bin/cut/Makefile6
-rw-r--r--usr.bin/cut/tests/Makefile21
-rw-r--r--usr.bin/dirname/Makefile6
-rw-r--r--usr.bin/dirname/tests/Makefile12
-rw-r--r--usr.bin/find/function.c2
-rw-r--r--usr.bin/grep/Makefile4
-rw-r--r--usr.bin/grep/tests/Makefile41
-rw-r--r--usr.bin/gzip/Makefile4
-rw-r--r--usr.bin/gzip/tests/Makefile12
-rw-r--r--usr.bin/mkimg/Makefile4
-rw-r--r--usr.bin/mkimg/ebr.c22
-rw-r--r--usr.bin/mkimg/mbr.c16
-rw-r--r--usr.bin/mkimg/mkimg.c21
-rw-r--r--usr.bin/mkimg/mkimg.h2
-rw-r--r--usr.bin/mkimg/pc98.c14
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu248
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu36
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu248
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu37
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu244
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu36
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu150
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu248
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu36
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu248
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu37
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu244
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu36
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu16
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu152
-rw-r--r--usr.bin/w/w.c18
-rw-r--r--usr.sbin/autofs/common.c15
-rw-r--r--usr.sbin/bhyve/acpi.c4
-rw-r--r--usr.sbin/bhyve/pci_virtio_block.c6
-rw-r--r--usr.sbin/bhyve/xmsr.c7
-rw-r--r--usr.sbin/ctladm/ctladm.85
-rw-r--r--usr.sbin/newsyslog/newsyslog.c4
-rw-r--r--usr.sbin/nmtree/Makefile6
-rw-r--r--usr.sbin/nmtree/tests/Makefile32
-rw-r--r--usr.sbin/nscd/query.c4
-rw-r--r--usr.sbin/pw/pw_user.c4
-rw-r--r--usr.sbin/pw/tests/Makefile2
-rwxr-xr-xusr.sbin/pw/tests/pw_modify.sh34
477 files changed, 42454 insertions, 18311 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index 3b92aef..8874972 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -299,6 +299,10 @@ HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT
WMAKEENV+= MK_CTF=no
.endif
+.if defined(CROSS_TOOLCHAIN)
+LOCALBASE?= /usr/local
+.include "${LOCALBASE}/share/toolchains/${CROSS_TOOLCHAIN}.mk"
+.endif
.if defined(CROSS_TOOLCHAIN_PREFIX)
CROSS_COMPILER_PREFIX?=${CROSS_TOOLCHAIN_PREFIX}
CROSS_BINUTILS_PREFIX?=${CROSS_TOOLCHAIN_PREFIX}
@@ -311,7 +315,7 @@ X${COMPILER}?= ${CROSS_COMPILER_PREFIX}${${COMPILER}}
X${COMPILER}?= ${${COMPILER}}
.endif
.endfor
-XBINUTILS= AS AR LD NM OBJDUMP RANLIB STRINGS
+XBINUTILS= AS AR LD NM OBJCOPY OBJDUMP RANLIB SIZE STRINGS
.for BINUTIL in ${XBINUTILS}
.if defined(CROSS_BINUTILS_PREFIX)
X${BINUTIL}?= ${CROSS_BINUTILS_PREFIX}${${BINUTIL}}
@@ -322,7 +326,9 @@ X${BINUTIL}?= ${${BINUTIL}}
WMAKEENV+= CC="${XCC} ${XFLAGS}" CXX="${XCXX} ${XFLAGS}" \
CPP="${XCPP} ${XFLAGS}" \
AS="${XAS}" AR="${XAR}" LD="${XLD}" NM=${XNM} \
- OBJDUMP=${XOBJDUMP} RANLIB=${XRANLIB} STRINGS=${XSTRINGS}
+ OBJDUMP=${XOBJDUMP} OBJCOPY="${XOBJCOPY}" \
+ RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \
+ SIZE="${XSIZE}"
.if ${XCC:M/*}
XFLAGS= --sysroot=${WORLDTMP}
@@ -343,10 +349,14 @@ TARGET_ABI= gnueabihf
TARGET_ABI= gnueabi
.endif
.endif
+.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc
+XFLAGS+= -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
+.else
TARGET_ABI?= unknown
TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd11.0
XFLAGS+= -target ${TARGET_TRIPLE}
.endif
+.endif
WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 DESTDIR=${WORLDTMP}
@@ -1531,9 +1541,12 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} \
lib/ncurses/ncurses lib/ncurses/ncursesw \
lib/libopie lib/libpam ${_lib_libthr} \
lib/libradius lib/libsbuf lib/libtacplus \
+ lib/libgeom \
${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \
+ ${_cddl_lib_libuutil} \
${_cddl_lib_libavl} \
${_cddl_lib_libzfs_core} \
+ ${_cddl_lib_libctf} \
lib/libutil lib/libpjdlog ${_lib_libypclnt} lib/libz lib/msun \
${_secure_lib_libcrypto} ${_lib_libldns} \
${_secure_lib_libssh} ${_secure_lib_libssl}
@@ -1543,6 +1556,8 @@ gnu/lib/libstdc++__L: lib/msun__L
gnu/lib/libsupc++__L: gnu/lib/libstdc++__L
.endif
+lib/libgeom__L: lib/libexpat__L
+
.if defined(WITH_ATF) || ${MK_TESTS} != "no"
.if !defined(WITH_ATF)
# Ensure that the ATF libraries will be built during make libraries, even
@@ -1580,9 +1595,13 @@ lib/libopie__L lib/libtacplus__L: lib/libmd__L
_cddl_lib_libumem= cddl/lib/libumem
_cddl_lib_libnvpair= cddl/lib/libnvpair
_cddl_lib_libavl= cddl/lib/libavl
+_cddl_lib_libuutil= cddl/lib/libuutil
_cddl_lib_libzfs_core= cddl/lib/libzfs_core
+_cddl_lib_libctf= cddl/lib/libctf
_cddl_lib= cddl/lib
cddl/lib/libzfs_core__L: cddl/lib/libnvpair__L
+cddl/lib/libzfs__L: lib/libgeom__L
+cddl/lib/libctf__L: lib/libz__L
.endif
.if ${MK_CRYPT} != "no"
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index e69a31a..3c4878b 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -1496,6 +1496,7 @@ OLD_LIBS+=usr/lib/libpanel.so.4
OLD_LIBS+=usr/lib/libpanelw.so.4
OLD_LIBS+=usr/lib/libpmc.so.4
OLD_LIBS+=usr/lib/libproc.so.1
+OLD_LIBS+=usr/lib/libproc.so.2
OLD_LIBS+=usr/lib/libradius.so.3
OLD_LIBS+=usr/lib/librpcsvc.so.4
OLD_LIBS+=usr/lib/libsdp.so.3
diff --git a/UPDATING b/UPDATING
index 04fe7a6..8fb2bd8 100644
--- a/UPDATING
+++ b/UPDATING
@@ -31,6 +31,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20141009:
+ gperf has been removed from the base system for architectures
+ that use clang. Ports that require gperf will obtain it from the
+ devel/gperf port.
+
20140923:
pjdfstest has been moved from tools/regression/pjdfstest to
contrib/pjdfstest .
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 3fd3050..ea2d264 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -316,9 +316,10 @@ evalloop(union node *n, int flags)
loopnest++;
status = 0;
for (;;) {
- evaltree(n->nbinary.ch1, EV_TESTED);
+ if (!evalskip)
+ evaltree(n->nbinary.ch1, EV_TESTED);
if (evalskip) {
-skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
+ if (evalskip == SKIPCONT && --skipcount <= 0) {
evalskip = 0;
continue;
}
@@ -337,8 +338,6 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
}
evaltree(n->nbinary.ch2, flags);
status = exitstatus;
- if (evalskip)
- goto skipping;
}
loopnest--;
exitstatus = status;
@@ -648,15 +647,15 @@ evalbackcmd(union node *n, struct backcmd *result)
struct jmploc *savehandler;
struct localvar *savelocalvars;
- setstackmark(&smark);
result->fd = -1;
result->buf = NULL;
result->nleft = 0;
result->jp = NULL;
if (n == NULL) {
exitstatus = 0;
- goto out;
+ return;
}
+ setstackmark(&smark);
exitstatus = oexitstatus;
if (is_valid_fast_cmdsubst(n)) {
savelocalvars = localvars;
@@ -698,7 +697,6 @@ evalbackcmd(union node *n, struct backcmd *result)
result->fd = pip[0];
result->jp = jp;
}
-out:
popstackmark(&smark);
TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
result->fd, result->buf, result->nleft, result->jp));
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index 15afc9c..b716f5c 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -328,24 +328,19 @@ exptilde(char *p, int flag)
done:
*p = '\0';
if (*(startp+1) == '\0') {
- if ((home = lookupvar("HOME")) == NULL)
- goto lose;
+ home = lookupvar("HOME");
} else {
- if ((pw = getpwnam(startp+1)) == NULL)
- goto lose;
- home = pw->pw_dir;
+ pw = getpwnam(startp+1);
+ home = pw != NULL ? pw->pw_dir : NULL;
}
- if (*home == '\0')
- goto lose;
*p = c;
+ if (home == NULL || *home == '\0')
+ return (startp);
if (quotes)
STPUTS_QUOTES(home, SQSYNTAX, expdest);
else
STPUTS(home, expdest);
return (p);
-lose:
- *p = c;
- return (startp);
}
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index e58310b..218e63d 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -373,13 +373,13 @@ showjob(struct job *jp, int mode)
strcat(statestr, " (core dumped)");
}
- for (ps = jp->ps ; ; ps++) { /* for each process */
+ for (ps = jp->ps ; procno > 0 ; ps++, procno--) { /* for each process */
if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
out1fmt("%d\n", (int)ps->pid);
- goto skip;
+ continue;
}
if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
- goto skip;
+ continue;
if (jobno == curr && ps == jp->ps)
c = '+';
else if (jobno == prev && ps == jp->ps)
@@ -410,8 +410,6 @@ showjob(struct job *jp, int mode)
out1c('\n');
} else
printjobcmd(jp);
-skip: if (--procno <= 0)
- break;
}
}
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 8e98768..f1f4e07 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -1279,6 +1279,13 @@ readcstyleesc(char *out)
c = pgetc();
if (c == PEOF)
synerror("Unterminated quoted string");
+ if (c == '\n') {
+ plinno++;
+ if (doprompt)
+ setprompt(2);
+ else
+ setprompt(0);
+ }
}
pungetc();
return out;
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 6127e86..95d3238 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -173,21 +173,12 @@ openredirect(union node *redir, char memory[10])
fname = redir->nfile.expfname;
if ((f = open(fname, O_RDONLY)) < 0)
error("cannot open %s: %s", fname, strerror(errno));
-movefd:
- if (f != fd) {
- if (dup2(f, fd) == -1) {
- e = errno;
- close(f);
- error("%d: %s", fd, strerror(e));
- }
- close(f);
- }
break;
case NFROMTO:
fname = redir->nfile.expfname;
if ((f = open(fname, O_RDWR|O_CREAT, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
- goto movefd;
+ break;
case NTO:
if (Cflag) {
fname = redir->nfile.expfname;
@@ -205,19 +196,19 @@ movefd:
} else
error("cannot create %s: %s", fname,
strerror(EEXIST));
- goto movefd;
+ break;
}
/* FALLTHROUGH */
case NCLOBBER:
fname = redir->nfile.expfname;
if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
- goto movefd;
+ break;
case NAPPEND:
fname = redir->nfile.expfname;
if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
error("cannot create %s: %s", fname, strerror(errno));
- goto movefd;
+ break;
case NTOFD:
case NFROMFD:
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
@@ -231,14 +222,22 @@ movefd:
} else {
close(fd);
}
- break;
+ return;
case NHERE:
case NXHERE:
f = openhere(redir);
- goto movefd;
+ break;
default:
abort();
}
+ if (f != fd) {
+ if (dup2(f, fd) == -1) {
+ e = errno;
+ close(f);
+ error("%d: %s", fd, strerror(e));
+ }
+ close(f);
+ }
}
diff --git a/bin/sh/tests/builtins/Makefile b/bin/sh/tests/builtins/Makefile
index 07c8098..d5d96b5 100644
--- a/bin/sh/tests/builtins/Makefile
+++ b/bin/sh/tests/builtins/Makefile
@@ -100,6 +100,7 @@ FILES+= jobid2.0
FILES+= kill1.0 kill2.0
FILES+= lineno.0 lineno.0.stdout
FILES+= lineno2.0
+FILES+= lineno3.0 lineno3.0.stdout
FILES+= local1.0
FILES+= local2.0
FILES+= local3.0
diff --git a/bin/sh/tests/builtins/lineno3.0 b/bin/sh/tests/builtins/lineno3.0
new file mode 100644
index 0000000..eb8f9ab
--- /dev/null
+++ b/bin/sh/tests/builtins/lineno3.0
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+echo before: $LINENO
+dummy=$'a\0
+'
+echo after: $LINENO
diff --git a/bin/sh/tests/builtins/lineno3.0.stdout b/bin/sh/tests/builtins/lineno3.0.stdout
new file mode 100644
index 0000000..6e0e4ac
--- /dev/null
+++ b/bin/sh/tests/builtins/lineno3.0.stdout
@@ -0,0 +1,2 @@
+before: 3
+after: 6
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index e5a2a91..8ea3b12 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -510,28 +510,25 @@ exitshell_savedstatus(void)
exiting_exitstatus = oexitstatus;
}
exitstatus = oexitstatus = exiting_exitstatus;
- if (setjmp(loc1.loc)) {
- goto l1;
- }
- if (setjmp(loc2.loc)) {
- goto l2;
- }
- handler = &loc1;
- if ((p = trap[0]) != NULL && *p != '\0') {
- /*
- * Reset evalskip, or the trap on EXIT could be
- * interrupted if the last command was a "return".
- */
- evalskip = 0;
- trap[0] = NULL;
- evalstring(p, 0);
+ if (!setjmp(loc1.loc)) {
+ handler = &loc1;
+ if ((p = trap[0]) != NULL && *p != '\0') {
+ /*
+ * Reset evalskip, or the trap on EXIT could be
+ * interrupted if the last command was a "return".
+ */
+ evalskip = 0;
+ trap[0] = NULL;
+ evalstring(p, 0);
+ }
}
-l1: handler = &loc2; /* probably unnecessary */
- flushall();
+ if (!setjmp(loc2.loc)) {
+ handler = &loc2; /* probably unnecessary */
+ flushall();
#if JOBS
- setjobctl(0);
+ setjobctl(0);
#endif
-l2:
+ }
if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN &&
sig != SIGTTOU) {
signal(sig, SIG_DFL);
diff --git a/bin/sleep/Makefile b/bin/sleep/Makefile
index 4ff7330..0ec3080 100644
--- a/bin/sleep/Makefile
+++ b/bin/sleep/Makefile
@@ -1,6 +1,12 @@
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= sleep
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/bin/sleep/tests/Makefile b/bin/sleep/tests/Makefile
new file mode 100644
index 0000000..9b286e6
--- /dev/null
+++ b/bin/sleep/tests/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/bin/sleep
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/bin/sleep
+ATF_TESTS_SH= sleep_test
+ATF_TESTS_SH_SRC_sleep_test= t_sleep.sh
+
+.include <bsd.test.mk>
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh
index 072fca7..54d975f 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh
@@ -38,7 +38,7 @@ fi
./$exe &
pid=$!
-$dtrace -32 -qs /dev/stdin <<EOF
+$dtrace -qs /dev/stdin <<EOF
typedef struct info {
char *zi_gamename;
int zi_ndungeons;
diff --git a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1 b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1
index b634d45..a725c8b 100644
--- a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1
+++ b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1
@@ -21,7 +21,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 24, 2013
+.Dd October 8, 2014
.Dt LOCKSTAT 1
.Os
.Sh NAME
@@ -238,10 +238,11 @@ Average duration of the events in nanoseconds, as appropriate for the event.
For the profiling event, duration means interrupt latency.
.It Lock
Address of the lock; displayed symbolically if possible.
-.It CPU+PIL
-CPU plus processor interrupt level (PIL).
-For example, if CPU 4 is interrupted while at PIL 6, this will be reported as
-cpu[4]+6.
+.It CPU+Pri_Class
+CPU plus the priority class of the interrupted thread.
+For example, if CPU 4 is interrupted while running a timeshare thread, this
+will be reported as
+.Ql cpu[4]+TShar .
.It Caller
Address of the caller; displayed symbolically if possible.
.El
diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
index 04970fc..1fce5b6 100644
--- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c
+++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
@@ -76,8 +76,10 @@
#ifndef lint
extern boolean_t zfs_recover;
+extern uint64_t zfs_arc_max, zfs_arc_meta_limit;
#else
boolean_t zfs_recover;
+uint64_t zfs_arc_max, zfs_arc_meta_limit;
#endif
const char cmdname[] = "zdb";
@@ -89,7 +91,7 @@ extern void dump_intent_log(zilog_t *);
uint64_t *zopt_object = NULL;
int zopt_objects = 0;
libzfs_handle_t *g_zfs;
-uint64_t max_inflight = 200;
+uint64_t max_inflight = 1000;
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
@@ -1461,6 +1463,11 @@ dump_deadlist(dsl_deadlist_t *dl)
if (dump_opt['d'] < 3)
return;
+ if (dl->dl_oldfmt) {
+ dump_bpobj(&dl->dl_bpobj, "old-format deadlist", 0);
+ return;
+ }
+
zdb_nicenum(dl->dl_phys->dl_used, bytes);
zdb_nicenum(dl->dl_phys->dl_comp, comp);
zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp);
@@ -2377,7 +2384,7 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
zcb->zcb_readfails = 0;
- if (dump_opt['b'] < 5 && isatty(STDERR_FILENO) &&
+ if (dump_opt['b'] < 5 &&
gethrtime() > zcb->zcb_lastprint + NANOSEC) {
uint64_t now = gethrtime();
char buf[10];
@@ -2462,9 +2469,9 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
if (!dump_opt['L']) {
vdev_t *rvd = spa->spa_root_vdev;
- for (int c = 0; c < rvd->vdev_children; c++) {
+ for (uint64_t c = 0; c < rvd->vdev_children; c++) {
vdev_t *vd = rvd->vdev_child[c];
- for (int m = 0; m < vd->vdev_ms_count; m++) {
+ for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
mutex_enter(&msp->ms_lock);
metaslab_unload(msp);
@@ -2477,6 +2484,15 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
* interfaces.
*/
if (msp->ms_sm != NULL) {
+ (void) fprintf(stderr,
+ "\rloading space map for "
+ "vdev %llu of %llu, "
+ "metaslab %llu of %llu ...",
+ (longlong_t)c,
+ (longlong_t)rvd->vdev_children,
+ (longlong_t)m,
+ (longlong_t)vd->vdev_ms_count);
+
msp->ms_ops = &zdb_metaslab_ops;
VERIFY0(space_map_load(msp->ms_sm,
msp->ms_tree, SM_ALLOC));
@@ -2485,6 +2501,7 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
mutex_exit(&msp->ms_lock);
}
}
+ (void) fprintf(stderr, "\n");
}
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
@@ -2594,10 +2611,12 @@ dump_block_stats(spa_t *spa)
* all async I/Os to complete.
*/
if (dump_opt['c']) {
- (void) zio_wait(spa->spa_async_zio_root);
- spa->spa_async_zio_root = zio_root(spa, NULL, NULL,
- ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
- ZIO_FLAG_GODFATHER);
+ for (int i = 0; i < max_ncpus; i++) {
+ (void) zio_wait(spa->spa_async_zio_root[i]);
+ spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
+ ZIO_FLAG_GODFATHER);
+ }
}
if (zcb.zcb_haderrors) {
@@ -3483,6 +3502,12 @@ main(int argc, char **argv)
usage();
}
+ /*
+ * ZDB does not typically re-read blocks; therefore limit the ARC
+ * to 256 MB, which can be used entirely for metadata.
+ */
+ zfs_arc_max = zfs_arc_meta_limit = 256 * 1024 * 1024;
+
kernel_init(FREAD);
g_zfs = libzfs_init();
ASSERT(g_zfs != NULL);
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
index 8cb8091..31340b0 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
@@ -2857,10 +2857,7 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
right_justify = B_FALSE;
if (pl->pl_prop != ZPROP_INVAL) {
- if (pl->pl_prop == ZPOOL_PROP_EXPANDSZ &&
- zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0)
- propstr = "-";
- else if (zpool_get_prop(zhp, pl->pl_prop, property,
+ if (zpool_get_prop(zhp, pl->pl_prop, property,
sizeof (property), NULL, cb->cb_literal) != 0)
propstr = "-";
else
@@ -2894,21 +2891,37 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
}
static void
-print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted)
+print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
+ boolean_t valid)
{
char propval[64];
boolean_t fixed;
size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
-
- if (prop == ZPOOL_PROP_EXPANDSZ && value == 0)
- (void) strlcpy(propval, "-", sizeof (propval));
- else if (prop == ZPOOL_PROP_FRAGMENTATION && value == ZFS_FRAG_INVALID)
- (void) strlcpy(propval, "-", sizeof (propval));
- else if (prop == ZPOOL_PROP_FRAGMENTATION)
+ switch (prop) {
+ case ZPOOL_PROP_EXPANDSZ:
+ if (value == 0)
+ (void) strlcpy(propval, "-", sizeof (propval));
+ else
+ zfs_nicenum(value, propval, sizeof (propval));
+ break;
+ case ZPOOL_PROP_FRAGMENTATION:
+ if (value == ZFS_FRAG_INVALID) {
+ (void) strlcpy(propval, "-", sizeof (propval));
+ } else {
+ (void) snprintf(propval, sizeof (propval), "%llu%%",
+ value);
+ }
+ break;
+ case ZPOOL_PROP_CAPACITY:
(void) snprintf(propval, sizeof (propval), "%llu%%", value);
- else
+ break;
+ default:
zfs_nicenum(value, propval, sizeof (propval));
+ }
+
+ if (!valid)
+ (void) strlcpy(propval, "-", sizeof (propval));
if (scripted)
(void) printf("\t%s", propval);
@@ -2930,6 +2943,9 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
(uint64_t **)&vs, &c) == 0);
if (name != NULL) {
+ boolean_t toplevel = (vs->vs_space != 0);
+ uint64_t cap;
+
if (scripted)
(void) printf("\t%s", name);
else if (strlen(name) + depth > cb->cb_namewidth)
@@ -2938,24 +2954,26 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
(void) printf("%*s%s%*s", depth, "", name,
(int)(cb->cb_namewidth - strlen(name) - depth), "");
- /* only toplevel vdevs have capacity stats */
- if (vs->vs_space == 0) {
- if (scripted)
- (void) printf("\t-\t-\t-\t-");
- else
- (void) printf(" - - - -");
- } else {
- print_one_column(ZPOOL_PROP_SIZE, vs->vs_space,
- scripted);
- print_one_column(ZPOOL_PROP_CAPACITY, vs->vs_alloc,
- scripted);
- print_one_column(ZPOOL_PROP_FREE,
- vs->vs_space - vs->vs_alloc, scripted);
- print_one_column(ZPOOL_PROP_FRAGMENTATION,
- vs->vs_fragmentation, scripted);
- }
- print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize,
- scripted);
+ /*
+ * Print the properties for the individual vdevs. Some
+ * properties are only applicable to toplevel vdevs. The
+ * 'toplevel' boolean value is passed to the print_one_column()
+ * to indicate that the value is valid.
+ */
+ print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
+ toplevel);
+ print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
+ toplevel);
+ print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
+ scripted, toplevel);
+ print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
+ B_TRUE);
+ print_one_column(ZPOOL_PROP_FRAGMENTATION,
+ vs->vs_fragmentation, scripted,
+ (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
+ cap = (vs->vs_space == 0) ? 0 :
+ (vs->vs_alloc * 100 / vs->vs_space);
+ print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
(void) printf("\n");
}
@@ -3024,7 +3042,8 @@ list_callback(zpool_handle_t *zhp, void *data)
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
* -o List of properties to display. Defaults to
- * "name,size,allocated,free,capacity,health,altroot"
+ * "name,size,allocated,free,expandsize,fragmentation,capacity,"
+ * "dedupratio,health,altroot"
* -p Diplay values in parsable (exact) format.
* -T Display a timestamp in date(1) or Unix format
*
@@ -3038,7 +3057,7 @@ zpool_do_list(int argc, char **argv)
int ret;
list_cbdata_t cb = { 0 };
static char default_props[] =
- "name,size,allocated,free,fragmentation,expandsize,capacity,"
+ "name,size,allocated,free,expandsize,fragmentation,capacity,"
"dedupratio,health,altroot";
char *props = default_props;
unsigned long interval = 0, count = 0;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
index 07790f4..6321b65 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
@@ -207,6 +207,8 @@
%type <l_tok> unary_operator
%type <l_tok> struct_or_union
+%type <l_str> dtrace_keyword_ident
+
%%
dtrace_program: d_expression DT_TOK_EOF { return (dt_node_root($1)); }
@@ -391,12 +393,18 @@ postfix_expression:
| postfix_expression DT_TOK_DOT DT_TOK_TNAME {
$$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
}
+ | postfix_expression DT_TOK_DOT dtrace_keyword_ident {
+ $$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
+ }
| postfix_expression DT_TOK_PTR DT_TOK_IDENT {
$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
}
| postfix_expression DT_TOK_PTR DT_TOK_TNAME {
$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
}
+ | postfix_expression DT_TOK_PTR dtrace_keyword_ident {
+ $$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
+ }
| postfix_expression DT_TOK_ADDADD {
$$ = OP1(DT_TOK_POSTINC, $1);
}
@@ -411,6 +419,10 @@ postfix_expression:
DT_TOK_TNAME DT_TOK_RPAR {
$$ = dt_node_offsetof($3, $5);
}
+ | DT_TOK_OFFSETOF DT_TOK_LPAR type_name DT_TOK_COMMA
+ dtrace_keyword_ident DT_TOK_RPAR {
+ $$ = dt_node_offsetof($3, $5);
+ }
| DT_TOK_XLATE DT_TOK_LT type_name DT_TOK_GT
DT_TOK_LPAR expression DT_TOK_RPAR {
$$ = OP2(DT_TOK_XLATE, dt_node_type($3), $6);
@@ -835,4 +847,15 @@ function_parameters:
| parameter_type_list { $$ = $1; }
;
+dtrace_keyword_ident:
+ DT_KEY_PROBE { $$ = DUP("probe"); }
+ | DT_KEY_PROVIDER { $$ = DUP("provider"); }
+ | DT_KEY_SELF { $$ = DUP("self"); }
+ | DT_KEY_STRING { $$ = DUP("string"); }
+ | DT_TOK_STRINGOF { $$ = DUP("stringof"); }
+ | DT_KEY_USERLAND { $$ = DUP("userland"); }
+ | DT_TOK_XLATE { $$ = DUP("xlate"); }
+ | DT_KEY_XLATOR { $$ = DUP("translator"); }
+ ;
+
%%
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
index c865a2d..6c529e5 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
@@ -434,15 +434,10 @@ static const prmap_t *
dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
{
char m[MAXPATHLEN];
-#if defined(sun)
Lmid_t lmid = PR_LMID_EVERY;
-#else
- Lmid_t lmid = 0;
-#endif
const char *obj;
const prmap_t *pmp;
-#if defined(sun)
/*
* Pick apart the link map from the library name.
*/
@@ -463,20 +458,17 @@ dt_pid_fix_mod(dtrace_probedesc_t *pdp, struct ps_prochandle *P)
} else {
obj = pdp->dtpd_mod;
}
-#else
- obj = pdp->dtpd_mod;
-#endif
if ((pmp = Plmid_to_map(P, lmid, obj)) == NULL)
return (NULL);
-#if defined(sun)
(void) Pobjname(P, pmp->pr_vaddr, m, sizeof (m));
if ((obj = strrchr(m, '/')) == NULL)
obj = &m[0];
else
obj++;
+#if defined(sun)
(void) Plmid(P, pmp->pr_vaddr, &lmid);
#endif
@@ -571,9 +563,7 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname)
{
struct ps_prochandle *P = data;
GElf_Sym sym;
-#if defined(sun)
prsyminfo_t sip;
-#endif
dof_helper_t dh;
GElf_Half e_type;
const char *mname;
@@ -852,11 +842,7 @@ dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
ctf_funcinfo_t f;
ctf_id_t argv[32];
GElf_Sym sym;
-#if defined(sun)
prsyminfo_t si;
-#else
- void *si;
-#endif
struct ps_prochandle *p;
int i, args;
char buf[DTRACE_ARGTYPELEN];
@@ -941,13 +927,11 @@ dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
goto out;
}
-#if defined(sun)
if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {
dt_dprintf("failed to get ctf information for %s in %s`%s\n",
pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
goto out;
}
-#endif
(void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,
pdp->dtpd_mod);
@@ -977,7 +961,6 @@ dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
(void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +
ret, DTRACE_ARGTYPELEN - ret, buf);
*nargs = 2;
-#if defined(sun)
} else {
if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)
goto out;
@@ -993,7 +976,6 @@ dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
(void) ctf_type_qname(fp, argv[i], adp->dtargd_native +
ret, DTRACE_ARGTYPELEN - ret, buf);
}
-#endif
}
out:
dt_proc_unlock(dtp, p);
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
index 30b2d87..e09417a 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@@ -304,7 +304,6 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case ZPOOL_PROP_FREE:
case ZPOOL_PROP_FREEING:
case ZPOOL_PROP_LEAKED:
- case ZPOOL_PROP_EXPANDSZ:
if (literal) {
(void) snprintf(buf, len, "%llu",
(u_longlong_t)intval);
@@ -312,7 +311,16 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
(void) zfs_nicenum(intval, buf, len);
}
break;
-
+ case ZPOOL_PROP_EXPANDSZ:
+ if (intval == 0) {
+ (void) strlcpy(buf, "-", len);
+ } else if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) zfs_nicenum(intval, buf, len);
+ }
+ break;
case ZPOOL_PROP_CAPACITY:
if (literal) {
(void) snprintf(buf, len, "%llu",
@@ -330,13 +338,11 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
(u_longlong_t)intval);
}
break;
-
case ZPOOL_PROP_DEDUPRATIO:
(void) snprintf(buf, len, "%llu.%02llux",
(u_longlong_t)(intval / 100),
(u_longlong_t)(intval % 100));
break;
-
case ZPOOL_PROP_HEALTH:
verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
diff --git a/cddl/lib/libdtrace/libproc_compat.h b/cddl/lib/libdtrace/libproc_compat.h
index 8443336..0d99d96 100644
--- a/cddl/lib/libdtrace/libproc_compat.h
+++ b/cddl/lib/libdtrace/libproc_compat.h
@@ -38,7 +38,7 @@
#define Pxlookup_by_addr(p, a, n, s, sym, i) \
proc_addr2sym(p, a, n, s, sym)
#define Pxlookup_by_name(p, l, s1, s2, sym, a) \
- proc_name2sym((p), (s1), (s2), (sym))
+ proc_name2sym(p, s1, s2, sym, a)
#define Paddr_to_map proc_addr2map
#define Pcreate_error strerror
#define Pdelbkpt proc_bkptdel
@@ -46,10 +46,10 @@
#define Plmid(p, a, l) (-1)
#define Plmid_to_map(p, l, o) proc_obj2map((p), (o))
#define Plookup_by_addr proc_addr2sym
-#define Pname_to_ctf(p, obj) NULL
+#define Pname_to_ctf(p, obj) (ctf_file_t *)proc_name2ctf(p, obj)
#define Pname_to_map proc_name2map
#define Pobject_iter proc_iter_objs
-#define Pobject_iter_resolved(p, f, arg) 1
+#define Pobject_iter_resolved(p, f, arg) proc_iter_objs(p, f, arg)
#define Pobjname proc_objname
#define Pread proc_read
#define Prd_agent proc_rdagent
diff --git a/cddl/lib/libzfs/Makefile b/cddl/lib/libzfs/Makefile
index 4010ac1..b2f4352 100644
--- a/cddl/lib/libzfs/Makefile
+++ b/cddl/lib/libzfs/Makefile
@@ -7,8 +7,11 @@
LIB= zfs
DPADD= ${LIBMD} ${LIBPTHREAD} ${LIBUMEM} ${LIBUTIL} ${LIBM} ${LIBNVPAIR} \
- ${LIBAVL} ${LIBZFS_CORE}
-LDADD= -lmd -lpthread -lumem -lutil -lm -lnvpair -lavl -lzfs_core
+ ${LIBAVL} ${LIBZFS_CORE} ${LIBUUTIL} ${LIBBSDXML} ${LIBGEOM} \
+ ${LIBNVPAIR}
+
+LDADD= -lmd -lpthread -lumem -lutil -luutil -lm -lnvpair -lavl \
+ -lbsdxml -lgeom -lnvpair -lzfs_core
SRCS= deviceid.c \
fsshare.c \
diff --git a/cddl/lib/libzpool/Makefile b/cddl/lib/libzpool/Makefile
index 8f60a20..b80af04 100644
--- a/cddl/lib/libzpool/Makefile
+++ b/cddl/lib/libzpool/Makefile
@@ -56,8 +56,9 @@ CFLAGS+= -I${.CURDIR}/../../../lib/libpthread/thread
CFLAGS+= -I${.CURDIR}/../../../lib/libpthread/sys
CFLAGS+= -I${.CURDIR}/../../../lib/libthr/arch/${MACHINE_CPUARCH}/include
-DPADD= ${LIBMD} ${LIBPTHREAD} ${LIBZ}
-LDADD= -lmd -lpthread -lz
+DPADD= ${LIBMD} ${LIBPTHREAD} ${LIBZ} ${LIBNVPAIR} \
+ ${LIBAVL} ${LIBUMEM}
+LDADD= -lmd -lpthread -lz -lnvpair -lavl -lumem
# atomic.S doesn't like profiling.
MK_PROFILE= no
diff --git a/contrib/binutils/bfd/config.bfd b/contrib/binutils/bfd/config.bfd
index 4717091..3d18dfa 100755
--- a/contrib/binutils/bfd/config.bfd
+++ b/contrib/binutils/bfd/config.bfd
@@ -273,19 +273,11 @@ case "${targ}" in
targ_defvec=bfd_elf32_littlearm_vec
targ_selvecs=bfd_elf32_bigarm_vec
;;
- armeb-*-freebsd*)
+ arm*eb*-*-freebsd*)
targ_defvec=bfd_elf32_bigarm_vec
targ_selvecs=bfd_elf32_littlearm_vec
;;
- armv6eb-*-freebsd*)
- targ_defvec=bfd_elf32_bigarm_vec
- targ_selvecs=bfd_elf32_littlearm_vec
- ;;
- armv6-*-freebsd* | armv6hf-*-freebsd*)
- targ_defvec=bfd_elf32_littlearm_vec
- targ_selvecs=bfd_elf32_bigarm_vec
- ;;
- arm-*-elf | arm-*-freebsd* | arm*-*-linux-* | arm*-*-conix* | \
+ arm-*-elf | arm*-*-freebsd* | arm*-*-linux-* | arm*-*-conix* | \
arm*-*-uclinux* | arm-*-kfreebsd*-gnu | \
arm*-*-eabi* )
targ_defvec=bfd_elf32_littlearm_vec
diff --git a/contrib/binutils/bfd/elf32-arm.c b/contrib/binutils/bfd/elf32-arm.c
index 02dd21b..83acfe5 100644
--- a/contrib/binutils/bfd/elf32-arm.c
+++ b/contrib/binutils/bfd/elf32-arm.c
@@ -6965,7 +6965,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
for (; in_list; in_list = in_list->next)
{
- if ((in_list->tag & 128) < 64)
+ if ((in_list->tag & 128) < 64
+ && in_list->tag != Tag_Virtualization_use)
{
_bfd_error_handler
(_("Warning: %B: Unknown EABI object attribute %d"),
diff --git a/contrib/binutils/gas/config/tc-arm.c b/contrib/binutils/gas/config/tc-arm.c
index 1d9e27c..8b470c0 100644
--- a/contrib/binutils/gas/config/tc-arm.c
+++ b/contrib/binutils/gas/config/tc-arm.c
@@ -19395,6 +19395,12 @@ arm_fix_adjustable (fixS * fixP)
|| fixP->fx_r_type == BFD_RELOC_ARM_LDR_PC_G0)
return 0;
+ if (fixP->fx_r_type == BFD_RELOC_ARM_MOVW
+ || fixP->fx_r_type == BFD_RELOC_ARM_MOVT
+ || fixP->fx_r_type == BFD_RELOC_ARM_THUMB_MOVW
+ || fixP->fx_r_type == BFD_RELOC_ARM_THUMB_MOVT)
+ return 0;
+
return 1;
}
#endif /* defined (OBJ_ELF) || defined (OBJ_COFF) */
diff --git a/contrib/binutils/include/elf/arm.h b/contrib/binutils/include/elf/arm.h
index e701883..b10bb72 100644
--- a/contrib/binutils/include/elf/arm.h
+++ b/contrib/binutils/include/elf/arm.h
@@ -271,6 +271,8 @@ enum
Tag_ABI_optimization_goals,
Tag_ABI_FP_optimization_goals,
/* 32 is generic. */
+
+ Tag_Virtualization_use = 68,
};
#endif
diff --git a/contrib/bsnmp/snmp_target/target_snmp.c b/contrib/bsnmp/snmp_target/target_snmp.c
index c6f05de..52b76dc 100644
--- a/contrib/bsnmp/snmp_target/target_snmp.c
+++ b/contrib/bsnmp/snmp_target/target_snmp.c
@@ -301,6 +301,7 @@ op_snmp_target_addrs(struct snmp_context *ctx __unused, struct snmp_value *val,
default:
break;
}
+ return (SNMP_ERR_NOERROR);
default:
abort();
@@ -625,6 +626,7 @@ op_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val,
default:
break;
}
+ return (SNMP_ERR_NOERROR);
default:
abort();
@@ -663,13 +665,14 @@ target_append_index(struct asn_oid *oid, uint sub, const char *name)
static int
target_decode_index(const struct asn_oid *oid, uint sub, char *name)
{
- uint32_t i, len;
+ uint32_t i;
- if ((len = oid->len - sub) >= SNMP_ADM_STR32_SIZ)
+ if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >=
+ SNMP_ADM_STR32_SIZ)
return (-1);
- for (i = 0; i < len; i++)
- name[i] = oid->subs[sub + i];
+ for (i = 0; i < oid->subs[sub]; i++)
+ name[i] = oid->subs[sub + i + 1];
name[i] = '\0';
return (0);
diff --git a/contrib/byacc/CHANGES b/contrib/byacc/CHANGES
index c9d73ce..1f01461 100644
--- a/contrib/byacc/CHANGES
+++ b/contrib/byacc/CHANGES
@@ -1,3 +1,145 @@
+2014-10-06 Thomas E. Dickey <tom@invisible-island.net>
+
+ * package/debian/source/format:
+ change to native format to work around regression in Debian packaging.
+
+ * VERSION, package/byacc.spec, package/debian/changelog, package/mingw-byacc.spec, package/pkgsrc/Makefile:
+ bump
+
+ * configure: regen
+
+ * main.c:
+ correct parameter for umask - for very old mkstemp's - and use type mode_t
+ to quiet compiler warning
+
+ * configure.in: add configure check for mode_t
+
+ * reader.c:
+ better fix for get_line, by ensuring there is enough space to null-terminate
+ its result (prompted by discussion with Craig Rodrigues).
+
+2014-10-05 Thomas E. Dickey <tom@invisible-island.net>
+
+ * main.c:
+ make change to umask before calling mkstemp, as suggested in Coverity #56902
+
+ * reader.c:
+ adjust logic in copy_action to avoid potential null-pointer dereference
+ (Coverity #56901)
+
+ * reader.c:
+ adjust logic to avoid potential null-pointer dereference in compile_args
+ (Coverity #63407)
+
+ * reader.c: eliminate strcpy into fixed-size buffer (Coverity #63408)
+
+ * yacc.1: document changes made with respect to %parse-param
+
+ * output.c:
+ add parameters from %parse-param to destructor. The order of the parameters
+ is intentionally inconsistent with yyparse/yyerror, for "compatibility" with
+ bison.
+
+ * test/btyacc/btyacc_destroy1.tab.c, test/btyacc/btyacc_destroy2.tab.c, test/btyacc/btyacc_destroy3.tab.c:
+ regen
+
+ * output.c:
+ use puts_param_types/puts_param_names to output lex_param data.
+
+ * test/btyacc/ok_syntax1.tab.c, test/btyacc/calc2.tab.c, test/btyacc/calc3.tab.c, test/yacc/ok_syntax1.tab.c, test/yacc/calc2.tab.c, test/yacc/calc3.tab.c, test/btyacc/error.tab.c, test/btyacc/grammar.tab.c, test/btyacc/inherit0.tab.c, test/btyacc/inherit1.tab.c, test/btyacc/inherit2.tab.c, test/btyacc/pure_calc.tab.c, test/btyacc/pure_error.tab.c, test/btyacc/quote_calc-s.tab.c, test/btyacc/quote_calc.tab.c, test/btyacc/quote_calc2-s.tab.c, test/btyacc/quote_calc2.tab.c, test/btyacc/quote_calc3-s.tab.c, test/btyacc/quote_calc3.tab.c, test/btyacc/quote_calc4-s.tab.c, test/btyacc/quote_calc4.tab.c, test/btyacc/varsyntax_calc1.tab.c, test/btyacc/btyacc_calc1.tab.c, test/btyacc/btyacc_demo.tab.c, test/btyacc/calc.tab.c, test/btyacc/calc1.tab.c, test/btyacc/code_calc.code.c, test/btyacc/code_error.code.c, test/btyacc/empty.tab.c, test/btyacc/err_inherit3.tab.c, test/btyacc/err_inherit4.tab.c, test/btyacc/err_syntax10.tab.c, test/btyacc/err_syntax11.tab.c, test/btyacc/err_syntax12.tab.c, test/btyacc/err_syntax18.tab.c, test/btyacc/err_syntax20.tab.c, test/btyacc/rename_debug.c:
+ regen
+
+ * btyaccpar.c: add casts, change types to fix strict compiler warnings
+
+ * test/btyacc/err_syntax17.tab.c, test/btyacc/err_syntax19.tab.c, test/btyacc/err_syntax2.tab.c, test/btyacc/err_syntax21.tab.c, test/btyacc/err_syntax22.tab.c, test/btyacc/err_syntax23.tab.c, test/btyacc/err_syntax24.tab.c, test/btyacc/err_syntax25.tab.c, test/btyacc/err_syntax26.tab.c, test/btyacc/err_syntax27.tab.c, test/btyacc/err_syntax3.tab.c, test/btyacc/err_syntax4.tab.c, test/btyacc/err_syntax5.tab.c, test/btyacc/err_syntax6.tab.c, test/btyacc/err_syntax7.tab.c, test/btyacc/err_syntax7a.tab.c, test/btyacc/err_syntax7b.tab.c, test/btyacc/err_syntax8.tab.c, test/btyacc/err_syntax8a.tab.c, test/btyacc/err_syntax9.tab.c, test/btyacc/err_inherit1.tab.c, test/btyacc/err_inherit2.tab.c, test/btyacc/err_inherit5.tab.c, test/btyacc/err_syntax1.tab.c, test/btyacc/err_syntax13.tab.c, test/btyacc/err_syntax14.tab.c, test/btyacc/err_syntax15.tab.c, test/btyacc/err_syntax16.tab.c:
+ regen
+
+ * output.c: gcc-warning
+
+ * test/btyacc/code_calc.tab.c, test/btyacc/code_error.tab.c: regen
+
+ * output.c: fix limit when merging real/workaround tables
+
+ * output.c:
+ for btyacc, it is possible to have no conflicts - but in that case, the
+ "ctable" was not generated at all, while the skeleton uses the table.
+ The most straightforward (workaround) is generating a dummy table which
+ rejects any state.
+
+ * test/btyacc_destroy3.y, test/btyacc_destroy2.y, test/btyacc_destroy1.y:
+ fix "make check_make"
+
+ * test/yacc/calc3.tab.c, test/yacc/ok_syntax1.tab.c, test/yacc/calc2.tab.c, test/btyacc/btyacc_destroy1.tab.c, test/btyacc/btyacc_destroy2.tab.c:
+ regen
+
+ * reader.c:
+ trim blanks from interim value in copy_param() to handle special case when
+ a space precedes a comma.
+
+ * output.c:
+ use two new functions, puts_param_types and puts_param_names, to improve
+ format of the parse_param list (by trimming space after "*") as well as
+ correcting the output of the comma-separated names (only the last name
+ was output).
+
+ * test/btyacc/ok_syntax1.tab.c, test/btyacc/btyacc_destroy3.tab.c, test/btyacc/calc2.tab.c, test/btyacc/calc3.tab.c:
+ regen
+
+ * reader.c:
+ modify copy_param() to handle resulting comma-separated list. Before, it
+ only expected a single parameter.
+
+2014-10-04 Thomas E. Dickey <tom@invisible-island.net>
+
+ * reader.c: split-out save_param() from copy_param()
+
+ * reader.c: trim_blanks() did not always convert spaces - fix.
+
+ * reader.c: fix some minor regressions with error-reporting
+
+ * aclocal.m4: update CF_XOPEN_SOURCE for Unixware change from lynx
+
+ * VERSION, package/byacc.spec, package/debian/changelog, package/mingw-byacc.spec, package/pkgsrc/Makefile:
+ bump
+
+ * reader.c:
+ modify copy_param() to accept multiple parameters, each in curly braces like
+ recent bison, as well as honoring bison's undocumented feature to accept the
+ parameters as a comma-separated list.
+
+ * test/btyacc/btyacc_destroy3.tab.c, test/btyacc/btyacc_destroy1.tab.c, test/btyacc/btyacc_destroy2.tab.c, test/btyacc/btyacc_destroy3.error, test/btyacc/btyacc_destroy3.output, test/btyacc/btyacc_destroy3.tab.h, test/btyacc/btyacc_destroy2.error, test/btyacc/btyacc_destroy2.output, test/btyacc/btyacc_destroy2.tab.h:
+ RCS_BASE
+
+2014-10-03 Thomas E. Dickey <tom@invisible-island.net>
+
+ * test/btyacc/btyacc_demo2.error, test/btyacc/btyacc_demo2.output, test/btyacc/btyacc_demo2.tab.c, test/btyacc/btyacc_demo2.tab.h, test/btyacc/btyacc_destroy1.error, test/btyacc/btyacc_destroy1.output, test/btyacc/btyacc_destroy1.tab.h, test/btyacc_destroy3.y, test/btyacc_destroy1.y, test/btyacc_destroy2.y:
+ RCS_BASE
+
+2014-10-02 Thomas E. Dickey <tom@invisible-island.net>
+
+ * main.c, reader.c, defs.h:
+ use calloc in get_line() when allocating line to ensure it is fully initialized,
+ fixes a later uninitialized value in copy_param() (FreeBSD #193499).
+
+2014-09-17 Thomas E. Dickey <tom@invisible-island.net>
+
+ * closure.c, lalr.c, output.c, defs.h:
+ rephrase odd addressing to fix Coverity #48848, #38950, #38860, not actually
+ a bug.
+
+2014-09-01 Thomas E. Dickey <tom@invisible-island.net>
+
+ * config.sub: update to 2014-07-28
+
+2014-07-27 Thomas E. Dickey <tom@invisible-island.net>
+
+ * configure: regen
+
+ * aclocal.m4: modified to support port to Minix3.2
+
+ * package/pkgsrc/Makefile, VERSION, package/byacc.spec, package/debian/changelog, package/mingw-byacc.spec:
+ bump
+
2014-07-15 Thomas E. Dickey <tom@invisible-island.net>
* aclocal.m4: resync with my-autoconf (no change to configure script)
diff --git a/contrib/byacc/MANIFEST b/contrib/byacc/MANIFEST
index 8a2b784..4ba0435 100644
--- a/contrib/byacc/MANIFEST
+++ b/contrib/byacc/MANIFEST
@@ -1,4 +1,4 @@
-MANIFEST for byacc-20140715, version t20140715
+MANIFEST for byacc-20141006, version t20141006
--------------------------------------------------------------------------------
MANIFEST this file
ACKNOWLEDGEMENTS original version of byacc - 1993
diff --git a/contrib/byacc/VERSION b/contrib/byacc/VERSION
index 088ee4d..572a8c2 100644
--- a/contrib/byacc/VERSION
+++ b/contrib/byacc/VERSION
@@ -1 +1 @@
-20140715
+20141006
diff --git a/contrib/byacc/aclocal.m4 b/contrib/byacc/aclocal.m4
index 0df47aa..627b187 100644
--- a/contrib/byacc/aclocal.m4
+++ b/contrib/byacc/aclocal.m4
@@ -1,4 +1,4 @@
-dnl $Id: aclocal.m4,v 1.35 2014/07/15 19:38:05 tom Exp $
+dnl $Id: aclocal.m4,v 1.37 2014/10/04 16:40:06 tom Exp $
dnl Macros for byacc configure script (Thomas E. Dickey)
dnl ---------------------------------------------------------------------------
dnl Copyright 2004-2013,2014 Thomas E. Dickey
@@ -54,7 +54,7 @@ define([CF_ACVERSION_COMPARE],
[ifelse([$8], , ,[$8])],
[ifelse([$9], , ,[$9])])])dnl
dnl ---------------------------------------------------------------------------
-dnl CF_ADD_CFLAGS version: 10 updated: 2010/05/26 05:38:42
+dnl CF_ADD_CFLAGS version: 11 updated: 2014/07/22 05:32:57
dnl -------------
dnl Copy non-preprocessor flags to $CFLAGS, preprocessor flags to $CPPFLAGS
dnl The second parameter if given makes this macro verbose.
@@ -79,7 +79,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[[^=]]*='\''\"[[^"]]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -116,7 +116,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[[^"]]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -1085,7 +1085,7 @@ fi
fi
])dnl
dnl ---------------------------------------------------------------------------
-dnl CF_XOPEN_SOURCE version: 46 updated: 2014/02/09 19:30:15
+dnl CF_XOPEN_SOURCE version: 48 updated: 2014/09/01 12:29:14
dnl ---------------
dnl Try to get _XOPEN_SOURCE defined properly that we can use POSIX functions,
dnl or adapt to the vendor's definitions to get equivalent functionality,
@@ -1136,6 +1136,9 @@ irix[[56]].*) #(vi
linux*|gnu*|mint*|k*bsd*-gnu) #(vi
CF_GNU_SOURCE
;;
+minix*) #(vi
+ cf_xopen_source="-D_NETBSD_SOURCE" # POSIX.1-2001 features are ifdef'd with this...
+ ;;
mirbsd*) #(vi
# setting _XOPEN_SOURCE or _POSIX_SOURCE breaks <sys/select.h> and other headers which use u_int / u_short types
cf_XOPEN_SOURCE=
@@ -1165,6 +1168,10 @@ solaris2.*) #(vi
cf_xopen_source="-D__EXTENSIONS__"
cf_cv_xopen_source=broken
;;
+sysv4.2uw2.*) # Novell/SCO UnixWare 2.x (tested on 2.1.2)
+ cf_XOPEN_SOURCE=
+ cf_POSIX_C_SOURCE=
+ ;;
*)
CF_TRY_XOPEN_SOURCE
CF_POSIX_C_SOURCE($cf_POSIX_C_SOURCE)
@@ -1172,7 +1179,7 @@ solaris2.*) #(vi
esac
if test -n "$cf_xopen_source" ; then
- CF_ADD_CFLAGS($cf_xopen_source)
+ CF_ADD_CFLAGS($cf_xopen_source,true)
fi
dnl In anything but the default case, we may have system-specific setting
diff --git a/contrib/byacc/btyaccpar.c b/contrib/byacc/btyaccpar.c
index f9c6216..d195b50 100644
--- a/contrib/byacc/btyaccpar.c
+++ b/contrib/byacc/btyaccpar.c
@@ -18,7 +18,7 @@ const char *const banner[] =
{
"/* original parser id follows */",
"/* yysccsid[] = \"@(#)yaccpar 1.9 (Berkeley) 02/21/93\" */",
- "/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */",
+ "/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */",
"",
"#define YYBYACC 1",
CONCAT1("#define YYMAJOR ", YYMAJOR),
@@ -56,7 +56,7 @@ const char *const tables[] =
"#if YYBTYACC",
"extern const YYINT yycindex[];",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"extern const YYINT yygindex[];",
"extern const YYINT yytable[];",
"extern const YYINT yycheck[];",
@@ -64,7 +64,7 @@ const char *const tables[] =
"#if YYBTYACC",
"extern const YYINT yyctable[];",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"",
"#if YYDEBUG",
"extern const char *const yyname[];",
@@ -127,7 +127,7 @@ const char *const hdr_defs[] =
"#define YYLVQUEUEGROWTH 32",
"#endif",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"",
"/* define the initial stack-sizes */",
"#ifdef YYSTACKSIZE",
@@ -172,7 +172,7 @@ const char *const hdr_defs[] =
"};",
"typedef struct YYParseState_s YYParseState;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
0
};
@@ -220,7 +220,7 @@ const char *const hdr_vars[] =
"",
"static short *yylexemes = 0;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
0
};
@@ -277,7 +277,7 @@ const char *const body_vars[] =
"",
" static short *yylexemes = 0;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
0
};
@@ -290,14 +290,14 @@ const char *const body_1[] =
"#if YYBTYACC",
"#define yytrial (yyps->save)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"",
"#if YYDEBUG",
- "#include <stdio.h> /* needed for printf */",
+ "#include <stdio.h> /* needed for printf */",
"#endif",
"",
- "#include <stdlib.h> /* needed for malloc, etc */",
- "#include <string.h> /* needed for memset */",
+ "#include <stdlib.h> /* needed for malloc, etc */",
+ "#include <string.h> /* needed for memset */",
"",
"/* allocate initial stack or double stack size, up to YYMAXDEPTH */",
"static int yygrowstack(YYSTACKDATA *data)",
@@ -404,7 +404,7 @@ const char *const body_1[] =
" free(p);",
"}",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"",
"#define YYABORT goto yyabort",
"#define YYREJECT goto yyabort",
@@ -416,7 +416,7 @@ const char *const body_1[] =
"#define YYVALID_NESTED do { if (yyps->save && \\",
" yyps->save->save == 0) goto yyvalid; } while(0)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"",
"int",
"YYPARSE_DECL()",
@@ -432,7 +432,7 @@ const char *const body_2[] =
" int yynewerrflag;",
" YYParseState *yyerrctx = NULL;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" YYLTYPE yyerror_loc_range[2]; /* position of error start & end */",
"#endif",
@@ -454,7 +454,7 @@ const char *const body_2[] =
" yyps = yyNewState(0); if (yyps == 0) goto yyenomem;",
" yyps->save = 0;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" yynerrs = 0;",
" yyerrflag = 0;",
" yychar = YYEMPTY;",
@@ -495,8 +495,8 @@ const char *const body_2[] =
" /* in trial mode; save scanner results for future parse attempts */",
" if (yylvp == yylvlim)",
" { /* Enlarge lexical value queue */",
- " int p = yylvp - yylvals;",
- " int s = yylvlim - yylvals;",
+ " size_t p = (size_t) (yylvp - yylvals);",
+ " size_t s = (size_t) (yylvlim - yylvals);",
"",
" s += YYLVQUEUEGROWTH;",
" if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;",
@@ -524,13 +524,13 @@ const char *const body_2[] =
" }",
" /* normal operation, no conflict encountered */",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" yychar = YYLEX;",
#if defined(YYBTYACC)
"#if YYBTYACC",
" } while (0);",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" if (yychar < 0) yychar = YYEOF;",
" /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */",
"#if YYDEBUG",
@@ -544,7 +544,7 @@ const char *const body_2[] =
"#if YYBTYACC",
" if (!yytrial)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" fprintf(stderr, \" <%s>\", YYSTYPE_TOSTRING(yychar, yylval));",
"#endif",
" fputc('\\n', stderr);",
@@ -598,12 +598,12 @@ const char *const body_2[] =
" save->state = yystate;",
" save->errflag = yyerrflag;",
" save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);",
- " memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
+ " memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
" save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);",
- " memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
+ " memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);",
- " memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
+ " memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
"#endif",
" ctry = yytable[yyn];",
" if (yyctable[ctry] == -1)",
@@ -658,7 +658,7 @@ const char *const body_2[] =
" yylexp--;",
" yychar = YYEMPTY;",
" }",
- " save->lexeme = yylvp - yylvals;",
+ " save->lexeme = (int) (yylvp - yylvals);",
" yyps->save = save;",
" }",
" if (yytable[yyn] == ctry)",
@@ -695,7 +695,7 @@ const char *const body_2[] =
" }",
" } /* End of code dealing with conflicts */",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" if (((yyn = yysindex[yystate]) != 0) && (yyn += yychar) >= 0 &&",
" yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)",
" {",
@@ -754,14 +754,14 @@ const char *const body_2[] =
" yyerrctx->state = yystate;",
" yyerrctx->errflag = yyerrflag;",
" yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);",
- " memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
+ " memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
" yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);",
- " memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
+ " memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);",
- " memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
+ " memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
"#endif",
- " yyerrctx->lexeme = yylvp - yylvals;",
+ " yyerrctx->lexeme = (int) (yylvp - yylvals);",
" }",
" yylvp = yylvals + save->lexeme;",
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
@@ -770,12 +770,12 @@ const char *const body_2[] =
" yylexp = yylexemes + save->lexeme;",
" yychar = YYEMPTY;",
" yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);",
- " memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
+ " memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
" yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);",
- " memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
+ " memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);",
- " memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
+ " memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
"#endif",
" ctry = ++save->ctry;",
" yystate = save->state;",
@@ -805,12 +805,12 @@ const char *const body_2[] =
" yylloc = yylpp[-1];",
"#endif",
" yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);",
- " memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
+ " memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
" yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);",
- " memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
+ " memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);",
- " memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
+ " memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
"#endif",
" yystate = yyerrctx->state;",
" yyFreeState(yyerrctx);",
@@ -820,7 +820,7 @@ const char *const body_2[] =
" }",
" if (yynewerrflag == 0) goto yyinrecovery;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"",
" YYERROR_CALL(\"syntax error\");",
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
@@ -876,7 +876,7 @@ const char *const body_2[] =
"#if YYBTYACC",
" if (!yytrial)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" YYDESTRUCT_CALL(\"error: discarding state\",",
" yystos[*yystack.s_mark], yystack.l_mark, yystack.p_mark);",
@@ -909,7 +909,7 @@ const char *const body_2[] =
"#if YYBTYACC",
" if (!yytrial)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" YYDESTRUCT_CALL(\"error: discarding token\", yychar, &yylval, &yylloc);",
"#else",
@@ -932,7 +932,7 @@ const char *const body_2[] =
"#if YYBTYACC",
" if (!yytrial)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" if (yym > 0)",
" {",
" int i;",
@@ -961,7 +961,7 @@ const char *const body_2[] =
"#if YYBTYACC",
" if (!yytrial)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" {",
" YYLLOC_DEFAULT(yyloc, &yystack.p_mark[1-yym], yym);",
" /* just in case YYERROR is invoked within the action, save",
@@ -998,7 +998,7 @@ const char *const trailer[] =
"#if YYBTYACC",
" if (!yytrial)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" fprintf(stderr, \"result is <%s>, \", YYSTYPE_TOSTRING(yystos[YYFINAL], yyval));",
"#endif",
" fprintf(stderr, \"shifting from state 0 to final state %d\\n\", YYFINAL);",
@@ -1030,8 +1030,8 @@ const char *const trailer[] =
" /* in trial mode; save scanner results for future parse attempts */",
" if (yylvp == yylvlim)",
" { /* Enlarge lexical value queue */",
- " int p = yylvp - yylvals;",
- " int s = yylvlim - yylvals;",
+ " size_t p = (size_t) (yylvp - yylvals);",
+ " size_t s = (size_t) (yylvlim - yylvals);",
"",
" s += YYLVQUEUEGROWTH;",
" if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)",
@@ -1062,13 +1062,13 @@ const char *const trailer[] =
" }",
" /* normal operation, no conflict encountered */",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" yychar = YYLEX;",
#if defined(YYBTYACC)
"#if YYBTYACC",
" } while (0);",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" if (yychar < 0) yychar = YYEOF;",
" /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */",
"#if YYDEBUG",
@@ -1097,7 +1097,7 @@ const char *const trailer[] =
"#if YYBTYACC",
" if (!yytrial)",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" fprintf(stderr, \"result is <%s>, \", YYSTYPE_TOSTRING(yystos[yystate], yyval));",
"#endif",
" fprintf(stderr, \"shifting from state %d to state %d\\n\", *yystack.s_mark, yystate);",
@@ -1140,17 +1140,17 @@ const char *const trailer[] =
" yylexp = yylexemes + yypath->lexeme;",
" yychar = YYEMPTY;",
" yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);",
- " memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
+ " memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));",
" yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);",
- " memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
+ " memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));",
"#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)",
" yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);",
- " memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
+ " memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));",
"#endif",
" yystate = yypath->state;",
" goto yyloop;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
"",
"yyoverflow:",
" YYERROR_CALL(\"yacc stack overflow\");",
@@ -1161,7 +1161,7 @@ const char *const trailer[] =
" YYERROR_CALL(\"memory exhausted\");",
"yyabort_nomem:",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" yyresult = 2;",
" goto yyreturn;",
"",
@@ -1174,7 +1174,7 @@ const char *const trailer[] =
"#if YYBTYACC",
" if (yyps->save) goto yyvalid;",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" yyresult = 0;",
"",
"yyreturn:",
@@ -1224,7 +1224,7 @@ const char *const trailer[] =
" yyFreeState(save);",
" }",
"#endif /* YYBTYACC */",
-#endif /* defined(YYBTYACC) */
+#endif /* defined(YYBTYACC) */
" yyfreestack(&yystack);",
" return (yyresult);",
"}",
diff --git a/contrib/byacc/closure.c b/contrib/byacc/closure.c
index 76003c0..f5c3f04 100644
--- a/contrib/byacc/closure.c
+++ b/contrib/byacc/closure.c
@@ -1,4 +1,4 @@
-/* $Id: closure.c,v 1.10 2014/02/19 00:45:42 Tom.Shields Exp $ */
+/* $Id: closure.c,v 1.11 2014/09/18 00:40:07 tom Exp $ */
#include "defs.h"
@@ -6,6 +6,7 @@ Value_t *itemset;
Value_t *itemsetend;
unsigned *ruleset;
+static unsigned *first_base;
static unsigned *first_derives;
static unsigned *EFF;
@@ -68,7 +69,8 @@ set_first_derives(void)
rulesetsize = WORDSIZE(nrules);
varsetsize = WORDSIZE(nvars);
- first_derives = NEW2(nvars * rulesetsize, unsigned) - ntokens * rulesetsize;
+ first_base = NEW2(nvars * rulesetsize, unsigned);
+ first_derives = first_base - ntokens * rulesetsize;
set_EFF();
@@ -176,7 +178,7 @@ finalize_closure(void)
{
FREE(itemset);
FREE(ruleset);
- FREE(first_derives + ntokens * WORDSIZE(nrules));
+ FREE(first_base);
}
#ifdef DEBUG
diff --git a/contrib/byacc/config.sub b/contrib/byacc/config.sub
index 6acbfac..88a0cb4 100755
--- a/contrib/byacc/config.sub
+++ b/contrib/byacc/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2014 Free Software Foundation, Inc.
-timestamp='2014-04-03'
+timestamp='2014-07-28'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -283,8 +283,10 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
@@ -401,8 +403,10 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
@@ -824,6 +828,10 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
msdos)
basic_machine=i386-pc
os=-msdos
@@ -1369,7 +1377,7 @@ case $os in
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
diff --git a/contrib/byacc/configure b/contrib/byacc/configure
index d2b654f..253c1cf1 100755
--- a/contrib/byacc/configure
+++ b/contrib/byacc/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 1.19 .
+# From configure.in Revision: 1.20 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by Autoconf 2.52.20121002.
#
@@ -106,6 +106,42 @@ SHELL=${CONFIG_SHELL-/bin/sh}
: ${ac_max_here_lines=38}
ac_unique_file="main.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
# Initialize some variables set by options.
ac_init_help=
@@ -854,7 +890,7 @@ if test -z "$CONFIG_SITE"; then
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
- { echo "$as_me:857: loading site script $ac_site_file" >&5
+ { echo "$as_me:893: loading site script $ac_site_file" >&5
echo "$as_me: loading site script $ac_site_file" >&6;}
cat "$ac_site_file" >&5
. "$ac_site_file"
@@ -865,7 +901,7 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special
# files actually), so we avoid doing that.
if test -f "$cache_file"; then
- { echo "$as_me:868: loading cache $cache_file" >&5
+ { echo "$as_me:904: loading cache $cache_file" >&5
echo "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . $cache_file;;
@@ -873,7 +909,7 @@ echo "$as_me: loading cache $cache_file" >&6;}
esac
fi
else
- { echo "$as_me:876: creating cache $cache_file" >&5
+ { echo "$as_me:912: creating cache $cache_file" >&5
echo "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
@@ -889,21 +925,21 @@ for ac_var in `(set) 2>&1 |
eval ac_new_val="\$ac_env_${ac_var}_value"
case $ac_old_set,$ac_new_set in
set,)
- { echo "$as_me:892: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+ { echo "$as_me:928: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { echo "$as_me:896: error: \`$ac_var' was not set in the previous run" >&5
+ { echo "$as_me:932: error: \`$ac_var' was not set in the previous run" >&5
echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
if test "x$ac_old_val" != "x$ac_new_val"; then
- { echo "$as_me:902: error: \`$ac_var' has changed since the previous run:" >&5
+ { echo "$as_me:938: error: \`$ac_var' has changed since the previous run:" >&5
echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
- { echo "$as_me:904: former value: $ac_old_val" >&5
+ { echo "$as_me:940: former value: $ac_old_val" >&5
echo "$as_me: former value: $ac_old_val" >&2;}
- { echo "$as_me:906: current value: $ac_new_val" >&5
+ { echo "$as_me:942: current value: $ac_new_val" >&5
echo "$as_me: current value: $ac_new_val" >&2;}
ac_cache_corrupted=:
fi;;
@@ -922,9 +958,9 @@ echo "$as_me: current value: $ac_new_val" >&2;}
fi
done
if $ac_cache_corrupted; then
- { echo "$as_me:925: error: changes in the environment can compromise the build" >&5
+ { echo "$as_me:961: error: changes in the environment can compromise the build" >&5
echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- { { echo "$as_me:927: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+ { { echo "$as_me:963: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
{ (exit 1); exit 1; }; }
fi
@@ -945,10 +981,10 @@ esac
echo "#! $SHELL" >conftest.sh
echo "exit 0" >>conftest.sh
chmod +x conftest.sh
-if { (echo "$as_me:948: PATH=\".;.\"; conftest.sh") >&5
+if { (echo "$as_me:984: PATH=\".;.\"; conftest.sh") >&5
(PATH=".;."; conftest.sh) 2>&5
ac_status=$?
- echo "$as_me:951: \$? = $ac_status" >&5
+ echo "$as_me:987: \$? = $ac_status" >&5
(exit $ac_status); }; then
ac_path_separator=';'
else
@@ -976,7 +1012,7 @@ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
fi
done
if test -z "$ac_aux_dir"; then
- { { echo "$as_me:979: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+ { { echo "$as_me:1015: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
{ (exit 1); exit 1; }; }
fi
@@ -986,11 +1022,11 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
# Make sure we can run config.sub.
$ac_config_sub sun4 >/dev/null 2>&1 ||
- { { echo "$as_me:989: error: cannot run $ac_config_sub" >&5
+ { { echo "$as_me:1025: error: cannot run $ac_config_sub" >&5
echo "$as_me: error: cannot run $ac_config_sub" >&2;}
{ (exit 1); exit 1; }; }
-echo "$as_me:993: checking build system type" >&5
+echo "$as_me:1029: checking build system type" >&5
echo $ECHO_N "checking build system type... $ECHO_C" >&6
if test "${ac_cv_build+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -999,23 +1035,23 @@ else
test -z "$ac_cv_build_alias" &&
ac_cv_build_alias=`$ac_config_guess`
test -z "$ac_cv_build_alias" &&
- { { echo "$as_me:1002: error: cannot guess build type; you must specify one" >&5
+ { { echo "$as_me:1038: error: cannot guess build type; you must specify one" >&5
echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
{ (exit 1); exit 1; }; }
ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
- { { echo "$as_me:1006: error: $ac_config_sub $ac_cv_build_alias failed." >&5
+ { { echo "$as_me:1042: error: $ac_config_sub $ac_cv_build_alias failed." >&5
echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed." >&2;}
{ (exit 1); exit 1; }; }
fi
-echo "$as_me:1011: result: $ac_cv_build" >&5
+echo "$as_me:1047: result: $ac_cv_build" >&5
echo "${ECHO_T}$ac_cv_build" >&6
build=$ac_cv_build
build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-echo "$as_me:1018: checking host system type" >&5
+echo "$as_me:1054: checking host system type" >&5
echo $ECHO_N "checking host system type... $ECHO_C" >&6
if test "${ac_cv_host+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1024,12 +1060,12 @@ else
test -z "$ac_cv_host_alias" &&
ac_cv_host_alias=$ac_cv_build_alias
ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
- { { echo "$as_me:1027: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+ { { echo "$as_me:1063: error: $ac_config_sub $ac_cv_host_alias failed" >&5
echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
{ (exit 1); exit 1; }; }
fi
-echo "$as_me:1032: result: $ac_cv_host" >&5
+echo "$as_me:1068: result: $ac_cv_host" >&5
echo "${ECHO_T}$ac_cv_host" >&6
host=$ac_cv_host
host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
@@ -1037,7 +1073,7 @@ host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
if test -f $srcdir/config.guess || test -f $ac_aux_dir/config.guess ; then
- echo "$as_me:1040: checking target system type" >&5
+ echo "$as_me:1076: checking target system type" >&5
echo $ECHO_N "checking target system type... $ECHO_C" >&6
if test "${ac_cv_target+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1046,12 +1082,12 @@ else
test "x$ac_cv_target_alias" = "x" &&
ac_cv_target_alias=$ac_cv_host_alias
ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
- { { echo "$as_me:1049: error: $ac_config_sub $ac_cv_target_alias failed" >&5
+ { { echo "$as_me:1085: error: $ac_config_sub $ac_cv_target_alias failed" >&5
echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
{ (exit 1); exit 1; }; }
fi
-echo "$as_me:1054: result: $ac_cv_target" >&5
+echo "$as_me:1090: result: $ac_cv_target" >&5
echo "${ECHO_T}$ac_cv_target" >&6
target=$ac_cv_target
target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
@@ -1083,13 +1119,13 @@ else
fi
test -z "$system_name" && system_name="$cf_cv_system_name"
-test -n "$cf_cv_system_name" && echo "$as_me:1086: result: Configuring for $cf_cv_system_name" >&5
+test -n "$cf_cv_system_name" && echo "$as_me:1122: result: Configuring for $cf_cv_system_name" >&5
echo "${ECHO_T}Configuring for $cf_cv_system_name" >&6
if test ".$system_name" != ".$cf_cv_system_name" ; then
- echo "$as_me:1090: result: Cached system name ($system_name) does not agree with actual ($cf_cv_system_name)" >&5
+ echo "$as_me:1126: result: Cached system name ($system_name) does not agree with actual ($cf_cv_system_name)" >&5
echo "${ECHO_T}Cached system name ($system_name) does not agree with actual ($cf_cv_system_name)" >&6
- { { echo "$as_me:1092: error: \"Please remove config.cache and try again.\"" >&5
+ { { echo "$as_me:1128: error: \"Please remove config.cache and try again.\"" >&5
echo "$as_me: error: \"Please remove config.cache and try again.\"" >&2;}
{ (exit 1); exit 1; }; }
fi
@@ -1116,7 +1152,7 @@ ac_main_return=return
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:1119: checking for $ac_word" >&5
+echo "$as_me:1155: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1131,7 +1167,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_CC="${ac_tool_prefix}gcc"
-echo "$as_me:1134: found $ac_dir/$ac_word" >&5
+echo "$as_me:1170: found $ac_dir/$ac_word" >&5
break
done
@@ -1139,10 +1175,10 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:1142: result: $CC" >&5
+ echo "$as_me:1178: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
- echo "$as_me:1145: result: no" >&5
+ echo "$as_me:1181: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -1151,7 +1187,7 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-echo "$as_me:1154: checking for $ac_word" >&5
+echo "$as_me:1190: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1166,7 +1202,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_ac_ct_CC="gcc"
-echo "$as_me:1169: found $ac_dir/$ac_word" >&5
+echo "$as_me:1205: found $ac_dir/$ac_word" >&5
break
done
@@ -1174,10 +1210,10 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- echo "$as_me:1177: result: $ac_ct_CC" >&5
+ echo "$as_me:1213: result: $ac_ct_CC" >&5
echo "${ECHO_T}$ac_ct_CC" >&6
else
- echo "$as_me:1180: result: no" >&5
+ echo "$as_me:1216: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -1190,7 +1226,7 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:1193: checking for $ac_word" >&5
+echo "$as_me:1229: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1205,7 +1241,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_CC="${ac_tool_prefix}cc"
-echo "$as_me:1208: found $ac_dir/$ac_word" >&5
+echo "$as_me:1244: found $ac_dir/$ac_word" >&5
break
done
@@ -1213,10 +1249,10 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:1216: result: $CC" >&5
+ echo "$as_me:1252: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
- echo "$as_me:1219: result: no" >&5
+ echo "$as_me:1255: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -1225,7 +1261,7 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-echo "$as_me:1228: checking for $ac_word" >&5
+echo "$as_me:1264: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1240,7 +1276,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_ac_ct_CC="cc"
-echo "$as_me:1243: found $ac_dir/$ac_word" >&5
+echo "$as_me:1279: found $ac_dir/$ac_word" >&5
break
done
@@ -1248,10 +1284,10 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- echo "$as_me:1251: result: $ac_ct_CC" >&5
+ echo "$as_me:1287: result: $ac_ct_CC" >&5
echo "${ECHO_T}$ac_ct_CC" >&6
else
- echo "$as_me:1254: result: no" >&5
+ echo "$as_me:1290: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -1264,7 +1300,7 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-echo "$as_me:1267: checking for $ac_word" >&5
+echo "$as_me:1303: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1284,7 +1320,7 @@ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
continue
fi
ac_cv_prog_CC="cc"
-echo "$as_me:1287: found $ac_dir/$ac_word" >&5
+echo "$as_me:1323: found $ac_dir/$ac_word" >&5
break
done
@@ -1306,10 +1342,10 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:1309: result: $CC" >&5
+ echo "$as_me:1345: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
- echo "$as_me:1312: result: no" >&5
+ echo "$as_me:1348: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -1320,7 +1356,7 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:1323: checking for $ac_word" >&5
+echo "$as_me:1359: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1335,7 +1371,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-echo "$as_me:1338: found $ac_dir/$ac_word" >&5
+echo "$as_me:1374: found $ac_dir/$ac_word" >&5
break
done
@@ -1343,10 +1379,10 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$as_me:1346: result: $CC" >&5
+ echo "$as_me:1382: result: $CC" >&5
echo "${ECHO_T}$CC" >&6
else
- echo "$as_me:1349: result: no" >&5
+ echo "$as_me:1385: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -1359,7 +1395,7 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-echo "$as_me:1362: checking for $ac_word" >&5
+echo "$as_me:1398: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1374,7 +1410,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_ac_ct_CC="$ac_prog"
-echo "$as_me:1377: found $ac_dir/$ac_word" >&5
+echo "$as_me:1413: found $ac_dir/$ac_word" >&5
break
done
@@ -1382,10 +1418,10 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- echo "$as_me:1385: result: $ac_ct_CC" >&5
+ echo "$as_me:1421: result: $ac_ct_CC" >&5
echo "${ECHO_T}$ac_ct_CC" >&6
else
- echo "$as_me:1388: result: no" >&5
+ echo "$as_me:1424: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -1397,32 +1433,32 @@ fi
fi
-test -z "$CC" && { { echo "$as_me:1400: error: no acceptable cc found in \$PATH" >&5
+test -z "$CC" && { { echo "$as_me:1436: error: no acceptable cc found in \$PATH" >&5
echo "$as_me: error: no acceptable cc found in \$PATH" >&2;}
{ (exit 1); exit 1; }; }
# Provide some information about the compiler.
-echo "$as_me:1405:" \
+echo "$as_me:1441:" \
"checking for C compiler version" >&5
ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:1408: \"$ac_compiler --version </dev/null >&5\"") >&5
+{ (eval echo "$as_me:1444: \"$ac_compiler --version </dev/null >&5\"") >&5
(eval $ac_compiler --version </dev/null >&5) 2>&5
ac_status=$?
- echo "$as_me:1411: \$? = $ac_status" >&5
+ echo "$as_me:1447: \$? = $ac_status" >&5
(exit $ac_status); }
-{ (eval echo "$as_me:1413: \"$ac_compiler -v </dev/null >&5\"") >&5
+{ (eval echo "$as_me:1449: \"$ac_compiler -v </dev/null >&5\"") >&5
(eval $ac_compiler -v </dev/null >&5) 2>&5
ac_status=$?
- echo "$as_me:1416: \$? = $ac_status" >&5
+ echo "$as_me:1452: \$? = $ac_status" >&5
(exit $ac_status); }
-{ (eval echo "$as_me:1418: \"$ac_compiler -V </dev/null >&5\"") >&5
+{ (eval echo "$as_me:1454: \"$ac_compiler -V </dev/null >&5\"") >&5
(eval $ac_compiler -V </dev/null >&5) 2>&5
ac_status=$?
- echo "$as_me:1421: \$? = $ac_status" >&5
+ echo "$as_me:1457: \$? = $ac_status" >&5
(exit $ac_status); }
cat >conftest.$ac_ext <<_ACEOF
-#line 1425 "configure"
+#line 1461 "configure"
#include "confdefs.h"
int
@@ -1438,13 +1474,13 @@ ac_clean_files="$ac_clean_files a.out a.exe"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-echo "$as_me:1441: checking for C compiler default output" >&5
+echo "$as_me:1477: checking for C compiler default output" >&5
echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:1444: \"$ac_link_default\"") >&5
+if { (eval echo "$as_me:1480: \"$ac_link_default\"") >&5
(eval $ac_link_default) 2>&5
ac_status=$?
- echo "$as_me:1447: \$? = $ac_status" >&5
+ echo "$as_me:1483: \$? = $ac_status" >&5
(exit $ac_status); }; then
# Find the output, starting from the most likely. This scheme is
# not robust to junk in `.', hence go to wildcards (a.*) only as a last
@@ -1467,34 +1503,34 @@ done
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
-{ { echo "$as_me:1470: error: C compiler cannot create executables" >&5
+{ { echo "$as_me:1506: error: C compiler cannot create executables" >&5
echo "$as_me: error: C compiler cannot create executables" >&2;}
{ (exit 77); exit 77; }; }
fi
ac_exeext=$ac_cv_exeext
-echo "$as_me:1476: result: $ac_file" >&5
+echo "$as_me:1512: result: $ac_file" >&5
echo "${ECHO_T}$ac_file" >&6
# Check the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-echo "$as_me:1481: checking whether the C compiler works" >&5
+echo "$as_me:1517: checking whether the C compiler works" >&5
echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
# If not cross compiling, check that we can run a simple program.
if test "$cross_compiling" != yes; then
if { ac_try='./$ac_file'
- { (eval echo "$as_me:1487: \"$ac_try\"") >&5
+ { (eval echo "$as_me:1523: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:1490: \$? = $ac_status" >&5
+ echo "$as_me:1526: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { echo "$as_me:1497: error: cannot run C compiled programs.
+ { { echo "$as_me:1533: error: cannot run C compiled programs.
If you meant to cross compile, use \`--host'." >&5
echo "$as_me: error: cannot run C compiled programs.
If you meant to cross compile, use \`--host'." >&2;}
@@ -1502,24 +1538,24 @@ If you meant to cross compile, use \`--host'." >&2;}
fi
fi
fi
-echo "$as_me:1505: result: yes" >&5
+echo "$as_me:1541: result: yes" >&5
echo "${ECHO_T}yes" >&6
rm -f a.out a.exe conftest$ac_cv_exeext
ac_clean_files=$ac_clean_files_save
# Check the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-echo "$as_me:1512: checking whether we are cross compiling" >&5
+echo "$as_me:1548: checking whether we are cross compiling" >&5
echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:1514: result: $cross_compiling" >&5
+echo "$as_me:1550: result: $cross_compiling" >&5
echo "${ECHO_T}$cross_compiling" >&6
-echo "$as_me:1517: checking for executable suffix" >&5
+echo "$as_me:1553: checking for executable suffix" >&5
echo $ECHO_N "checking for executable suffix... $ECHO_C" >&6
-if { (eval echo "$as_me:1519: \"$ac_link\"") >&5
+if { (eval echo "$as_me:1555: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
- echo "$as_me:1522: \$? = $ac_status" >&5
+ echo "$as_me:1558: \$? = $ac_status" >&5
(exit $ac_status); }; then
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
@@ -1535,25 +1571,25 @@ for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
esac
done
else
- { { echo "$as_me:1538: error: cannot compute EXEEXT: cannot compile and link" >&5
+ { { echo "$as_me:1574: error: cannot compute EXEEXT: cannot compile and link" >&5
echo "$as_me: error: cannot compute EXEEXT: cannot compile and link" >&2;}
{ (exit 1); exit 1; }; }
fi
rm -f conftest$ac_cv_exeext
-echo "$as_me:1544: result: $ac_cv_exeext" >&5
+echo "$as_me:1580: result: $ac_cv_exeext" >&5
echo "${ECHO_T}$ac_cv_exeext" >&6
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
-echo "$as_me:1550: checking for object suffix" >&5
+echo "$as_me:1586: checking for object suffix" >&5
echo $ECHO_N "checking for object suffix... $ECHO_C" >&6
if test "${ac_cv_objext+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 1556 "configure"
+#line 1592 "configure"
#include "confdefs.h"
int
@@ -1565,10 +1601,10 @@ main ()
}
_ACEOF
rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:1568: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:1604: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:1571: \$? = $ac_status" >&5
+ echo "$as_me:1607: \$? = $ac_status" >&5
(exit $ac_status); }; then
for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
case $ac_file in
@@ -1580,24 +1616,24 @@ done
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
-{ { echo "$as_me:1583: error: cannot compute OBJEXT: cannot compile" >&5
+{ { echo "$as_me:1619: error: cannot compute OBJEXT: cannot compile" >&5
echo "$as_me: error: cannot compute OBJEXT: cannot compile" >&2;}
{ (exit 1); exit 1; }; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-echo "$as_me:1590: result: $ac_cv_objext" >&5
+echo "$as_me:1626: result: $ac_cv_objext" >&5
echo "${ECHO_T}$ac_cv_objext" >&6
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-echo "$as_me:1594: checking whether we are using the GNU C compiler" >&5
+echo "$as_me:1630: checking whether we are using the GNU C compiler" >&5
echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
if test "${ac_cv_c_compiler_gnu+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 1600 "configure"
+#line 1636 "configure"
#include "confdefs.h"
int
@@ -1612,16 +1648,16 @@ main ()
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:1615: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:1651: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:1618: \$? = $ac_status" >&5
+ echo "$as_me:1654: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:1621: \"$ac_try\"") >&5
+ { (eval echo "$as_me:1657: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:1624: \$? = $ac_status" >&5
+ echo "$as_me:1660: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_compiler_gnu=yes
else
@@ -1633,19 +1669,19 @@ rm -f conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-echo "$as_me:1636: result: $ac_cv_c_compiler_gnu" >&5
+echo "$as_me:1672: result: $ac_cv_c_compiler_gnu" >&5
echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
GCC=`test $ac_compiler_gnu = yes && echo yes`
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
CFLAGS="-g"
-echo "$as_me:1642: checking whether $CC accepts -g" >&5
+echo "$as_me:1678: checking whether $CC accepts -g" >&5
echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
if test "${ac_cv_prog_cc_g+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 1648 "configure"
+#line 1684 "configure"
#include "confdefs.h"
int
@@ -1657,16 +1693,16 @@ main ()
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:1660: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:1696: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:1663: \$? = $ac_status" >&5
+ echo "$as_me:1699: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:1666: \"$ac_try\"") >&5
+ { (eval echo "$as_me:1702: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:1669: \$? = $ac_status" >&5
+ echo "$as_me:1705: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_prog_cc_g=yes
else
@@ -1676,7 +1712,7 @@ ac_cv_prog_cc_g=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:1679: result: $ac_cv_prog_cc_g" >&5
+echo "$as_me:1715: result: $ac_cv_prog_cc_g" >&5
echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
@@ -1703,16 +1739,16 @@ cat >conftest.$ac_ext <<_ACEOF
#endif
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:1706: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:1742: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:1709: \$? = $ac_status" >&5
+ echo "$as_me:1745: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:1712: \"$ac_try\"") >&5
+ { (eval echo "$as_me:1748: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:1715: \$? = $ac_status" >&5
+ echo "$as_me:1751: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
for ac_declaration in \
''\
@@ -1724,7 +1760,7 @@ if { (eval echo "$as_me:1706: \"$ac_compile\"") >&5
'void exit (int);'
do
cat >conftest.$ac_ext <<_ACEOF
-#line 1727 "configure"
+#line 1763 "configure"
#include "confdefs.h"
#include <stdlib.h>
$ac_declaration
@@ -1737,16 +1773,16 @@ exit (42);
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:1740: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:1776: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:1743: \$? = $ac_status" >&5
+ echo "$as_me:1779: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:1746: \"$ac_try\"") >&5
+ { (eval echo "$as_me:1782: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:1749: \$? = $ac_status" >&5
+ echo "$as_me:1785: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
:
else
@@ -1756,7 +1792,7 @@ continue
fi
rm -f conftest.$ac_objext conftest.$ac_ext
cat >conftest.$ac_ext <<_ACEOF
-#line 1759 "configure"
+#line 1795 "configure"
#include "confdefs.h"
$ac_declaration
int
@@ -1768,16 +1804,16 @@ exit (42);
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:1771: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:1807: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:1774: \$? = $ac_status" >&5
+ echo "$as_me:1810: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:1777: \"$ac_try\"") >&5
+ { (eval echo "$as_me:1813: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:1780: \$? = $ac_status" >&5
+ echo "$as_me:1816: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
break
else
@@ -1807,15 +1843,15 @@ ac_main_return=return
GCC_VERSION=none
if test "$GCC" = yes ; then
- echo "$as_me:1810: checking version of $CC" >&5
+ echo "$as_me:1846: checking version of $CC" >&5
echo $ECHO_N "checking version of $CC... $ECHO_C" >&6
GCC_VERSION="`${CC} --version 2>/dev/null | sed -e '2,$d' -e 's/^.*(GCC[^)]*) //' -e 's/^.*(Debian[^)]*) //' -e 's/^[^0-9.]*//' -e 's/[^0-9.].*//'`"
test -z "$GCC_VERSION" && GCC_VERSION=unknown
- echo "$as_me:1814: result: $GCC_VERSION" >&5
+ echo "$as_me:1850: result: $GCC_VERSION" >&5
echo "${ECHO_T}$GCC_VERSION" >&6
fi
-echo "$as_me:1818: checking for $CC option to accept ANSI C" >&5
+echo "$as_me:1854: checking for $CC option to accept ANSI C" >&5
echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
if test "${ac_cv_prog_cc_stdc+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -1823,7 +1859,7 @@ else
ac_cv_prog_cc_stdc=no
ac_save_CC=$CC
cat >conftest.$ac_ext <<_ACEOF
-#line 1826 "configure"
+#line 1862 "configure"
#include "confdefs.h"
#include <stdarg.h>
#include <stdio.h>
@@ -1872,16 +1908,16 @@ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIO
do
CC="$ac_save_CC $ac_arg"
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:1875: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:1911: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:1878: \$? = $ac_status" >&5
+ echo "$as_me:1914: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:1881: \"$ac_try\"") >&5
+ { (eval echo "$as_me:1917: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:1884: \$? = $ac_status" >&5
+ echo "$as_me:1920: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_prog_cc_stdc=$ac_arg
break
@@ -1898,10 +1934,10 @@ fi
case "x$ac_cv_prog_cc_stdc" in
x|xno)
- echo "$as_me:1901: result: none needed" >&5
+ echo "$as_me:1937: result: none needed" >&5
echo "${ECHO_T}none needed" >&6 ;;
*)
- echo "$as_me:1904: result: $ac_cv_prog_cc_stdc" >&5
+ echo "$as_me:1940: result: $ac_cv_prog_cc_stdc" >&5
echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
CC="$CC $ac_cv_prog_cc_stdc" ;;
esac
@@ -1909,13 +1945,13 @@ esac
# This should have been defined by AC_PROG_CC
: ${CC:=cc}
-echo "$as_me:1912: checking \$CC variable" >&5
+echo "$as_me:1948: checking \$CC variable" >&5
echo $ECHO_N "checking \$CC variable... $ECHO_C" >&6
case "$CC" in #(vi
*[\ \ ]-[IUD]*)
- echo "$as_me:1916: result: broken" >&5
+ echo "$as_me:1952: result: broken" >&5
echo "${ECHO_T}broken" >&6
- { echo "$as_me:1918: WARNING: your environment misuses the CC variable to hold CFLAGS/CPPFLAGS options" >&5
+ { echo "$as_me:1954: WARNING: your environment misuses the CC variable to hold CFLAGS/CPPFLAGS options" >&5
echo "$as_me: WARNING: your environment misuses the CC variable to hold CFLAGS/CPPFLAGS options" >&2;}
# humor him...
cf_flags=`echo "$CC" | sed -e 's/^[^ ]*[ ]//'`
@@ -1936,7 +1972,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -1977,7 +2013,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -2001,12 +2037,12 @@ fi
;;
*)
- echo "$as_me:2004: result: ok" >&5
+ echo "$as_me:2040: result: ok" >&5
echo "${ECHO_T}ok" >&6
;;
esac
-echo "$as_me:2009: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "$as_me:2045: checking whether ${MAKE-make} sets \${MAKE}" >&5
echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
@@ -2026,11 +2062,11 @@ fi
rm -f conftest.make
fi
if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
- echo "$as_me:2029: result: yes" >&5
+ echo "$as_me:2065: result: yes" >&5
echo "${ECHO_T}yes" >&6
SET_MAKE=
else
- echo "$as_me:2033: result: no" >&5
+ echo "$as_me:2069: result: no" >&5
echo "${ECHO_T}no" >&6
SET_MAKE="MAKE=${MAKE-make}"
fi
@@ -2047,7 +2083,7 @@ fi
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
-echo "$as_me:2050: checking for a BSD compatible install" >&5
+echo "$as_me:2086: checking for a BSD compatible install" >&5
echo $ECHO_N "checking for a BSD compatible install... $ECHO_C" >&6
if test -z "$INSTALL"; then
if test "${ac_cv_path_install+set}" = set; then
@@ -2096,7 +2132,7 @@ fi
INSTALL=$ac_install_sh
fi
fi
-echo "$as_me:2099: result: $INSTALL" >&5
+echo "$as_me:2135: result: $INSTALL" >&5
echo "${ECHO_T}$INSTALL" >&6
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
@@ -2107,7 +2143,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-echo "$as_me:2110: checking if filesystem supports mixed-case filenames" >&5
+echo "$as_me:2146: checking if filesystem supports mixed-case filenames" >&5
echo $ECHO_N "checking if filesystem supports mixed-case filenames... $ECHO_C" >&6
if test "${cf_cv_mixedcase+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2134,7 +2170,7 @@ else
fi
fi
-echo "$as_me:2137: result: $cf_cv_mixedcase" >&5
+echo "$as_me:2173: result: $cf_cv_mixedcase" >&5
echo "${ECHO_T}$cf_cv_mixedcase" >&6
test "$cf_cv_mixedcase" = yes &&
cat >>confdefs.h <<\EOF
@@ -2145,7 +2181,7 @@ for ac_prog in exctags ctags
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-echo "$as_me:2148: checking for $ac_word" >&5
+echo "$as_me:2184: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_CTAGS+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2160,7 +2196,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_CTAGS="$ac_prog"
-echo "$as_me:2163: found $ac_dir/$ac_word" >&5
+echo "$as_me:2199: found $ac_dir/$ac_word" >&5
break
done
@@ -2168,10 +2204,10 @@ fi
fi
CTAGS=$ac_cv_prog_CTAGS
if test -n "$CTAGS"; then
- echo "$as_me:2171: result: $CTAGS" >&5
+ echo "$as_me:2207: result: $CTAGS" >&5
echo "${ECHO_T}$CTAGS" >&6
else
- echo "$as_me:2174: result: no" >&5
+ echo "$as_me:2210: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -2182,7 +2218,7 @@ for ac_prog in exetags etags
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-echo "$as_me:2185: checking for $ac_word" >&5
+echo "$as_me:2221: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_ETAGS+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2197,7 +2233,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_ETAGS="$ac_prog"
-echo "$as_me:2200: found $ac_dir/$ac_word" >&5
+echo "$as_me:2236: found $ac_dir/$ac_word" >&5
break
done
@@ -2205,10 +2241,10 @@ fi
fi
ETAGS=$ac_cv_prog_ETAGS
if test -n "$ETAGS"; then
- echo "$as_me:2208: result: $ETAGS" >&5
+ echo "$as_me:2244: result: $ETAGS" >&5
echo "${ECHO_T}$ETAGS" >&6
else
- echo "$as_me:2211: result: no" >&5
+ echo "$as_me:2247: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -2217,7 +2253,7 @@ done
# Extract the first word of "${CTAGS:-ctags}", so it can be a program name with args.
set dummy ${CTAGS:-ctags}; ac_word=$2
-echo "$as_me:2220: checking for $ac_word" >&5
+echo "$as_me:2256: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_MAKE_LOWER_TAGS+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2232,7 +2268,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_MAKE_LOWER_TAGS="yes"
-echo "$as_me:2235: found $ac_dir/$ac_word" >&5
+echo "$as_me:2271: found $ac_dir/$ac_word" >&5
break
done
@@ -2241,17 +2277,17 @@ fi
fi
MAKE_LOWER_TAGS=$ac_cv_prog_MAKE_LOWER_TAGS
if test -n "$MAKE_LOWER_TAGS"; then
- echo "$as_me:2244: result: $MAKE_LOWER_TAGS" >&5
+ echo "$as_me:2280: result: $MAKE_LOWER_TAGS" >&5
echo "${ECHO_T}$MAKE_LOWER_TAGS" >&6
else
- echo "$as_me:2247: result: no" >&5
+ echo "$as_me:2283: result: no" >&5
echo "${ECHO_T}no" >&6
fi
if test "$cf_cv_mixedcase" = yes ; then
# Extract the first word of "${ETAGS:-etags}", so it can be a program name with args.
set dummy ${ETAGS:-etags}; ac_word=$2
-echo "$as_me:2254: checking for $ac_word" >&5
+echo "$as_me:2290: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_MAKE_UPPER_TAGS+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2266,7 +2302,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_MAKE_UPPER_TAGS="yes"
-echo "$as_me:2269: found $ac_dir/$ac_word" >&5
+echo "$as_me:2305: found $ac_dir/$ac_word" >&5
break
done
@@ -2275,10 +2311,10 @@ fi
fi
MAKE_UPPER_TAGS=$ac_cv_prog_MAKE_UPPER_TAGS
if test -n "$MAKE_UPPER_TAGS"; then
- echo "$as_me:2278: result: $MAKE_UPPER_TAGS" >&5
+ echo "$as_me:2314: result: $MAKE_UPPER_TAGS" >&5
echo "${ECHO_T}$MAKE_UPPER_TAGS" >&6
else
- echo "$as_me:2281: result: no" >&5
+ echo "$as_me:2317: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -2302,7 +2338,7 @@ for ac_prog in mawk gawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-echo "$as_me:2305: checking for $ac_word" >&5
+echo "$as_me:2341: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_AWK+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2317,7 +2353,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_AWK="$ac_prog"
-echo "$as_me:2320: found $ac_dir/$ac_word" >&5
+echo "$as_me:2356: found $ac_dir/$ac_word" >&5
break
done
@@ -2325,17 +2361,17 @@ fi
fi
AWK=$ac_cv_prog_AWK
if test -n "$AWK"; then
- echo "$as_me:2328: result: $AWK" >&5
+ echo "$as_me:2364: result: $AWK" >&5
echo "${ECHO_T}$AWK" >&6
else
- echo "$as_me:2331: result: no" >&5
+ echo "$as_me:2367: result: no" >&5
echo "${ECHO_T}no" >&6
fi
test -n "$AWK" && break
done
-test -z "$AWK" && { { echo "$as_me:2338: error: No awk program found" >&5
+test -z "$AWK" && { { echo "$as_me:2374: error: No awk program found" >&5
echo "$as_me: error: No awk program found" >&2;}
{ (exit 1); exit 1; }; }
@@ -2343,7 +2379,7 @@ for ac_prog in tdlint lint alint splint lclint
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-echo "$as_me:2346: checking for $ac_word" >&5
+echo "$as_me:2382: checking for $ac_word" >&5
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
if test "${ac_cv_prog_LINT+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -2358,7 +2394,7 @@ for ac_dir in $ac_dummy; do
test -z "$ac_dir" && ac_dir=.
$as_executable_p "$ac_dir/$ac_word" || continue
ac_cv_prog_LINT="$ac_prog"
-echo "$as_me:2361: found $ac_dir/$ac_word" >&5
+echo "$as_me:2397: found $ac_dir/$ac_word" >&5
break
done
@@ -2366,10 +2402,10 @@ fi
fi
LINT=$ac_cv_prog_LINT
if test -n "$LINT"; then
- echo "$as_me:2369: result: $LINT" >&5
+ echo "$as_me:2405: result: $LINT" >&5
echo "${ECHO_T}$LINT" >&6
else
- echo "$as_me:2372: result: no" >&5
+ echo "$as_me:2408: result: no" >&5
echo "${ECHO_T}no" >&6
fi
@@ -2414,14 +2450,14 @@ irix[56].*) #(vi
;;
linux*|gnu*|mint*|k*bsd*-gnu) #(vi
-echo "$as_me:2417: checking if we must define _GNU_SOURCE" >&5
+echo "$as_me:2453: checking if we must define _GNU_SOURCE" >&5
echo $ECHO_N "checking if we must define _GNU_SOURCE... $ECHO_C" >&6
if test "${cf_cv_gnu_source+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 2424 "configure"
+#line 2460 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -2436,16 +2472,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2439: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2475: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2442: \$? = $ac_status" >&5
+ echo "$as_me:2478: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2445: \"$ac_try\"") >&5
+ { (eval echo "$as_me:2481: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2448: \$? = $ac_status" >&5
+ echo "$as_me:2484: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_gnu_source=no
else
@@ -2454,7 +2490,7 @@ cat conftest.$ac_ext >&5
cf_save="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
cat >conftest.$ac_ext <<_ACEOF
-#line 2457 "configure"
+#line 2493 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -2469,16 +2505,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2472: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2508: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2475: \$? = $ac_status" >&5
+ echo "$as_me:2511: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2478: \"$ac_try\"") >&5
+ { (eval echo "$as_me:2514: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2481: \$? = $ac_status" >&5
+ echo "$as_me:2517: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_gnu_source=no
else
@@ -2493,11 +2529,14 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:2496: result: $cf_cv_gnu_source" >&5
+echo "$as_me:2532: result: $cf_cv_gnu_source" >&5
echo "${ECHO_T}$cf_cv_gnu_source" >&6
test "$cf_cv_gnu_source" = yes && CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
;;
+minix*) #(vi
+ cf_xopen_source="-D_NETBSD_SOURCE" # POSIX.1-2001 features are ifdef'd with this...
+ ;;
mirbsd*) #(vi
# setting _XOPEN_SOURCE or _POSIX_SOURCE breaks <sys/select.h> and other headers which use u_int / u_short types
cf_XOPEN_SOURCE=
@@ -2515,16 +2554,16 @@ cf_trim_CPPFLAGS=`echo "$cf_save_CPPFLAGS" | \
sed -e 's/-[UD]'"_POSIX_C_SOURCE"'\(=[^ ]*\)\?[ ]/ /g' \
-e 's/-[UD]'"_POSIX_C_SOURCE"'\(=[^ ]*\)\?$//g'`
-echo "$as_me:2518: checking if we should define _POSIX_C_SOURCE" >&5
+echo "$as_me:2557: checking if we should define _POSIX_C_SOURCE" >&5
echo $ECHO_N "checking if we should define _POSIX_C_SOURCE... $ECHO_C" >&6
if test "${cf_cv_posix_c_source+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
-echo "${as_me:-configure}:2524: testing if the symbol is already defined go no further ..." 1>&5
+echo "${as_me:-configure}:2563: testing if the symbol is already defined go no further ..." 1>&5
cat >conftest.$ac_ext <<_ACEOF
-#line 2527 "configure"
+#line 2566 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -2539,16 +2578,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2542: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2581: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2545: \$? = $ac_status" >&5
+ echo "$as_me:2584: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2548: \"$ac_try\"") >&5
+ { (eval echo "$as_me:2587: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2551: \$? = $ac_status" >&5
+ echo "$as_me:2590: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_posix_c_source=no
else
@@ -2569,7 +2608,7 @@ cf_want_posix_source=no
esac
if test "$cf_want_posix_source" = yes ; then
cat >conftest.$ac_ext <<_ACEOF
-#line 2572 "configure"
+#line 2611 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -2584,16 +2623,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2587: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2626: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2590: \$? = $ac_status" >&5
+ echo "$as_me:2629: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2593: \"$ac_try\"") >&5
+ { (eval echo "$as_me:2632: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2596: \$? = $ac_status" >&5
+ echo "$as_me:2635: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
:
else
@@ -2604,15 +2643,15 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "${as_me:-configure}:2607: testing ifdef from value $cf_POSIX_C_SOURCE ..." 1>&5
+echo "${as_me:-configure}:2646: testing ifdef from value $cf_POSIX_C_SOURCE ..." 1>&5
CFLAGS="$cf_trim_CFLAGS"
CPPFLAGS="$cf_trim_CPPFLAGS $cf_cv_posix_c_source"
-echo "${as_me:-configure}:2612: testing if the second compile does not leave our definition intact error ..." 1>&5
+echo "${as_me:-configure}:2651: testing if the second compile does not leave our definition intact error ..." 1>&5
cat >conftest.$ac_ext <<_ACEOF
-#line 2615 "configure"
+#line 2654 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -2627,16 +2666,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2630: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2669: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2633: \$? = $ac_status" >&5
+ echo "$as_me:2672: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2636: \"$ac_try\"") >&5
+ { (eval echo "$as_me:2675: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2639: \$? = $ac_status" >&5
+ echo "$as_me:2678: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
:
else
@@ -2652,7 +2691,7 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:2655: result: $cf_cv_posix_c_source" >&5
+echo "$as_me:2694: result: $cf_cv_posix_c_source" >&5
echo "${ECHO_T}$cf_cv_posix_c_source" >&6
if test "$cf_cv_posix_c_source" != no ; then
@@ -2674,7 +2713,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -2715,7 +2754,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -2764,16 +2803,20 @@ solaris2.*) #(vi
cf_xopen_source="-D__EXTENSIONS__"
cf_cv_xopen_source=broken
;;
+sysv4.2uw2.*) # Novell/SCO UnixWare 2.x (tested on 2.1.2)
+ cf_XOPEN_SOURCE=
+ cf_POSIX_C_SOURCE=
+ ;;
*)
-echo "$as_me:2769: checking if we should define _XOPEN_SOURCE" >&5
+echo "$as_me:2812: checking if we should define _XOPEN_SOURCE" >&5
echo $ECHO_N "checking if we should define _XOPEN_SOURCE... $ECHO_C" >&6
if test "${cf_cv_xopen_source+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 2776 "configure"
+#line 2819 "configure"
#include "confdefs.h"
#include <stdlib.h>
@@ -2792,16 +2835,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2795: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2838: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2798: \$? = $ac_status" >&5
+ echo "$as_me:2841: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2801: \"$ac_try\"") >&5
+ { (eval echo "$as_me:2844: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2804: \$? = $ac_status" >&5
+ echo "$as_me:2847: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_xopen_source=no
else
@@ -2810,7 +2853,7 @@ cat conftest.$ac_ext >&5
cf_save="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=$cf_XOPEN_SOURCE"
cat >conftest.$ac_ext <<_ACEOF
-#line 2813 "configure"
+#line 2856 "configure"
#include "confdefs.h"
#include <stdlib.h>
@@ -2829,16 +2872,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2832: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:2875: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2835: \$? = $ac_status" >&5
+ echo "$as_me:2878: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2838: \"$ac_try\"") >&5
+ { (eval echo "$as_me:2881: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2841: \$? = $ac_status" >&5
+ echo "$as_me:2884: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_xopen_source=no
else
@@ -2853,7 +2896,7 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:2856: result: $cf_cv_xopen_source" >&5
+echo "$as_me:2899: result: $cf_cv_xopen_source" >&5
echo "${ECHO_T}$cf_cv_xopen_source" >&6
if test "$cf_cv_xopen_source" != no ; then
@@ -2883,7 +2926,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -2924,7 +2967,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -2961,16 +3004,16 @@ cf_trim_CPPFLAGS=`echo "$cf_save_CPPFLAGS" | \
sed -e 's/-[UD]'"_POSIX_C_SOURCE"'\(=[^ ]*\)\?[ ]/ /g' \
-e 's/-[UD]'"_POSIX_C_SOURCE"'\(=[^ ]*\)\?$//g'`
-echo "$as_me:2964: checking if we should define _POSIX_C_SOURCE" >&5
+echo "$as_me:3007: checking if we should define _POSIX_C_SOURCE" >&5
echo $ECHO_N "checking if we should define _POSIX_C_SOURCE... $ECHO_C" >&6
if test "${cf_cv_posix_c_source+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
-echo "${as_me:-configure}:2970: testing if the symbol is already defined go no further ..." 1>&5
+echo "${as_me:-configure}:3013: testing if the symbol is already defined go no further ..." 1>&5
cat >conftest.$ac_ext <<_ACEOF
-#line 2973 "configure"
+#line 3016 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -2985,16 +3028,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:2988: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3031: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:2991: \$? = $ac_status" >&5
+ echo "$as_me:3034: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:2994: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3037: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:2997: \$? = $ac_status" >&5
+ echo "$as_me:3040: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_posix_c_source=no
else
@@ -3015,7 +3058,7 @@ cf_want_posix_source=no
esac
if test "$cf_want_posix_source" = yes ; then
cat >conftest.$ac_ext <<_ACEOF
-#line 3018 "configure"
+#line 3061 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -3030,16 +3073,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3033: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3076: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:3036: \$? = $ac_status" >&5
+ echo "$as_me:3079: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:3039: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3082: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3042: \$? = $ac_status" >&5
+ echo "$as_me:3085: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
:
else
@@ -3050,15 +3093,15 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "${as_me:-configure}:3053: testing ifdef from value $cf_POSIX_C_SOURCE ..." 1>&5
+echo "${as_me:-configure}:3096: testing ifdef from value $cf_POSIX_C_SOURCE ..." 1>&5
CFLAGS="$cf_trim_CFLAGS"
CPPFLAGS="$cf_trim_CPPFLAGS $cf_cv_posix_c_source"
-echo "${as_me:-configure}:3058: testing if the second compile does not leave our definition intact error ..." 1>&5
+echo "${as_me:-configure}:3101: testing if the second compile does not leave our definition intact error ..." 1>&5
cat >conftest.$ac_ext <<_ACEOF
-#line 3061 "configure"
+#line 3104 "configure"
#include "confdefs.h"
#include <sys/types.h>
int
@@ -3073,16 +3116,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3076: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3119: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:3079: \$? = $ac_status" >&5
+ echo "$as_me:3122: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:3082: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3125: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3085: \$? = $ac_status" >&5
+ echo "$as_me:3128: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
:
else
@@ -3098,7 +3141,7 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:3101: result: $cf_cv_posix_c_source" >&5
+echo "$as_me:3144: result: $cf_cv_posix_c_source" >&5
echo "${ECHO_T}$cf_cv_posix_c_source" >&6
if test "$cf_cv_posix_c_source" != no ; then
@@ -3120,7 +3163,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -3161,7 +3204,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -3205,7 +3248,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -3246,7 +3289,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -3254,16 +3297,25 @@ esac
done
if test -n "$cf_new_cflags" ; then
+ test -n "$verbose" && echo " add to \$CFLAGS $cf_new_cflags" 1>&6
+
+echo "${as_me:-configure}:3302: testing add to \$CFLAGS $cf_new_cflags ..." 1>&5
CFLAGS="$CFLAGS $cf_new_cflags"
fi
if test -n "$cf_new_cppflags" ; then
+ test -n "$verbose" && echo " add to \$CPPFLAGS $cf_new_cppflags" 1>&6
+
+echo "${as_me:-configure}:3310: testing add to \$CPPFLAGS $cf_new_cppflags ..." 1>&5
CPPFLAGS="$CPPFLAGS $cf_new_cppflags"
fi
if test -n "$cf_new_extra_cppflags" ; then
+ test -n "$verbose" && echo " add to \$EXTRA_CPPFLAGS $cf_new_extra_cppflags" 1>&6
+
+echo "${as_me:-configure}:3318: testing add to \$EXTRA_CPPFLAGS $cf_new_extra_cppflags ..." 1>&5
EXTRA_CPPFLAGS="$cf_new_extra_cppflags $EXTRA_CPPFLAGS"
fi
@@ -3271,10 +3323,10 @@ fi
fi
if test -n "$cf_XOPEN_SOURCE" && test -z "$cf_cv_xopen_source" ; then
- echo "$as_me:3274: checking if _XOPEN_SOURCE really is set" >&5
+ echo "$as_me:3326: checking if _XOPEN_SOURCE really is set" >&5
echo $ECHO_N "checking if _XOPEN_SOURCE really is set... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
-#line 3277 "configure"
+#line 3329 "configure"
#include "confdefs.h"
#include <stdlib.h>
int
@@ -3289,16 +3341,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3292: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3344: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:3295: \$? = $ac_status" >&5
+ echo "$as_me:3347: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:3298: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3350: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3301: \$? = $ac_status" >&5
+ echo "$as_me:3353: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_XOPEN_SOURCE_set=yes
else
@@ -3307,12 +3359,12 @@ cat conftest.$ac_ext >&5
cf_XOPEN_SOURCE_set=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
- echo "$as_me:3310: result: $cf_XOPEN_SOURCE_set" >&5
+ echo "$as_me:3362: result: $cf_XOPEN_SOURCE_set" >&5
echo "${ECHO_T}$cf_XOPEN_SOURCE_set" >&6
if test $cf_XOPEN_SOURCE_set = yes
then
cat >conftest.$ac_ext <<_ACEOF
-#line 3315 "configure"
+#line 3367 "configure"
#include "confdefs.h"
#include <stdlib.h>
int
@@ -3327,16 +3379,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3330: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3382: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:3333: \$? = $ac_status" >&5
+ echo "$as_me:3385: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:3336: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3388: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3339: \$? = $ac_status" >&5
+ echo "$as_me:3391: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_XOPEN_SOURCE_set_ok=yes
else
@@ -3347,19 +3399,19 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
if test $cf_XOPEN_SOURCE_set_ok = no
then
- { echo "$as_me:3350: WARNING: _XOPEN_SOURCE is lower than requested" >&5
+ { echo "$as_me:3402: WARNING: _XOPEN_SOURCE is lower than requested" >&5
echo "$as_me: WARNING: _XOPEN_SOURCE is lower than requested" >&2;}
fi
else
-echo "$as_me:3355: checking if we should define _XOPEN_SOURCE" >&5
+echo "$as_me:3407: checking if we should define _XOPEN_SOURCE" >&5
echo $ECHO_N "checking if we should define _XOPEN_SOURCE... $ECHO_C" >&6
if test "${cf_cv_xopen_source+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 3362 "configure"
+#line 3414 "configure"
#include "confdefs.h"
#include <stdlib.h>
@@ -3378,16 +3430,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3381: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3433: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:3384: \$? = $ac_status" >&5
+ echo "$as_me:3436: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:3387: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3439: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3390: \$? = $ac_status" >&5
+ echo "$as_me:3442: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_xopen_source=no
else
@@ -3396,7 +3448,7 @@ cat conftest.$ac_ext >&5
cf_save="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=$cf_XOPEN_SOURCE"
cat >conftest.$ac_ext <<_ACEOF
-#line 3399 "configure"
+#line 3451 "configure"
#include "confdefs.h"
#include <stdlib.h>
@@ -3415,16 +3467,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:3418: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:3470: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:3421: \$? = $ac_status" >&5
+ echo "$as_me:3473: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:3424: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3476: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3427: \$? = $ac_status" >&5
+ echo "$as_me:3479: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_xopen_source=no
else
@@ -3439,7 +3491,7 @@ fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "$as_me:3442: result: $cf_cv_xopen_source" >&5
+echo "$as_me:3494: result: $cf_cv_xopen_source" >&5
echo "${ECHO_T}$cf_cv_xopen_source" >&6
if test "$cf_cv_xopen_source" != no ; then
@@ -3469,7 +3521,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -3510,7 +3562,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -3543,7 +3595,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_main_return=return
-echo "$as_me:3546: checking how to run the C preprocessor" >&5
+echo "$as_me:3598: checking how to run the C preprocessor" >&5
echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
@@ -3564,18 +3616,18 @@ do
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat >conftest.$ac_ext <<_ACEOF
-#line 3567 "configure"
+#line 3619 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax error
_ACEOF
-if { (eval echo "$as_me:3572: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:3624: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
egrep -v '^ *\+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
- echo "$as_me:3578: \$? = $ac_status" >&5
+ echo "$as_me:3630: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
@@ -3598,17 +3650,17 @@ rm -f conftest.err conftest.$ac_ext
# OK, works on sane cases. Now check whether non-existent headers
# can be detected and how.
cat >conftest.$ac_ext <<_ACEOF
-#line 3601 "configure"
+#line 3653 "configure"
#include "confdefs.h"
#include <ac_nonexistent.h>
_ACEOF
-if { (eval echo "$as_me:3605: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:3657: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
egrep -v '^ *\+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
- echo "$as_me:3611: \$? = $ac_status" >&5
+ echo "$as_me:3663: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
@@ -3645,7 +3697,7 @@ fi
else
ac_cv_prog_CPP=$CPP
fi
-echo "$as_me:3648: result: $CPP" >&5
+echo "$as_me:3700: result: $CPP" >&5
echo "${ECHO_T}$CPP" >&6
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
@@ -3655,18 +3707,18 @@ do
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat >conftest.$ac_ext <<_ACEOF
-#line 3658 "configure"
+#line 3710 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax error
_ACEOF
-if { (eval echo "$as_me:3663: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:3715: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
egrep -v '^ *\+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
- echo "$as_me:3669: \$? = $ac_status" >&5
+ echo "$as_me:3721: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
@@ -3689,17 +3741,17 @@ rm -f conftest.err conftest.$ac_ext
# OK, works on sane cases. Now check whether non-existent headers
# can be detected and how.
cat >conftest.$ac_ext <<_ACEOF
-#line 3692 "configure"
+#line 3744 "configure"
#include "confdefs.h"
#include <ac_nonexistent.h>
_ACEOF
-if { (eval echo "$as_me:3696: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:3748: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
egrep -v '^ *\+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
- echo "$as_me:3702: \$? = $ac_status" >&5
+ echo "$as_me:3754: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
@@ -3727,7 +3779,7 @@ rm -f conftest.err conftest.$ac_ext
if $ac_preproc_ok; then
:
else
- { { echo "$as_me:3730: error: C preprocessor \"$CPP\" fails sanity check" >&5
+ { { echo "$as_me:3782: error: C preprocessor \"$CPP\" fails sanity check" >&5
echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;}
{ (exit 1); exit 1; }; }
fi
@@ -3742,23 +3794,23 @@ ac_main_return=return
for ac_header in fcntl.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:3745: checking for $ac_header" >&5
+echo "$as_me:3797: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
if eval "test \"\${$as_ac_Header+set}\" = set"; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 3751 "configure"
+#line 3803 "configure"
#include "confdefs.h"
#include <$ac_header>
_ACEOF
-if { (eval echo "$as_me:3755: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:3807: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
egrep -v '^ *\+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
- echo "$as_me:3761: \$? = $ac_status" >&5
+ echo "$as_me:3813: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
@@ -3777,7 +3829,7 @@ else
fi
rm -f conftest.err conftest.$ac_ext
fi
-echo "$as_me:3780: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "$as_me:3832: result: `eval echo '${'$as_ac_Header'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
if test `eval echo '${'$as_ac_Header'}'` = yes; then
cat >>confdefs.h <<EOF
@@ -3787,7 +3839,7 @@ EOF
fi
done
-echo "$as_me:3790: checking for working mkstemp" >&5
+echo "$as_me:3842: checking for working mkstemp" >&5
echo $ECHO_N "checking for working mkstemp... $ECHO_C" >&6
if test "${cf_cv_func_mkstemp+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -3798,7 +3850,7 @@ if test "$cross_compiling" = yes; then
cf_cv_func_mkstemp=maybe
else
cat >conftest.$ac_ext <<_ACEOF
-#line 3801 "configure"
+#line 3853 "configure"
#include "confdefs.h"
#include <sys/types.h>
@@ -3836,15 +3888,15 @@ int main()
_ACEOF
rm -f conftest$ac_exeext
-if { (eval echo "$as_me:3839: \"$ac_link\"") >&5
+if { (eval echo "$as_me:3891: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
- echo "$as_me:3842: \$? = $ac_status" >&5
+ echo "$as_me:3894: \$? = $ac_status" >&5
(exit $ac_status); } && { ac_try='./conftest$ac_exeext'
- { (eval echo "$as_me:3844: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3896: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3847: \$? = $ac_status" >&5
+ echo "$as_me:3899: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
cf_cv_func_mkstemp=yes
@@ -3859,16 +3911,16 @@ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
fi
-echo "$as_me:3862: result: $cf_cv_func_mkstemp" >&5
+echo "$as_me:3914: result: $cf_cv_func_mkstemp" >&5
echo "${ECHO_T}$cf_cv_func_mkstemp" >&6
if test "x$cf_cv_func_mkstemp" = xmaybe ; then
- echo "$as_me:3865: checking for mkstemp" >&5
+ echo "$as_me:3917: checking for mkstemp" >&5
echo $ECHO_N "checking for mkstemp... $ECHO_C" >&6
if test "${ac_cv_func_mkstemp+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 3871 "configure"
+#line 3923 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char mkstemp (); below. */
@@ -3899,16 +3951,16 @@ f = mkstemp; /* workaround for ICC 12.0.3 */ if (f == 0) return 1;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:3902: \"$ac_link\"") >&5
+if { (eval echo "$as_me:3954: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
- echo "$as_me:3905: \$? = $ac_status" >&5
+ echo "$as_me:3957: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:3908: \"$ac_try\"") >&5
+ { (eval echo "$as_me:3960: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3911: \$? = $ac_status" >&5
+ echo "$as_me:3963: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_func_mkstemp=yes
else
@@ -3918,7 +3970,7 @@ ac_cv_func_mkstemp=no
fi
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:3921: result: $ac_cv_func_mkstemp" >&5
+echo "$as_me:3973: result: $ac_cv_func_mkstemp" >&5
echo "${ECHO_T}$ac_cv_func_mkstemp" >&6
fi
@@ -3933,13 +3985,13 @@ fi
for ac_func in vsnprintf
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:3936: checking for $ac_func" >&5
+echo "$as_me:3988: checking for $ac_func" >&5
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
if eval "test \"\${$as_ac_var+set}\" = set"; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 3942 "configure"
+#line 3994 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func (); below. */
@@ -3970,16 +4022,16 @@ f = $ac_func; /* workaround for ICC 12.0.3 */ if (f == 0) return 1;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:3973: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4025: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
- echo "$as_me:3976: \$? = $ac_status" >&5
+ echo "$as_me:4028: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:3979: \"$ac_try\"") >&5
+ { (eval echo "$as_me:4031: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:3982: \$? = $ac_status" >&5
+ echo "$as_me:4034: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
eval "$as_ac_var=yes"
else
@@ -3989,7 +4041,7 @@ eval "$as_ac_var=no"
fi
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
-echo "$as_me:3992: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "$as_me:4044: result: `eval echo '${'$as_ac_var'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
if test `eval echo '${'$as_ac_var'}'` = yes; then
cat >>confdefs.h <<EOF
@@ -3999,7 +4051,7 @@ EOF
fi
done
-echo "$as_me:4002: checking for maximum table size" >&5
+echo "$as_me:4054: checking for maximum table size" >&5
echo $ECHO_N "checking for maximum table size... $ECHO_C" >&6
# Check whether --with-max-table-size or --without-max-table-size was given.
@@ -4009,12 +4061,12 @@ if test "${with_max_table_size+set}" = set; then
fi;
if test -n "$with_max_table_size"
then
- echo "$as_me:4012: result: $with_max_table_size" >&5
+ echo "$as_me:4064: result: $with_max_table_size" >&5
echo "${ECHO_T}$with_max_table_size" >&6
check=`expr "$with_max_table_size" + 0`
if test "x$check" != "x$with_max_table_size"
then
- { { echo "$as_me:4017: error: invalid value for --with-max-table-size: $with_max_table_size" >&5
+ { { echo "$as_me:4069: error: invalid value for --with-max-table-size: $with_max_table_size" >&5
echo "$as_me: error: invalid value for --with-max-table-size: $with_max_table_size" >&2;}
{ (exit 1); exit 1; }; }
fi
@@ -4024,11 +4076,11 @@ cat >>confdefs.h <<EOF
EOF
else
- echo "$as_me:4027: result: default" >&5
+ echo "$as_me:4079: result: default" >&5
echo "${ECHO_T}default" >&6
fi
-echo "$as_me:4031: checking if backtracking extension is wanted" >&5
+echo "$as_me:4083: checking if backtracking extension is wanted" >&5
echo $ECHO_N "checking if backtracking extension is wanted... $ECHO_C" >&6
# Check whether --enable-btyacc or --disable-btyacc was given.
@@ -4036,7 +4088,7 @@ if test "${enable_btyacc+set}" = set; then
enableval="$enable_btyacc"
fi;
-echo "$as_me:4039: result: $enable_btyacc" >&5
+echo "$as_me:4091: result: $enable_btyacc" >&5
echo "${ECHO_T}$enable_btyacc" >&6
if test "$enable_btyacc" = "yes"; then
@@ -4051,7 +4103,7 @@ fi
if ( test "$GCC" = yes || test "$GXX" = yes )
then
-echo "$as_me:4054: checking if you want to check for gcc warnings" >&5
+echo "$as_me:4106: checking if you want to check for gcc warnings" >&5
echo $ECHO_N "checking if you want to check for gcc warnings... $ECHO_C" >&6
# Check whether --with-warnings or --without-warnings was given.
@@ -4061,7 +4113,7 @@ if test "${with_warnings+set}" = set; then
else
cf_opt_with_warnings=no
fi;
-echo "$as_me:4064: result: $cf_opt_with_warnings" >&5
+echo "$as_me:4116: result: $cf_opt_with_warnings" >&5
echo "${ECHO_T}$cf_opt_with_warnings" >&6
if test "$cf_opt_with_warnings" != no ; then
@@ -4083,10 +4135,10 @@ cat > conftest.i <<EOF
EOF
if test "$GCC" = yes
then
- { echo "$as_me:4086: checking for $CC __attribute__ directives..." >&5
+ { echo "$as_me:4138: checking for $CC __attribute__ directives..." >&5
echo "$as_me: checking for $CC __attribute__ directives..." >&6;}
cat > conftest.$ac_ext <<EOF
-#line 4089 "${as_me:-configure}"
+#line 4141 "${as_me:-configure}"
#include "confdefs.h"
#include "conftest.h"
#include "conftest.i"
@@ -4135,12 +4187,12 @@ EOF
;;
esac
- if { (eval echo "$as_me:4138: \"$ac_compile\"") >&5
+ if { (eval echo "$as_me:4190: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:4141: \$? = $ac_status" >&5
+ echo "$as_me:4193: \$? = $ac_status" >&5
(exit $ac_status); }; then
- test -n "$verbose" && echo "$as_me:4143: result: ... $cf_attribute" >&5
+ test -n "$verbose" && echo "$as_me:4195: result: ... $cf_attribute" >&5
echo "${ECHO_T}... $cf_attribute" >&6
cat conftest.h >>confdefs.h
case $cf_attribute in #(vi
@@ -4204,12 +4256,12 @@ INTEL_COMPILER=no
if test "$GCC" = yes ; then
case $host_os in
linux*|gnu*)
- echo "$as_me:4207: checking if this is really Intel C compiler" >&5
+ echo "$as_me:4259: checking if this is really Intel C compiler" >&5
echo $ECHO_N "checking if this is really Intel C compiler... $ECHO_C" >&6
cf_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -no-gcc"
cat >conftest.$ac_ext <<_ACEOF
-#line 4212 "configure"
+#line 4264 "configure"
#include "confdefs.h"
int
@@ -4226,16 +4278,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:4229: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:4281: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:4232: \$? = $ac_status" >&5
+ echo "$as_me:4284: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:4235: \"$ac_try\"") >&5
+ { (eval echo "$as_me:4287: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:4238: \$? = $ac_status" >&5
+ echo "$as_me:4290: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
INTEL_COMPILER=yes
cf_save_CFLAGS="$cf_save_CFLAGS -we147"
@@ -4246,7 +4298,7 @@ cat conftest.$ac_ext >&5
fi
rm -f conftest.$ac_objext conftest.$ac_ext
CFLAGS="$cf_save_CFLAGS"
- echo "$as_me:4249: result: $INTEL_COMPILER" >&5
+ echo "$as_me:4301: result: $INTEL_COMPILER" >&5
echo "${ECHO_T}$INTEL_COMPILER" >&6
;;
esac
@@ -4255,12 +4307,12 @@ fi
CLANG_COMPILER=no
if test "$GCC" = yes ; then
- echo "$as_me:4258: checking if this is really Clang C compiler" >&5
+ echo "$as_me:4310: checking if this is really Clang C compiler" >&5
echo $ECHO_N "checking if this is really Clang C compiler... $ECHO_C" >&6
cf_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Qunused-arguments"
cat >conftest.$ac_ext <<_ACEOF
-#line 4263 "configure"
+#line 4315 "configure"
#include "confdefs.h"
int
@@ -4277,16 +4329,16 @@ make an error
}
_ACEOF
rm -f conftest.$ac_objext
-if { (eval echo "$as_me:4280: \"$ac_compile\"") >&5
+if { (eval echo "$as_me:4332: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:4283: \$? = $ac_status" >&5
+ echo "$as_me:4335: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:4286: \"$ac_try\"") >&5
+ { (eval echo "$as_me:4338: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:4289: \$? = $ac_status" >&5
+ echo "$as_me:4341: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
CLANG_COMPILER=yes
cf_save_CFLAGS="$cf_save_CFLAGS -Qunused-arguments"
@@ -4297,12 +4349,12 @@ cat conftest.$ac_ext >&5
fi
rm -f conftest.$ac_objext conftest.$ac_ext
CFLAGS="$cf_save_CFLAGS"
- echo "$as_me:4300: result: $CLANG_COMPILER" >&5
+ echo "$as_me:4352: result: $CLANG_COMPILER" >&5
echo "${ECHO_T}$CLANG_COMPILER" >&6
fi
cat > conftest.$ac_ext <<EOF
-#line 4305 "${as_me:-configure}"
+#line 4357 "${as_me:-configure}"
int main(int argc, char *argv[]) { return (argv[argc-1] == 0) ; }
EOF
@@ -4319,7 +4371,7 @@ then
# remark #981: operands are evaluated in unspecified order
# warning #279: controlling expression is constant
- { echo "$as_me:4322: checking for $CC warning options..." >&5
+ { echo "$as_me:4374: checking for $CC warning options..." >&5
echo "$as_me: checking for $CC warning options..." >&6;}
cf_save_CFLAGS="$CFLAGS"
EXTRA_CFLAGS="-Wall"
@@ -4335,12 +4387,12 @@ echo "$as_me: checking for $CC warning options..." >&6;}
wd981
do
CFLAGS="$cf_save_CFLAGS $EXTRA_CFLAGS -$cf_opt"
- if { (eval echo "$as_me:4338: \"$ac_compile\"") >&5
+ if { (eval echo "$as_me:4390: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:4341: \$? = $ac_status" >&5
+ echo "$as_me:4393: \$? = $ac_status" >&5
(exit $ac_status); }; then
- test -n "$verbose" && echo "$as_me:4343: result: ... -$cf_opt" >&5
+ test -n "$verbose" && echo "$as_me:4395: result: ... -$cf_opt" >&5
echo "${ECHO_T}... -$cf_opt" >&6
EXTRA_CFLAGS="$EXTRA_CFLAGS -$cf_opt"
fi
@@ -4349,7 +4401,7 @@ echo "${ECHO_T}... -$cf_opt" >&6
elif test "$GCC" = yes
then
- { echo "$as_me:4352: checking for $CC warning options..." >&5
+ { echo "$as_me:4404: checking for $CC warning options..." >&5
echo "$as_me: checking for $CC warning options..." >&6;}
cf_save_CFLAGS="$CFLAGS"
EXTRA_CFLAGS=
@@ -4373,12 +4425,12 @@ echo "$as_me: checking for $CC warning options..." >&6;}
Wundef $cf_gcc_warnings $cf_warn_CONST Wwrite-strings
do
CFLAGS="$cf_save_CFLAGS $EXTRA_CFLAGS -$cf_opt"
- if { (eval echo "$as_me:4376: \"$ac_compile\"") >&5
+ if { (eval echo "$as_me:4428: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
- echo "$as_me:4379: \$? = $ac_status" >&5
+ echo "$as_me:4431: \$? = $ac_status" >&5
(exit $ac_status); }; then
- test -n "$verbose" && echo "$as_me:4381: result: ... -$cf_opt" >&5
+ test -n "$verbose" && echo "$as_me:4433: result: ... -$cf_opt" >&5
echo "${ECHO_T}... -$cf_opt" >&6
case $cf_opt in #(vi
Wcast-qual) #(vi
@@ -4389,7 +4441,7 @@ echo "${ECHO_T}... -$cf_opt" >&6
[34].*)
test -n "$verbose" && echo " feature is broken in gcc $GCC_VERSION" 1>&6
-echo "${as_me:-configure}:4392: testing feature is broken in gcc $GCC_VERSION ..." 1>&5
+echo "${as_me:-configure}:4444: testing feature is broken in gcc $GCC_VERSION ..." 1>&5
continue;;
esac
@@ -4399,7 +4451,7 @@ echo "${as_me:-configure}:4392: testing feature is broken in gcc $GCC_VERSION ..
[12].*)
test -n "$verbose" && echo " feature is broken in gcc $GCC_VERSION" 1>&6
-echo "${as_me:-configure}:4402: testing feature is broken in gcc $GCC_VERSION ..." 1>&5
+echo "${as_me:-configure}:4454: testing feature is broken in gcc $GCC_VERSION ..." 1>&5
continue;;
esac
@@ -4415,7 +4467,7 @@ rm -rf conftest*
fi
fi
-echo "$as_me:4418: checking if you want to see long compiling messages" >&5
+echo "$as_me:4470: checking if you want to see long compiling messages" >&5
echo $ECHO_N "checking if you want to see long compiling messages... $ECHO_C" >&6
# Check whether --enable-echo or --disable-echo was given.
@@ -4449,10 +4501,10 @@ else
ECHO_CC=''
fi;
-echo "$as_me:4452: result: $enableval" >&5
+echo "$as_me:4504: result: $enableval" >&5
echo "${ECHO_T}$enableval" >&6
-echo "$as_me:4455: checking if you want to use dmalloc for testing" >&5
+echo "$as_me:4507: checking if you want to use dmalloc for testing" >&5
echo $ECHO_N "checking if you want to use dmalloc for testing... $ECHO_C" >&6
# Check whether --with-dmalloc or --without-dmalloc was given.
@@ -4469,7 +4521,7 @@ EOF
else
with_dmalloc=
fi;
-echo "$as_me:4472: result: ${with_dmalloc:-no}" >&5
+echo "$as_me:4524: result: ${with_dmalloc:-no}" >&5
echo "${ECHO_T}${with_dmalloc:-no}" >&6
case .$with_cflags in #(vi
@@ -4494,7 +4546,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -4535,7 +4587,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -4563,23 +4615,23 @@ fi
esac
if test "$with_dmalloc" = yes ; then
- echo "$as_me:4566: checking for dmalloc.h" >&5
+ echo "$as_me:4618: checking for dmalloc.h" >&5
echo $ECHO_N "checking for dmalloc.h... $ECHO_C" >&6
if test "${ac_cv_header_dmalloc_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 4572 "configure"
+#line 4624 "configure"
#include "confdefs.h"
#include <dmalloc.h>
_ACEOF
-if { (eval echo "$as_me:4576: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:4628: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
egrep -v '^ *\+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
- echo "$as_me:4582: \$? = $ac_status" >&5
+ echo "$as_me:4634: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
@@ -4598,11 +4650,11 @@ else
fi
rm -f conftest.err conftest.$ac_ext
fi
-echo "$as_me:4601: result: $ac_cv_header_dmalloc_h" >&5
+echo "$as_me:4653: result: $ac_cv_header_dmalloc_h" >&5
echo "${ECHO_T}$ac_cv_header_dmalloc_h" >&6
if test $ac_cv_header_dmalloc_h = yes; then
-echo "$as_me:4605: checking for dmalloc_debug in -ldmalloc" >&5
+echo "$as_me:4657: checking for dmalloc_debug in -ldmalloc" >&5
echo $ECHO_N "checking for dmalloc_debug in -ldmalloc... $ECHO_C" >&6
if test "${ac_cv_lib_dmalloc_dmalloc_debug+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -4610,7 +4662,7 @@ else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldmalloc $LIBS"
cat >conftest.$ac_ext <<_ACEOF
-#line 4613 "configure"
+#line 4665 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
@@ -4629,16 +4681,16 @@ dmalloc_debug ();
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:4632: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4684: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
- echo "$as_me:4635: \$? = $ac_status" >&5
+ echo "$as_me:4687: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:4638: \"$ac_try\"") >&5
+ { (eval echo "$as_me:4690: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:4641: \$? = $ac_status" >&5
+ echo "$as_me:4693: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_dmalloc_dmalloc_debug=yes
else
@@ -4649,7 +4701,7 @@ fi
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:4652: result: $ac_cv_lib_dmalloc_dmalloc_debug" >&5
+echo "$as_me:4704: result: $ac_cv_lib_dmalloc_dmalloc_debug" >&5
echo "${ECHO_T}$ac_cv_lib_dmalloc_dmalloc_debug" >&6
if test $ac_cv_lib_dmalloc_dmalloc_debug = yes; then
cat >>confdefs.h <<EOF
@@ -4664,7 +4716,7 @@ fi
fi
-echo "$as_me:4667: checking if you want to use dbmalloc for testing" >&5
+echo "$as_me:4719: checking if you want to use dbmalloc for testing" >&5
echo $ECHO_N "checking if you want to use dbmalloc for testing... $ECHO_C" >&6
# Check whether --with-dbmalloc or --without-dbmalloc was given.
@@ -4681,7 +4733,7 @@ EOF
else
with_dbmalloc=
fi;
-echo "$as_me:4684: result: ${with_dbmalloc:-no}" >&5
+echo "$as_me:4736: result: ${with_dbmalloc:-no}" >&5
echo "${ECHO_T}${with_dbmalloc:-no}" >&6
case .$with_cflags in #(vi
@@ -4706,7 +4758,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -4747,7 +4799,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -4775,23 +4827,23 @@ fi
esac
if test "$with_dbmalloc" = yes ; then
- echo "$as_me:4778: checking for dbmalloc.h" >&5
+ echo "$as_me:4830: checking for dbmalloc.h" >&5
echo $ECHO_N "checking for dbmalloc.h... $ECHO_C" >&6
if test "${ac_cv_header_dbmalloc_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
-#line 4784 "configure"
+#line 4836 "configure"
#include "confdefs.h"
#include <dbmalloc.h>
_ACEOF
-if { (eval echo "$as_me:4788: \"$ac_cpp conftest.$ac_ext\"") >&5
+if { (eval echo "$as_me:4840: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
egrep -v '^ *\+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
- echo "$as_me:4794: \$? = $ac_status" >&5
+ echo "$as_me:4846: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
@@ -4810,11 +4862,11 @@ else
fi
rm -f conftest.err conftest.$ac_ext
fi
-echo "$as_me:4813: result: $ac_cv_header_dbmalloc_h" >&5
+echo "$as_me:4865: result: $ac_cv_header_dbmalloc_h" >&5
echo "${ECHO_T}$ac_cv_header_dbmalloc_h" >&6
if test $ac_cv_header_dbmalloc_h = yes; then
-echo "$as_me:4817: checking for debug_malloc in -ldbmalloc" >&5
+echo "$as_me:4869: checking for debug_malloc in -ldbmalloc" >&5
echo $ECHO_N "checking for debug_malloc in -ldbmalloc... $ECHO_C" >&6
if test "${ac_cv_lib_dbmalloc_debug_malloc+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -4822,7 +4874,7 @@ else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldbmalloc $LIBS"
cat >conftest.$ac_ext <<_ACEOF
-#line 4825 "configure"
+#line 4877 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
@@ -4841,16 +4893,16 @@ debug_malloc ();
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:4844: \"$ac_link\"") >&5
+if { (eval echo "$as_me:4896: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
- echo "$as_me:4847: \$? = $ac_status" >&5
+ echo "$as_me:4899: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest$ac_exeext'
- { (eval echo "$as_me:4850: \"$ac_try\"") >&5
+ { (eval echo "$as_me:4902: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
- echo "$as_me:4853: \$? = $ac_status" >&5
+ echo "$as_me:4905: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_dbmalloc_debug_malloc=yes
else
@@ -4861,7 +4913,7 @@ fi
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-echo "$as_me:4864: result: $ac_cv_lib_dbmalloc_debug_malloc" >&5
+echo "$as_me:4916: result: $ac_cv_lib_dbmalloc_debug_malloc" >&5
echo "${ECHO_T}$ac_cv_lib_dbmalloc_debug_malloc" >&6
if test $ac_cv_lib_dbmalloc_debug_malloc = yes; then
cat >>confdefs.h <<EOF
@@ -4876,7 +4928,7 @@ fi
fi
-echo "$as_me:4879: checking if you want to use valgrind for testing" >&5
+echo "$as_me:4931: checking if you want to use valgrind for testing" >&5
echo $ECHO_N "checking if you want to use valgrind for testing... $ECHO_C" >&6
# Check whether --with-valgrind or --without-valgrind was given.
@@ -4893,7 +4945,7 @@ EOF
else
with_valgrind=
fi;
-echo "$as_me:4896: result: ${with_valgrind:-no}" >&5
+echo "$as_me:4948: result: ${with_valgrind:-no}" >&5
echo "${ECHO_T}${with_valgrind:-no}" >&6
case .$with_cflags in #(vi
@@ -4918,7 +4970,7 @@ no)
-D*)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^-D[^=]*='\''\"[^"]*//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=yes
@@ -4959,7 +5011,7 @@ yes)
cf_tst_cflags=`echo ${cf_add_cflags} |sed -e 's/^[^"]*"'\''//'`
- test "${cf_add_cflags}" != "${cf_tst_cflags}" \
+ test "x${cf_add_cflags}" != "x${cf_tst_cflags}" \
&& test -z "${cf_tst_cflags}" \
&& cf_fix_cppflags=no
;;
@@ -4986,7 +5038,7 @@ fi
;;
esac
-echo "$as_me:4989: checking if you want to perform memory-leak testing" >&5
+echo "$as_me:5041: checking if you want to perform memory-leak testing" >&5
echo $ECHO_N "checking if you want to perform memory-leak testing... $ECHO_C" >&6
# Check whether --enable-leaks or --disable-leaks was given.
@@ -4996,7 +5048,7 @@ if test "${enable_leaks+set}" = set; then
else
: ${with_no_leaks:=no}
fi;
-echo "$as_me:4999: result: $with_no_leaks" >&5
+echo "$as_me:5051: result: $with_no_leaks" >&5
echo "${ECHO_T}$with_no_leaks" >&6
if test "$with_no_leaks" = yes ; then
@@ -5011,6 +5063,243 @@ EOF
fi
+echo "$as_me:5066: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 5072 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+_ACEOF
+if { (eval echo "$as_me:5080: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:5086: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+#line 5108 "configure"
+#include "confdefs.h"
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -rf conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+#line 5126 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -rf conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 5147 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ $ac_main_return(2);
+ $ac_main_return (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:5173: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:5176: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:5178: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:5181: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:5194: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:5210: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 5216 "configure"
+#include "confdefs.h"
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:5222: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:5225: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:5228: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:5231: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:5241: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+EOF
+
+fi
+done
+
+echo "$as_me:5251: checking for mode_t" >&5
+echo $ECHO_N "checking for mode_t... $ECHO_C" >&6
+if test "${ac_cv_type_mode_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 5257 "configure"
+#include "confdefs.h"
+$ac_includes_default
+int
+main ()
+{
+if ((mode_t *) 0)
+ return 0;
+if (sizeof (mode_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:5272: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:5275: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:5278: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:5281: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_mode_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_mode_t=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:5291: result: $ac_cv_type_mode_t" >&5
+echo "${ECHO_T}$ac_cv_type_mode_t" >&6
+if test $ac_cv_type_mode_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<EOF
+#define mode_t int
+EOF
+
+fi
+
### output makefile
ac_config_files="$ac_config_files makefile"
cat >confcache <<\_ACEOF
@@ -5092,7 +5381,7 @@ DEFS=-DHAVE_CONFIG_H
: ${CONFIG_STATUS=./config.status}
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:5095: creating $CONFIG_STATUS" >&5
+{ echo "$as_me:5384: creating $CONFIG_STATUS" >&5
echo "$as_me: creating $CONFIG_STATUS" >&6;}
cat >$CONFIG_STATUS <<_ACEOF
#! $SHELL
@@ -5265,7 +5554,7 @@ cat >>$CONFIG_STATUS <<\EOF
echo "$ac_cs_version"; exit 0 ;;
--he | --h)
# Conflict between --help and --header
- { { echo "$as_me:5268: error: ambiguous option: $1
+ { { echo "$as_me:5557: error: ambiguous option: $1
Try \`$0 --help' for more information." >&5
echo "$as_me: error: ambiguous option: $1
Try \`$0 --help' for more information." >&2;}
@@ -5284,7 +5573,7 @@ Try \`$0 --help' for more information." >&2;}
ac_need_defaults=false;;
# This is an error.
- -*) { { echo "$as_me:5287: error: unrecognized option: $1
+ -*) { { echo "$as_me:5576: error: unrecognized option: $1
Try \`$0 --help' for more information." >&5
echo "$as_me: error: unrecognized option: $1
Try \`$0 --help' for more information." >&2;}
@@ -5321,7 +5610,7 @@ do
# Handling of arguments.
"makefile" ) CONFIG_FILES="$CONFIG_FILES makefile" ;;
"config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config_h.in" ;;
- *) { { echo "$as_me:5324: error: invalid argument: $ac_config_target" >&5
+ *) { { echo "$as_me:5613: error: invalid argument: $ac_config_target" >&5
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
{ (exit 1); exit 1; }; };;
esac
@@ -5556,7 +5845,7 @@ done; }
esac
if test x"$ac_file" != x-; then
- { echo "$as_me:5559: creating $ac_file" >&5
+ { echo "$as_me:5848: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
rm -f "$ac_file"
fi
@@ -5574,7 +5863,7 @@ echo "$as_me: creating $ac_file" >&6;}
-) echo $tmp/stdin ;;
[\\/$]*)
# Absolute (can't be DOS-style, as IFS=:)
- test -f "$f" || { { echo "$as_me:5577: error: cannot find input file: $f" >&5
+ test -f "$f" || { { echo "$as_me:5866: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
echo $f;;
@@ -5587,7 +5876,7 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
echo $srcdir/$f
else
# /dev/null tree
- { { echo "$as_me:5590: error: cannot find input file: $f" >&5
+ { { echo "$as_me:5879: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
fi;;
@@ -5603,7 +5892,7 @@ cat >>$CONFIG_STATUS <<\EOF
if test -n "$ac_seen"; then
ac_used=`grep '@datarootdir@' $ac_item`
if test -z "$ac_used"; then
- { echo "$as_me:5606: WARNING: datarootdir was used implicitly but not set:
+ { echo "$as_me:5895: WARNING: datarootdir was used implicitly but not set:
$ac_seen" >&5
echo "$as_me: WARNING: datarootdir was used implicitly but not set:
$ac_seen" >&2;}
@@ -5612,7 +5901,7 @@ $ac_seen" >&2;}
fi
ac_seen=`grep '${datarootdir}' $ac_item`
if test -n "$ac_seen"; then
- { echo "$as_me:5615: WARNING: datarootdir was used explicitly but not set:
+ { echo "$as_me:5904: WARNING: datarootdir was used explicitly but not set:
$ac_seen" >&5
echo "$as_me: WARNING: datarootdir was used explicitly but not set:
$ac_seen" >&2;}
@@ -5649,7 +5938,7 @@ s,@INSTALL@,$ac_INSTALL,;t t
ac_init=`egrep '[ ]*'$ac_name'[ ]*=' $ac_file`
if test -z "$ac_init"; then
ac_seen=`echo "$ac_seen" |sed -e 's,^,'$ac_file':,'`
- { echo "$as_me:5652: WARNING: Variable $ac_name is used but was not set:
+ { echo "$as_me:5941: WARNING: Variable $ac_name is used but was not set:
$ac_seen" >&5
echo "$as_me: WARNING: Variable $ac_name is used but was not set:
$ac_seen" >&2;}
@@ -5660,7 +5949,7 @@ $ac_seen" >&2;}
egrep -n '@[A-Z_][A-Z_0-9]+@' $ac_file >>$tmp/out
if test -s $tmp/out; then
ac_seen=`sed -e 's,^,'$ac_file':,' < $tmp/out`
- { echo "$as_me:5663: WARNING: Some variables may not be substituted:
+ { echo "$as_me:5952: WARNING: Some variables may not be substituted:
$ac_seen" >&5
echo "$as_me: WARNING: Some variables may not be substituted:
$ac_seen" >&2;}
@@ -5709,7 +5998,7 @@ for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
* ) ac_file_in=$ac_file.in ;;
esac
- test x"$ac_file" != x- && { echo "$as_me:5712: creating $ac_file" >&5
+ test x"$ac_file" != x- && { echo "$as_me:6001: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
# First look for the input files in the build tree, otherwise in the
@@ -5720,7 +6009,7 @@ echo "$as_me: creating $ac_file" >&6;}
-) echo $tmp/stdin ;;
[\\/$]*)
# Absolute (can't be DOS-style, as IFS=:)
- test -f "$f" || { { echo "$as_me:5723: error: cannot find input file: $f" >&5
+ test -f "$f" || { { echo "$as_me:6012: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
echo $f;;
@@ -5733,7 +6022,7 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
echo $srcdir/$f
else
# /dev/null tree
- { { echo "$as_me:5736: error: cannot find input file: $f" >&5
+ { { echo "$as_me:6025: error: cannot find input file: $f" >&5
echo "$as_me: error: cannot find input file: $f" >&2;}
{ (exit 1); exit 1; }; }
fi;;
@@ -5851,7 +6140,7 @@ cat >>$CONFIG_STATUS <<\EOF
rm -f $tmp/in
if test x"$ac_file" != x-; then
if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
- { echo "$as_me:5854: $ac_file is unchanged" >&5
+ { echo "$as_me:6143: $ac_file is unchanged" >&5
echo "$as_me: $ac_file is unchanged" >&6;}
else
ac_dir=`$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
diff --git a/contrib/byacc/configure.in b/contrib/byacc/configure.in
index 92afc35..df1fd44 100644
--- a/contrib/byacc/configure.in
+++ b/contrib/byacc/configure.in
@@ -1,7 +1,7 @@
dnl Process this file with 'autoconf' to produce a 'configure' script
-dnl $Id: configure.in,v 1.19 2014/04/22 22:56:51 tom Exp $
+dnl $Id: configure.in,v 1.20 2014/10/06 22:39:39 tom Exp $
AC_PREREQ(2.52.20011201)
-AC_REVISION($Revision: 1.19 $)
+AC_REVISION($Revision: 1.20 $)
AC_INIT(main.c)
AC_CONFIG_HEADER(config.h:config_h.in)
@@ -54,6 +54,8 @@ CF_WITH_WARNINGS(Wwrite-strings)
CF_DISABLE_ECHO
CF_DISABLE_LEAKS
+AC_TYPE_MODE_T
+
### output makefile
AC_OUTPUT(makefile)
CF_MAKE_DOCS(yacc,1)
diff --git a/contrib/byacc/defs.h b/contrib/byacc/defs.h
index 58ebc8d..0124a84 100644
--- a/contrib/byacc/defs.h
+++ b/contrib/byacc/defs.h
@@ -1,4 +1,4 @@
-/* $Id: defs.h,v 1.49 2014/04/22 23:34:34 tom Exp $ */
+/* $Id: defs.h,v 1.51 2014/10/02 22:38:13 tom Exp $ */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -157,6 +157,7 @@
#define CALLOC(k,n) (calloc((size_t)(k),(size_t)(n)))
#define FREE(x) (free((char*)(x)))
#define MALLOC(n) (malloc((size_t)(n)))
+#define TCMALLOC(t,n) ((t*) calloc((size_t)(n), sizeof(t)))
#define TMALLOC(t,n) ((t*) malloc((size_t)(n) * sizeof(t)))
#define NEW(t) ((t*)allocate(sizeof(t)))
#define NEW2(n,t) ((t*)allocate(((size_t)(n)*sizeof(t))))
@@ -366,6 +367,7 @@ extern reductions **reduction_table;
extern unsigned *LA;
extern Value_t *LAruleno;
extern Value_t *lookaheads;
+extern Value_t *goto_base;
extern Value_t *goto_map;
extern Value_t *from_state;
extern Value_t *to_state;
diff --git a/contrib/byacc/lalr.c b/contrib/byacc/lalr.c
index f2ae5b4..bf7e6a8 100644
--- a/contrib/byacc/lalr.c
+++ b/contrib/byacc/lalr.c
@@ -1,4 +1,4 @@
-/* $Id: lalr.c,v 1.10 2014/02/19 00:35:17 Tom.Shields Exp $ */
+/* $Id: lalr.c,v 1.11 2014/09/18 00:26:39 tom Exp $ */
#include "defs.h"
@@ -34,6 +34,7 @@ Value_t *accessing_symbol;
core **state_table;
shifts **shift_table;
reductions **reduction_table;
+Value_t *goto_base;
Value_t *goto_map;
Value_t *from_state;
Value_t *to_state;
@@ -179,12 +180,16 @@ set_goto_map(void)
int i;
int symbol;
int k;
+ Value_t *temp_base;
Value_t *temp_map;
Value_t state2;
Value_t state1;
- goto_map = NEW2(nvars + 1, Value_t) - ntokens;
- temp_map = NEW2(nvars + 1, Value_t) - ntokens;
+ goto_base = NEW2(nvars + 1, Value_t);
+ temp_base = NEW2(nvars + 1, Value_t);
+
+ goto_map = goto_base - ntokens;
+ temp_map = temp_base - ntokens;
ngotos = 0;
for (sp = first_shift; sp; sp = sp->next)
@@ -237,7 +242,7 @@ set_goto_map(void)
}
}
- FREE(temp_map + ntokens);
+ FREE(temp_base);
}
/* Map_goto maps a state/symbol pair into its numeric representation. */
diff --git a/contrib/byacc/main.c b/contrib/byacc/main.c
index 5de9235..b43cd13 100644
--- a/contrib/byacc/main.c
+++ b/contrib/byacc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.51 2014/05/28 02:01:55 Tom.Shields Exp $ */
+/* $Id: main.c,v 1.54 2014/10/06 22:40:07 tom Exp $ */
#include <signal.h>
#ifndef _WIN32
@@ -491,8 +491,8 @@ close_tmpfiles(void)
{
MY_TMPFILES *next = my_tmpfiles->next;
- chmod(my_tmpfiles->name, 0644);
- unlink(my_tmpfiles->name);
+ (void)chmod(my_tmpfiles->name, 0644);
+ (void)unlink(my_tmpfiles->name);
free(my_tmpfiles->name);
free(my_tmpfiles);
@@ -574,6 +574,8 @@ open_tmpfile(const char *label)
result = 0;
if (name != 0)
{
+ mode_t save_umask = umask(0177);
+
if ((mark = strrchr(label, '_')) == 0)
mark = label + strlen(label);
@@ -601,6 +603,7 @@ open_tmpfile(const char *label)
my_tmpfiles = item;
}
}
+ (void)umask(save_umask);
}
#else
result = tmpfile();
diff --git a/contrib/byacc/output.c b/contrib/byacc/output.c
index eb4402d..ecd9494 100644
--- a/contrib/byacc/output.c
+++ b/contrib/byacc/output.c
@@ -1,4 +1,4 @@
-/* $Id: output.c,v 1.67 2014/04/22 23:16:57 tom Exp $ */
+/* $Id: output.c,v 1.74 2014/10/05 23:21:09 tom Exp $ */
#include "defs.h"
@@ -54,6 +54,43 @@ puts_code(FILE * fp, const char *s)
}
static void
+puts_param_types(FILE * fp, param * list, int more)
+{
+ param *p;
+
+ if (list != 0)
+ {
+ for (p = list; p; p = p->next)
+ {
+ size_t len_type = strlen(p->type);
+ fprintf(fp, "%s%s%s%s%s", p->type,
+ (((len_type != 0) && (p->type[len_type - 1] == '*'))
+ ? ""
+ : " "),
+ p->name, p->type2,
+ ((more || p->next) ? ", " : ""));
+ }
+ }
+ else
+ {
+ if (!more)
+ fprintf(fp, "void");
+ }
+}
+
+static void
+puts_param_names(FILE * fp, param * list, int more)
+{
+ param *p;
+
+ for (p = list; p; p = p->next)
+ {
+ fprintf(fp, "%s%s", p->name,
+ ((more || p->next) ? ", " : ""));
+ }
+}
+
+static void
write_code_lineno(FILE * fp)
{
if (!lflag && (fp == code_file))
@@ -1007,30 +1044,33 @@ output_ctable(void)
{
int i;
int j;
+ int limit = (conflicts != 0) ? nconflicts : 0;
- if (conflicts)
- {
- output_line("#if YYBTYACC");
- start_int_table("ctable", conflicts[0]);
+ if (limit < high)
+ limit = (int)high;
- j = 10;
- for (i = 1; i < nconflicts; i++)
- {
- if (j >= 10)
- {
- output_newline();
- j = 1;
- }
- else
- ++j;
+ output_line("#if YYBTYACC");
+ start_int_table("ctable", conflicts ? conflicts[0] : -1);
- output_int(conflicts[i]);
+ j = 10;
+ for (i = 1; i < limit; i++)
+ {
+ if (j >= 10)
+ {
+ output_newline();
+ j = 1;
}
+ else
+ ++j;
- end_table();
- output_line("#endif");
- FREE(conflicts);
+ output_int((conflicts != 0 && i < nconflicts) ? conflicts[i] : -1);
}
+
+ if (conflicts)
+ FREE(conflicts);
+
+ end_table();
+ output_line("#endif");
}
#endif
@@ -1056,7 +1096,7 @@ output_actions(void)
FREE(accessing_symbol);
goto_actions();
- FREE(goto_map + ntokens);
+ FREE(goto_base);
FREE(from_state);
FREE(to_state);
@@ -1607,15 +1647,7 @@ output_parse_decl(FILE * fp)
putl_code(fp, "#else\n");
puts_code(fp, "# define YYPARSE_DECL() yyparse(");
- if (!parse_param)
- puts_code(fp, "void");
- else
- {
- param *p;
- for (p = parse_param; p; p = p->next)
- fprintf(fp, "%s %s%s%s", p->type, p->name, p->type2,
- p->next ? ", " : "");
- }
+ puts_param_types(fp, parse_param, 0);
putl_code(fp, ")\n");
putl_code(fp, "#endif\n");
@@ -1633,7 +1665,8 @@ output_lex_decl(FILE * fp)
#if defined(YYBTYACC)
if (locations)
{
- putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, YYLTYPE *yylloc,"
+ putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval,"
+ " YYLTYPE *yylloc,"
" YYLEX_PARAM_TYPE YYLEX_PARAM)\n");
}
else
@@ -1646,7 +1679,8 @@ output_lex_decl(FILE * fp)
#if defined(YYBTYACC)
if (locations)
{
- putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, YYLTYPE *yylloc,"
+ putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval,"
+ " YYLTYPE *yylloc,"
" void * YYLEX_PARAM)\n");
}
else
@@ -1672,8 +1706,6 @@ output_lex_decl(FILE * fp)
putl_code(fp, "#else\n");
if (pure_parser && lex_param)
{
- param *p;
-
#if defined(YYBTYACC)
if (locations)
puts_code(fp,
@@ -1681,9 +1713,7 @@ output_lex_decl(FILE * fp)
else
#endif
puts_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, ");
- for (p = lex_param; p; p = p->next)
- fprintf(fp, "%s %s%s%s", p->type, p->name, p->type2,
- p->next ? ", " : "");
+ puts_param_types(fp, lex_param, 0);
putl_code(fp, ")\n");
#if defined(YYBTYACC)
@@ -1692,8 +1722,7 @@ output_lex_decl(FILE * fp)
else
#endif
puts_code(fp, "# define YYLEX yylex(&yylval, ");
- for (p = lex_param; p; p = p->next)
- fprintf(fp, "%s%s", p->name, p->next ? ", " : "");
+ puts_param_names(fp, lex_param, 0);
putl_code(fp, ")\n");
}
else if (pure_parser)
@@ -1714,17 +1743,12 @@ output_lex_decl(FILE * fp)
}
else if (lex_param)
{
- param *p;
-
puts_code(fp, "# define YYLEX_DECL() yylex(");
- for (p = lex_param; p; p = p->next)
- fprintf(fp, "%s %s%s%s", p->type, p->name, p->type2,
- p->next ? ", " : "");
+ puts_param_types(fp, lex_param, 0);
putl_code(fp, ")\n");
puts_code(fp, "# define YYLEX yylex(");
- for (p = lex_param; p; p = p->next)
- fprintf(fp, "%s%s", p->name, p->next ? ", " : "");
+ puts_param_names(fp, lex_param, 0);
putl_code(fp, ")\n");
}
else
@@ -1738,8 +1762,6 @@ output_lex_decl(FILE * fp)
static void
output_error_decl(FILE * fp)
{
- param *p;
-
putc_code(fp, '\n');
putl_code(fp, "/* Parameters sent to yyerror. */\n");
putl_code(fp, "#ifndef YYERROR_DECL\n");
@@ -1748,22 +1770,20 @@ output_error_decl(FILE * fp)
if (locations)
puts_code(fp, "YYLTYPE loc, ");
#endif
- for (p = parse_param; p; p = p->next)
- fprintf(fp, "%s %s%s, ", p->type, p->name, p->type2);
+ puts_param_types(fp, parse_param, 1);
putl_code(fp, "const char *s)\n");
putl_code(fp, "#endif\n");
putl_code(fp, "#ifndef YYERROR_CALL\n");
- puts_code(fp, "#define YYERROR_CALL(msg) yyerror(");
+ puts_code(fp, "#define YYERROR_CALL(msg) yyerror(");
#if defined(YYBTYACC)
if (locations)
puts_code(fp, "yylloc, ");
#endif
- for (p = parse_param; p; p = p->next)
- fprintf(fp, "%s, ", p->name);
-
+ puts_param_names(fp, parse_param, 1);
putl_code(fp, "msg)\n");
+
putl_code(fp, "#endif\n");
}
@@ -1773,24 +1793,42 @@ output_yydestruct_decl(FILE * fp)
{
putc_code(fp, '\n');
putl_code(fp, "#ifndef YYDESTRUCT_DECL\n");
+
+ puts_code(fp,
+ "#define YYDESTRUCT_DECL() "
+ "yydestruct(const char *msg, int psymb, YYSTYPE *val");
#if defined(YYBTYACC)
if (locations)
- putl_code(fp,
- "#define YYDESTRUCT_DECL() yydestruct(const char *msg, int psymb, YYSTYPE *val, YYLTYPE *loc)\n");
- else
+ puts_code(fp, ", YYLTYPE *loc");
#endif
- putl_code(fp,
- "#define YYDESTRUCT_DECL() yydestruct(const char *msg, int psymb, YYSTYPE *val)\n");
+ if (parse_param)
+ {
+ puts_code(fp, ", ");
+ puts_param_types(fp, parse_param, 0);
+ }
+ putl_code(fp, ")\n");
+
putl_code(fp, "#endif\n");
+
putl_code(fp, "#ifndef YYDESTRUCT_CALL\n");
+
+ puts_code(fp, "#define YYDESTRUCT_CALL(msg, psymb, val");
#if defined(YYBTYACC)
if (locations)
- putl_code(fp,
- "#define YYDESTRUCT_CALL(msg, psymb, val, loc) yydestruct(msg, psymb, val, loc)\n");
- else
+ puts_code(fp, ", loc");
#endif
- putl_code(fp,
- "#define YYDESTRUCT_CALL(msg, psymb, val) yydestruct(msg, psymb, val)\n");
+ puts_code(fp, ") yydestruct(msg, psymb, val");
+#if defined(YYBTYACC)
+ if (locations)
+ puts_code(fp, ", loc");
+#endif
+ if (parse_param)
+ {
+ puts_code(fp, ", ");
+ puts_param_names(fp, parse_param, 0);
+ }
+ putl_code(fp, ")\n");
+
putl_code(fp, "#endif\n");
}
diff --git a/contrib/byacc/package/byacc.spec b/contrib/byacc/package/byacc.spec
index b2ac30e..efed521 100644
--- a/contrib/byacc/package/byacc.spec
+++ b/contrib/byacc/package/byacc.spec
@@ -1,8 +1,8 @@
Summary: byacc - public domain Berkeley LALR Yacc parser generator
%define AppProgram byacc
-%define AppVersion 20140715
+%define AppVersion 20141006
%define UseProgram yacc
-# $XTermId: byacc.spec,v 1.22 2014/07/15 19:36:54 tom Exp $
+# $XTermId: byacc.spec,v 1.25 2014/10/06 22:52:03 tom Exp $
Name: %{AppProgram}
Version: %{AppVersion}
Release: 1
diff --git a/contrib/byacc/package/debian/changelog b/contrib/byacc/package/debian/changelog
index 33f31fa..c700fb56 100644
--- a/contrib/byacc/package/debian/changelog
+++ b/contrib/byacc/package/debian/changelog
@@ -1,3 +1,15 @@
+byacc (20141006) unstable; urgency=low
+
+ * maintenance updates
+
+ -- Thomas E. Dickey <dickey@invisible-island.net> Mon, 06 Oct 2014 18:52:03 -0400
+
+byacc (20141005) unstable; urgency=low
+
+ * maintenance updates
+
+ -- Thomas E. Dickey <dickey@invisible-island.net> Sun, 27 Jul 2014 10:45:06 -0400
+
byacc (20140715) unstable; urgency=low
* maintenance updates
diff --git a/contrib/byacc/package/debian/source/format b/contrib/byacc/package/debian/source/format
index 163aaf8..89ae9db 100644
--- a/contrib/byacc/package/debian/source/format
+++ b/contrib/byacc/package/debian/source/format
@@ -1 +1 @@
-3.0 (quilt)
+3.0 (native)
diff --git a/contrib/byacc/package/mingw-byacc.spec b/contrib/byacc/package/mingw-byacc.spec
index 24230cb..3cc0292 100644
--- a/contrib/byacc/package/mingw-byacc.spec
+++ b/contrib/byacc/package/mingw-byacc.spec
@@ -1,8 +1,8 @@
Summary: byacc - public domain Berkeley LALR Yacc parser generator
%define AppProgram byacc
-%define AppVersion 20140715
+%define AppVersion 20141006
%define UseProgram yacc
-# $XTermId: mingw-byacc.spec,v 1.4 2014/07/15 19:36:54 tom Exp $
+# $XTermId: mingw-byacc.spec,v 1.7 2014/10/06 22:52:03 tom Exp $
Name: %{AppProgram}
Version: %{AppVersion}
Release: 1
diff --git a/contrib/byacc/package/pkgsrc/Makefile b/contrib/byacc/package/pkgsrc/Makefile
index 750137a..691b678 100644
--- a/contrib/byacc/package/pkgsrc/Makefile
+++ b/contrib/byacc/package/pkgsrc/Makefile
@@ -1,7 +1,7 @@
# $NetBSD: Makefile,v 1.9 2008/07/24 17:13:00 tonnerre Exp $
#
-DISTNAME= byacc-20140715
+DISTNAME= byacc-20141006
PKGREVISION= 1
CATEGORIES= devel
MASTER_SITES= ftp://invisible-island.net/byacc/
diff --git a/contrib/byacc/reader.c b/contrib/byacc/reader.c
index 8312a69..d3aaf2b 100644
--- a/contrib/byacc/reader.c
+++ b/contrib/byacc/reader.c
@@ -1,4 +1,4 @@
-/* $Id: reader.c,v 1.47 2014/04/09 21:09:27 tom Exp $ */
+/* $Id: reader.c,v 1.58 2014/10/06 22:15:08 tom Exp $ */
#include "defs.h"
@@ -70,6 +70,7 @@ static bucket *default_destructor[3] =
static bucket *
lookup_type_destructor(char *tag)
{
+ const char fmt[] = "%.*s destructor";
char name[1024] = "\0";
bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
@@ -80,7 +81,8 @@ lookup_type_destructor(char *tag)
bpp = &bp->link;
}
- *bpp = bp = make_bucket(strcat(strcpy(name, tag), " destructor"));
+ sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
+ *bpp = bp = make_bucket(name);
bp->tag = tag;
return (bp);
@@ -133,10 +135,10 @@ get_line(void)
++lineno;
for (;;)
{
- line[i] = (char)c;
+ line[i++] = (char)c;
if (c == '\n')
break;
- if (++i >= linesize)
+ if ((i + 3) >= linesize)
{
linesize += LINESIZE;
line = TREALLOC(char, line, linesize);
@@ -145,11 +147,12 @@ get_line(void)
c = getc(f);
if (c == EOF)
{
- line[i] = '\n';
+ line[i++] = '\n';
saw_eof = 1;
break;
}
}
+ line[i] = '\0';
cptr = line;
return;
}
@@ -205,7 +208,7 @@ skip_comment(void)
}
static int
-nextc(void)
+next_inline(void)
{
char *s;
@@ -221,27 +224,6 @@ nextc(void)
{
switch (*s)
{
- case '\n':
- get_line();
- if (line == 0)
- return (EOF);
- s = cptr;
- break;
-
- case ' ':
- case '\t':
- case '\f':
- case '\r':
- case '\v':
- case ',':
- case ';':
- ++s;
- break;
-
- case '\\':
- cptr = s;
- return ('%');
-
case '/':
if (s[1] == '*')
{
@@ -266,6 +248,41 @@ nextc(void)
}
}
}
+
+static int
+nextc(void)
+{
+ int ch;
+ int finish = 0;
+
+ do
+ {
+ switch (ch = next_inline())
+ {
+ case '\n':
+ get_line();
+ break;
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\r':
+ case '\v':
+ case ',':
+ case ';':
+ ++cptr;
+ break;
+ case '\\':
+ ch = '%';
+ /* FALLTHRU */
+ default:
+ finish = 1;
+ break;
+ }
+ }
+ while (!finish);
+
+ return ch;
+}
/* *INDENT-OFF* */
static struct keyword
{
@@ -644,92 +661,109 @@ copy_union(void)
}
}
+static char *
+after_blanks(char *s)
+{
+ while (*s != '\0' && isspace(UCH(*s)))
+ ++s;
+ return s;
+}
+
/*
- * Keep a linked list of parameters
+ * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
+ * single space. Return index to last character in the buffer.
*/
-static void
-copy_param(int k)
+static int
+trim_blanks(char *buffer)
{
- char *buf;
- int c;
- param *head, *p;
- int i;
- int name, type2;
-
- c = nextc();
- if (c == EOF)
- unexpected_EOF();
- if (c != L_CURL)
- goto out;
- cptr++;
+ if (*buffer != '\0')
+ {
+ char *d = buffer;
+ char *s = after_blanks(d);
- c = nextc();
- if (c == EOF)
- unexpected_EOF();
- if (c == R_CURL)
- goto out;
+ while ((*d++ = *s++) != '\0')
+ {
+ ;
+ }
- buf = TMALLOC(char, linesize);
- NO_SPACE(buf);
+ --d;
+ while ((--d != buffer) && isspace(UCH(*d)))
+ *d = '\0';
- for (i = 0; (c = *cptr++) != R_CURL; i++)
- {
- if (c == '\0')
- missing_brace();
- if (c == EOF)
- unexpected_EOF();
- buf[i] = (char)c;
+ for (s = d = buffer; (*d++ = *s++) != '\0';)
+ {
+ if (isspace(UCH(*s)))
+ {
+ *s = ' ';
+ while (isspace(UCH(*s)))
+ {
+ *s++ = ' ';
+ }
+ --s;
+ }
+ }
}
- if (i == 0)
- goto out;
-
- buf[i--] = '\0';
- while (i > 0 && isspace(UCH(buf[i])))
- buf[i--] = '\0';
+ return (int)strlen(buffer) - 1;
+}
- if (buf[i] == ']')
+/*
+ * Scan forward in the current line-buffer looking for a right-curly bracket.
+ *
+ * Parameters begin with a left-curly bracket, and continue until there are no
+ * more interesting characters after the last right-curly bracket on the
+ * current line. Bison documents parameters as separated like this:
+ * {type param1} {type2 param2}
+ * but also accepts commas (although some versions of bison mishandle this)
+ * {type param1, type2 param2}
+ */
+static int
+more_curly(void)
+{
+ char *save = cptr;
+ int result = 0;
+ int finish = 0;
+ do
{
- int level = 1;
- while (i >= 0 && level > 0 && buf[i] != '[')
+ switch (next_inline())
{
- if (buf[i] == ']')
- ++level;
- else if (buf[i] == '[')
- --level;
- i--;
+ case 0:
+ case '\n':
+ finish = 1;
+ break;
+ case R_CURL:
+ finish = 1;
+ result = 1;
+ break;
}
- if (i <= 0)
- unexpected_EOF();
- type2 = i--;
- }
- else
- {
- type2 = i + 1;
+ ++cptr;
}
+ while (!finish);
+ cptr = save;
+ return result;
+}
- while (i > 0 && (isalnum(UCH(buf[i])) ||
- UCH(buf[i]) == '_'))
- i--;
-
- if (!isspace(UCH(buf[i])) && buf[i] != '*')
- goto out;
-
- name = i + 1;
+static void
+save_param(int k, char *buffer, int name, int type2)
+{
+ param *head, *p;
p = TMALLOC(param, 1);
NO_SPACE(p);
- p->type2 = strdup(buf + type2);
+ p->type2 = strdup(buffer + type2);
NO_SPACE(p->type2);
+ buffer[type2] = '\0';
+ (void)trim_blanks(p->type2);
- buf[type2] = '\0';
-
- p->name = strdup(buf + name);
+ p->name = strdup(buffer + name);
NO_SPACE(p->name);
+ buffer[name] = '\0';
+ (void)trim_blanks(p->name);
- buf[name] = '\0';
- p->type = buf;
+ p->type = strdup(buffer);
+ NO_SPACE(p->type);
+ (void)trim_blanks(p->type);
if (k == LEX_PARAM)
head = lex_param;
@@ -750,9 +784,169 @@ copy_param(int k)
parse_param = p;
}
p->next = NULL;
+}
+
+/*
+ * Keep a linked list of parameters. This may be multi-line, if the trailing
+ * right-curly bracket is absent.
+ */
+static void
+copy_param(int k)
+{
+ int c;
+ int name, type2;
+ int curly = 0;
+ char *buf = 0;
+ int i = -1;
+ size_t buf_size = 0;
+ int st_lineno = lineno;
+ char *comma;
+
+ do
+ {
+ int state = curly;
+ c = next_inline();
+ switch (c)
+ {
+ case EOF:
+ unexpected_EOF();
+ break;
+ case L_CURL:
+ if (curly == 1)
+ {
+ goto oops;
+ }
+ curly = 1;
+ st_lineno = lineno;
+ break;
+ case R_CURL:
+ if (curly != 1)
+ {
+ goto oops;
+ }
+ curly = 2;
+ break;
+ case '\n':
+ if (curly == 0)
+ {
+ goto oops;
+ }
+ break;
+ case '%':
+ if ((curly == 1) && (cptr == line))
+ {
+ lineno = st_lineno;
+ missing_brace();
+ }
+ /* FALLTHRU */
+ case '"':
+ case '\'':
+ goto oops;
+ default:
+ if (curly == 0 && !isspace(UCH(c)))
+ {
+ goto oops;
+ }
+ break;
+ }
+ if (buf == 0)
+ {
+ buf_size = (size_t) linesize;
+ buf = TMALLOC(char, buf_size);
+ }
+ else if (c == '\n')
+ {
+ get_line();
+ if (line == 0)
+ unexpected_EOF();
+ --cptr;
+ buf_size += (size_t) linesize;
+ buf = TREALLOC(char, buf, buf_size);
+ }
+ NO_SPACE(buf);
+ if (curly)
+ {
+ if ((state == 2) && (c == L_CURL))
+ {
+ buf[++i] = ',';
+ }
+ else if ((state == 2) && isspace(UCH(c)))
+ {
+ ;
+ }
+ else if ((c != L_CURL) && (c != R_CURL))
+ {
+ buf[++i] = (char)c;
+ }
+ }
+ cptr++;
+ }
+ while (curly < 2 || more_curly());
+
+ if (i == 0)
+ {
+ if (curly == 1)
+ {
+ lineno = st_lineno;
+ missing_brace();
+ }
+ goto oops;
+ }
+
+ buf[i--] = '\0';
+ i = trim_blanks(buf);
+
+ comma = buf - 1;
+ do
+ {
+ char *parms = (comma + 1);
+ comma = strchr(parms, ',');
+ if (comma != 0)
+ *comma = '\0';
+
+ (void)trim_blanks(parms);
+ i = (int)strlen(parms) - 1;
+ if (i < 0)
+ {
+ goto oops;
+ }
+
+ if (parms[i] == ']')
+ {
+ int level = 1;
+ while (i >= 0 && level > 0 && parms[i] != '[')
+ {
+ if (parms[i] == ']')
+ ++level;
+ else if (parms[i] == '[')
+ --level;
+ i--;
+ }
+ if (i <= 0)
+ unexpected_EOF();
+ type2 = i--;
+ }
+ else
+ {
+ type2 = i + 1;
+ }
+
+ while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
+ i--;
+
+ if (!isspace(UCH(parms[i])) && parms[i] != '*')
+ goto oops;
+
+ name = i + 1;
+
+ save_param(k, parms, name, type2);
+ }
+ while (comma != 0);
+ FREE(buf);
return;
- out:
+ oops:
+ FREE(buf);
syntax_error(lineno, line, cptr);
}
@@ -1634,10 +1828,11 @@ compile_arg(char **theptr, char *yyvaltag)
{
offsets = TMALLOC(Value_t, maxoffset + 1);
NO_SPACE(offsets);
+
+ for (j = 0, i++; i < nitems; i++)
+ if (pitem[i]->class != ARGUMENT)
+ offsets[++j] = (Value_t) (i - nitems + 1);
}
- for (j = 0, i++; i < nitems; i++)
- if (pitem[i]->class != ARGUMENT)
- offsets[++j] = (Value_t) (i - nitems + 1);
rhs = pitem + nitems - 1;
if (yyvaltag)
@@ -1664,7 +1859,7 @@ compile_arg(char **theptr, char *yyvaltag)
dollar_warning(rescan_lineno, val);
i = val - maxoffset;
}
- else
+ else if (maxoffset > 0)
{
i = offsets[val];
if (!tag && !(tag = rhs[i]->tag) && havetags)
@@ -2020,14 +2215,6 @@ add_symbol(void)
pitem[nitems - 1] = bp;
}
-static char *
-after_blanks(char *s)
-{
- while (*s != '\0' && isspace(UCH(*s)))
- ++s;
- return s;
-}
-
static void
copy_action(void)
{
@@ -2084,12 +2271,13 @@ copy_action(void)
{
offsets = TMALLOC(Value_t, maxoffset + 1);
NO_SPACE(offsets);
- }
- for (j = 0, i++; i < nitems; i++)
- {
- if (pitem[i]->class != ARGUMENT)
+
+ for (j = 0, i++; i < nitems; i++)
{
- offsets[++j] = (Value_t) (i - nitems + 1);
+ if (pitem[i]->class != ARGUMENT)
+ {
+ offsets[++j] = (Value_t) (i - nitems + 1);
+ }
}
}
rhs = pitem + nitems - 1;
@@ -2177,7 +2365,7 @@ copy_action(void)
{
++cptr;
i = get_number();
- if (havetags)
+ if (havetags && offsets)
{
if (i <= 0 || i > maxoffset)
unknown_rhs(i);
diff --git a/contrib/byacc/test/btyacc/btyacc_calc1.tab.c b/contrib/byacc/test/btyacc/btyacc_calc1.tab.c
index 6e4cade..f7e6a30 100644
--- a/contrib/byacc/test/btyacc/btyacc_calc1.tab.c
+++ b/contrib/byacc/test/btyacc/btyacc_calc1.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -311,7 +311,26 @@ static const YYINT calc1_ctable[] = { 20,
16, -1, 21, 16, -1, 22, 16, -1, 23, 16,
-1, 4, 16, -1, 14, 16, -1, 34, 16, -1,
10, 16, -1, 11, 16, -1, 12, 16, -1, 13,
- 16, -1,
+ 16, -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,
};
#endif
#define YYFINAL 1
@@ -594,7 +613,7 @@ vdiv(double a, double b, INTERVAL v)
{
return (hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo));
}
-#line 598 "btyacc_calc1.tab.c"
+#line 617 "btyacc_calc1.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -603,11 +622,11 @@ vdiv(double a, double b, INTERVAL v)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -841,8 +860,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -938,12 +957,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -998,7 +1017,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -1092,14 +1111,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -1108,12 +1127,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -1143,12 +1162,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1494,7 +1513,7 @@ case 28:
yyval.vval = yystack.l_mark[-1].vval;
}
break;
-#line 1498 "btyacc_calc1.tab.c"
+#line 1517 "btyacc_calc1.tab.c"
default:
break;
}
@@ -1545,8 +1564,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1649,12 +1668,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/btyacc_demo.tab.c b/contrib/byacc/test/btyacc/btyacc_demo.tab.c
index 4a92347..cd7995b 100644
--- a/contrib/byacc/test/btyacc/btyacc_demo.tab.c
+++ b/contrib/byacc/test/btyacc/btyacc_demo.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -387,7 +387,32 @@ static const YYINT demo_check[] = { 42,
#if YYBTYACC
static const YYINT demo_ctable[] = { -1,
1, 10, -1, 21, 4, -1, 23, 29, -1, 1,
- 51, -1, 101, 56, -1,
+ 51, -1, 101, 56, -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,
};
#endif
#define YYFINAL 1
@@ -634,7 +659,7 @@ extern Expr * var_expr(Scope *scope, char *id);
extern Code * build_expr_code(Expr *expr);
extern Code * build_if(Expr *cond_expr, Code *then_stmt, Code *else_stmt);
extern Code * code_append(Code *stmt_list, Code *stmt);
-#line 638 "btyacc_demo.tab.c"
+#line 663 "btyacc_demo.tab.c"
/* Release memory associated with symbol. */
#if ! defined YYDESTRUCT_IS_DECLARED
@@ -651,7 +676,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 655 "btyacc_demo.tab.c"
+#line 680 "btyacc_demo.tab.c"
case 45:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -660,7 +685,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 664 "btyacc_demo.tab.c"
+#line 689 "btyacc_demo.tab.c"
case 42:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -669,7 +694,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 673 "btyacc_demo.tab.c"
+#line 698 "btyacc_demo.tab.c"
case 47:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -678,7 +703,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 682 "btyacc_demo.tab.c"
+#line 707 "btyacc_demo.tab.c"
case 37:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -687,7 +712,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 691 "btyacc_demo.tab.c"
+#line 716 "btyacc_demo.tab.c"
case 257:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -696,7 +721,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 700 "btyacc_demo.tab.c"
+#line 725 "btyacc_demo.tab.c"
case 258:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -705,7 +730,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 709 "btyacc_demo.tab.c"
+#line 734 "btyacc_demo.tab.c"
case 40:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -714,7 +739,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 718 "btyacc_demo.tab.c"
+#line 743 "btyacc_demo.tab.c"
case 91:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -723,7 +748,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 727 "btyacc_demo.tab.c"
+#line 752 "btyacc_demo.tab.c"
case 46:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -732,7 +757,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 736 "btyacc_demo.tab.c"
+#line 761 "btyacc_demo.tab.c"
case 259:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -741,7 +766,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).id); }
break;
-#line 745 "btyacc_demo.tab.c"
+#line 770 "btyacc_demo.tab.c"
case 260:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -750,7 +775,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).expr); }
break;
-#line 754 "btyacc_demo.tab.c"
+#line 779 "btyacc_demo.tab.c"
case 261:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -759,7 +784,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 763 "btyacc_demo.tab.c"
+#line 788 "btyacc_demo.tab.c"
case 262:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -768,7 +793,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 772 "btyacc_demo.tab.c"
+#line 797 "btyacc_demo.tab.c"
case 263:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -777,7 +802,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 781 "btyacc_demo.tab.c"
+#line 806 "btyacc_demo.tab.c"
case 264:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -786,7 +811,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 790 "btyacc_demo.tab.c"
+#line 815 "btyacc_demo.tab.c"
case 265:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -795,7 +820,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 799 "btyacc_demo.tab.c"
+#line 824 "btyacc_demo.tab.c"
case 266:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -804,7 +829,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 808 "btyacc_demo.tab.c"
+#line 833 "btyacc_demo.tab.c"
case 267:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -813,7 +838,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 817 "btyacc_demo.tab.c"
+#line 842 "btyacc_demo.tab.c"
case 268:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -822,7 +847,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 826 "btyacc_demo.tab.c"
+#line 851 "btyacc_demo.tab.c"
case 269:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -831,7 +856,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 835 "btyacc_demo.tab.c"
+#line 860 "btyacc_demo.tab.c"
case 59:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -840,7 +865,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 844 "btyacc_demo.tab.c"
+#line 869 "btyacc_demo.tab.c"
case 44:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -849,7 +874,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 853 "btyacc_demo.tab.c"
+#line 878 "btyacc_demo.tab.c"
case 41:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -858,7 +883,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 862 "btyacc_demo.tab.c"
+#line 887 "btyacc_demo.tab.c"
case 93:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -867,7 +892,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 871 "btyacc_demo.tab.c"
+#line 896 "btyacc_demo.tab.c"
case 123:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -876,7 +901,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 880 "btyacc_demo.tab.c"
+#line 905 "btyacc_demo.tab.c"
case 125:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -885,7 +910,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 889 "btyacc_demo.tab.c"
+#line 914 "btyacc_demo.tab.c"
case 270:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -894,7 +919,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 898 "btyacc_demo.tab.c"
+#line 923 "btyacc_demo.tab.c"
case 271:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -903,7 +928,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 907 "btyacc_demo.tab.c"
+#line 932 "btyacc_demo.tab.c"
case 272:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -912,7 +937,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).expr); }
break;
-#line 916 "btyacc_demo.tab.c"
+#line 941 "btyacc_demo.tab.c"
case 273:
#line 67 "btyacc_demo.y"
{ /* 'msg' is a 'char *' indicating the context of destructor invocation*/
@@ -922,7 +947,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).decl->scope); free((*val).decl->type); }
break;
-#line 926 "btyacc_demo.tab.c"
+#line 951 "btyacc_demo.tab.c"
case 274:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -931,7 +956,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 935 "btyacc_demo.tab.c"
+#line 960 "btyacc_demo.tab.c"
case 275:
#line 83 "btyacc_demo.y"
{ printf("%s accessed by symbol with no type @ position[%d,%d..%d,%d]\n",
@@ -940,7 +965,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
/* in this example, we don't know what to do here */ }
break;
-#line 944 "btyacc_demo.tab.c"
+#line 969 "btyacc_demo.tab.c"
case 276:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -949,7 +974,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).code); }
break;
-#line 953 "btyacc_demo.tab.c"
+#line 978 "btyacc_demo.tab.c"
case 277:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -958,7 +983,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).code); }
break;
-#line 962 "btyacc_demo.tab.c"
+#line 987 "btyacc_demo.tab.c"
case 278:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -967,7 +992,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).code); }
break;
-#line 971 "btyacc_demo.tab.c"
+#line 996 "btyacc_demo.tab.c"
case 279:
#line 73 "btyacc_demo.y"
{ printf("%s accessed by symbol with type <decl> (case s.b. 279 & 280) @ position[%d,%d..%d,%d]\n",
@@ -976,7 +1001,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).decl); }
break;
-#line 980 "btyacc_demo.tab.c"
+#line 1005 "btyacc_demo.tab.c"
case 280:
#line 73 "btyacc_demo.y"
{ printf("%s accessed by symbol with type <decl> (case s.b. 279 & 280) @ position[%d,%d..%d,%d]\n",
@@ -985,7 +1010,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).decl); }
break;
-#line 989 "btyacc_demo.tab.c"
+#line 1014 "btyacc_demo.tab.c"
case 281:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -994,7 +1019,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 998 "btyacc_demo.tab.c"
+#line 1023 "btyacc_demo.tab.c"
case 282:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1003,7 +1028,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 1007 "btyacc_demo.tab.c"
+#line 1032 "btyacc_demo.tab.c"
case 283:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1012,7 +1037,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 1016 "btyacc_demo.tab.c"
+#line 1041 "btyacc_demo.tab.c"
case 284:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1021,7 +1046,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 1025 "btyacc_demo.tab.c"
+#line 1050 "btyacc_demo.tab.c"
case 285:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1030,7 +1055,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 1034 "btyacc_demo.tab.c"
+#line 1059 "btyacc_demo.tab.c"
case 286:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1039,7 +1064,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1043 "btyacc_demo.tab.c"
+#line 1068 "btyacc_demo.tab.c"
case 287:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1048,7 +1073,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).dlist); }
break;
-#line 1052 "btyacc_demo.tab.c"
+#line 1077 "btyacc_demo.tab.c"
case 288:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1057,7 +1082,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).dlist); }
break;
-#line 1061 "btyacc_demo.tab.c"
+#line 1086 "btyacc_demo.tab.c"
case 289:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1066,7 +1091,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1070 "btyacc_demo.tab.c"
+#line 1095 "btyacc_demo.tab.c"
case 290:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1075,7 +1100,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1079 "btyacc_demo.tab.c"
+#line 1104 "btyacc_demo.tab.c"
case 291:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1084,7 +1109,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 1088 "btyacc_demo.tab.c"
+#line 1113 "btyacc_demo.tab.c"
case 292:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1093,7 +1118,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1097 "btyacc_demo.tab.c"
+#line 1122 "btyacc_demo.tab.c"
case 293:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1102,7 +1127,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1106 "btyacc_demo.tab.c"
+#line 1131 "btyacc_demo.tab.c"
case 294:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1111,7 +1136,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 1115 "btyacc_demo.tab.c"
+#line 1140 "btyacc_demo.tab.c"
case 295:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1120,7 +1145,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1124 "btyacc_demo.tab.c"
+#line 1149 "btyacc_demo.tab.c"
case 296:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1129,7 +1154,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).type); }
break;
-#line 1133 "btyacc_demo.tab.c"
+#line 1158 "btyacc_demo.tab.c"
case 297:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1138,7 +1163,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1142 "btyacc_demo.tab.c"
+#line 1167 "btyacc_demo.tab.c"
case 298:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1147,7 +1172,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1151 "btyacc_demo.tab.c"
+#line 1176 "btyacc_demo.tab.c"
case 299:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1156,7 +1181,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1160 "btyacc_demo.tab.c"
+#line 1185 "btyacc_demo.tab.c"
case 300:
#line 78 "btyacc_demo.y"
{ printf("%s accessed by symbol of any type other than <decl> @ position[%d,%d..%d,%d]\n",
@@ -1165,7 +1190,7 @@ YYDESTRUCT_DECL()
(*loc).last_line, (*loc).last_column);
free((*val).scope); }
break;
-#line 1169 "btyacc_demo.tab.c"
+#line 1194 "btyacc_demo.tab.c"
}
}
#define YYDESTRUCT_IS_DECLARED 1
@@ -1178,11 +1203,11 @@ YYDESTRUCT_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -1366,8 +1391,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -1463,12 +1488,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -1523,7 +1548,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -1617,14 +1642,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -1633,12 +1658,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -1668,12 +1693,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -2093,7 +2118,7 @@ case 61:
#line 197 "btyacc_demo.y"
{ yyval.code = yystack.l_mark[-1].code; }
break;
-#line 2097 "btyacc_demo.tab.c"
+#line 2122 "btyacc_demo.tab.c"
default:
break;
}
@@ -2144,8 +2169,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -2248,12 +2273,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/btyacc_demo2.error b/contrib/byacc/test/btyacc/btyacc_demo2.error
new file mode 100644
index 0000000..554dd5a
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_demo2.error
@@ -0,0 +1 @@
+YACC: e - line 82 of "./btyacc_demo2.y", $$ is untyped
diff --git a/contrib/byacc/test/btyacc/btyacc_demo2.output b/contrib/byacc/test/btyacc/btyacc_demo2.output
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_demo2.output
diff --git a/contrib/byacc/test/btyacc/btyacc_demo2.tab.c b/contrib/byacc/test/btyacc/btyacc_demo2.tab.c
new file mode 100644
index 0000000..6c35f23
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_demo2.tab.c
@@ -0,0 +1,15 @@
+/* original parser id follows */
+/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYCHECK "yyyymmdd"
+
+#define YYEMPTY (-1)
+#define yyclearin (yychar = YYEMPTY)
+#define yyerrok (yyerrflag = 0)
+#define YYRECOVERING() (yyerrflag != 0)
+#define YYENOMEM (-2)
+#define YYEOF 0
diff --git a/contrib/byacc/test/btyacc/btyacc_demo2.tab.h b/contrib/byacc/test/btyacc/btyacc_demo2.tab.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_demo2.tab.h
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy1.error b/contrib/byacc/test/btyacc/btyacc_destroy1.error
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy1.error
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy1.output b/contrib/byacc/test/btyacc/btyacc_destroy1.output
new file mode 100644
index 0000000..918354c
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy1.output
@@ -0,0 +1,247 @@
+ 0 $accept : declaration $end
+
+ 1 declaration : class type namelist '(' class ',' type ')'
+ 2 | type locnamelist '(' class ')'
+
+ 3 class : GLOBAL
+ 4 | LOCAL
+
+ 5 type : REAL
+ 6 | INTEGER
+
+ 7 namelist : namelist NAME
+ 8 | NAME
+
+ 9 locnamelist : namelist '(' LOCAL ',' type ')'
+
+state 0
+ $accept : . declaration $end (0)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ declaration goto 5
+ class goto 6
+ type goto 7
+
+
+state 1
+ class : GLOBAL . (3)
+
+ . reduce 3
+
+
+state 2
+ class : LOCAL . (4)
+
+ . reduce 4
+
+
+state 3
+ type : REAL . (5)
+
+ . reduce 5
+
+
+state 4
+ type : INTEGER . (6)
+
+ . reduce 6
+
+
+state 5
+ $accept : declaration . $end (0)
+
+ $end accept
+
+
+state 6
+ declaration : class . type namelist '(' class ',' type ')' (1)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 8
+
+
+state 7
+ declaration : type . locnamelist '(' class ')' (2)
+
+ NAME shift 9
+ . error
+
+ locnamelist goto 10
+ namelist goto 11
+
+
+state 8
+ declaration : class type . namelist '(' class ',' type ')' (1)
+
+ NAME shift 9
+ . error
+
+ namelist goto 12
+
+
+state 9
+ namelist : NAME . (8)
+
+ . reduce 8
+
+
+state 10
+ declaration : type locnamelist . '(' class ')' (2)
+
+ '(' shift 13
+ . error
+
+
+state 11
+ namelist : namelist . NAME (7)
+ locnamelist : namelist . '(' LOCAL ',' type ')' (9)
+
+ NAME shift 14
+ '(' shift 15
+ . error
+
+
+state 12
+ declaration : class type namelist . '(' class ',' type ')' (1)
+ namelist : namelist . NAME (7)
+
+ NAME shift 14
+ '(' shift 16
+ . error
+
+
+state 13
+ declaration : type locnamelist '(' . class ')' (2)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ . error
+
+ class goto 17
+
+
+state 14
+ namelist : namelist NAME . (7)
+
+ . reduce 7
+
+
+state 15
+ locnamelist : namelist '(' . LOCAL ',' type ')' (9)
+
+ LOCAL shift 18
+ . error
+
+
+state 16
+ declaration : class type namelist '(' . class ',' type ')' (1)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ . error
+
+ class goto 19
+
+
+state 17
+ declaration : type locnamelist '(' class . ')' (2)
+
+ ')' shift 20
+ . error
+
+
+state 18
+ locnamelist : namelist '(' LOCAL . ',' type ')' (9)
+
+ ',' shift 21
+ . error
+
+
+state 19
+ declaration : class type namelist '(' class . ',' type ')' (1)
+
+ ',' shift 22
+ . error
+
+
+state 20
+ declaration : type locnamelist '(' class ')' . (2)
+
+ . reduce 2
+
+
+state 21
+ locnamelist : namelist '(' LOCAL ',' . type ')' (9)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 23
+
+
+state 22
+ declaration : class type namelist '(' class ',' . type ')' (1)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 24
+
+
+state 23
+ locnamelist : namelist '(' LOCAL ',' type . ')' (9)
+
+ ')' shift 25
+ . error
+
+
+state 24
+ declaration : class type namelist '(' class ',' type . ')' (1)
+
+ ')' shift 26
+ . error
+
+
+state 25
+ locnamelist : namelist '(' LOCAL ',' type ')' . (9)
+
+ . reduce 9
+
+
+state 26
+ declaration : class type namelist '(' class ',' type ')' . (1)
+
+ . reduce 1
+
+
+10 terminals, 6 nonterminals
+10 grammar rules, 27 states
+
+grammar parser grammar
+symbol# value# symbol
+ 0 0 $end
+ 1 256 error
+ 2 257 GLOBAL
+ 3 258 LOCAL
+ 4 259 REAL
+ 5 260 INTEGER
+ 6 261 NAME
+ 7 40 '('
+ 8 44 ','
+ 9 41 ')'
+ 10 262 $accept
+ 11 263 declaration
+ 12 264 locnamelist
+ 13 265 class
+ 14 266 type
+ 15 267 namelist
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy1.tab.c b/contrib/byacc/test/btyacc/btyacc_destroy1.tab.c
new file mode 100644
index 0000000..85738e9
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy1.tab.c
@@ -0,0 +1,1451 @@
+/* original parser id follows */
+/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
+
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYCHECK "yyyymmdd"
+
+#define YYEMPTY (-1)
+#define yyclearin (yychar = YYEMPTY)
+#define yyerrok (yyerrflag = 0)
+#define YYRECOVERING() (yyerrflag != 0)
+#define YYENOMEM (-2)
+#define YYEOF 0
+#undef YYBTYACC
+#define YYBTYACC 1
+#define YYDEBUGSTR (yytrial ? YYPREFIX "debug(trial)" : YYPREFIX "debug")
+
+#ifndef yyparse
+#define yyparse destroy1_parse
+#endif /* yyparse */
+
+#ifndef yylex
+#define yylex destroy1_lex
+#endif /* yylex */
+
+#ifndef yyerror
+#define yyerror destroy1_error
+#endif /* yyerror */
+
+#ifndef yychar
+#define yychar destroy1_char
+#endif /* yychar */
+
+#ifndef yyval
+#define yyval destroy1_val
+#endif /* yyval */
+
+#ifndef yylval
+#define yylval destroy1_lval
+#endif /* yylval */
+
+#ifndef yydebug
+#define yydebug destroy1_debug
+#endif /* yydebug */
+
+#ifndef yynerrs
+#define yynerrs destroy1_nerrs
+#endif /* yynerrs */
+
+#ifndef yyerrflag
+#define yyerrflag destroy1_errflag
+#endif /* yyerrflag */
+
+#ifndef yylhs
+#define yylhs destroy1_lhs
+#endif /* yylhs */
+
+#ifndef yylen
+#define yylen destroy1_len
+#endif /* yylen */
+
+#ifndef yydefred
+#define yydefred destroy1_defred
+#endif /* yydefred */
+
+#ifndef yystos
+#define yystos destroy1_stos
+#endif /* yystos */
+
+#ifndef yydgoto
+#define yydgoto destroy1_dgoto
+#endif /* yydgoto */
+
+#ifndef yysindex
+#define yysindex destroy1_sindex
+#endif /* yysindex */
+
+#ifndef yyrindex
+#define yyrindex destroy1_rindex
+#endif /* yyrindex */
+
+#ifndef yygindex
+#define yygindex destroy1_gindex
+#endif /* yygindex */
+
+#ifndef yytable
+#define yytable destroy1_table
+#endif /* yytable */
+
+#ifndef yycheck
+#define yycheck destroy1_check
+#endif /* yycheck */
+
+#ifndef yyname
+#define yyname destroy1_name
+#endif /* yyname */
+
+#ifndef yyrule
+#define yyrule destroy1_rule
+#endif /* yyrule */
+
+#if YYBTYACC
+
+#ifndef yycindex
+#define yycindex destroy1_cindex
+#endif /* yycindex */
+
+#ifndef yyctable
+#define yyctable destroy1_ctable
+#endif /* yyctable */
+
+#endif /* YYBTYACC */
+
+#define YYPREFIX "destroy1_"
+
+#define YYPURE 0
+
+#line 4 "btyacc_destroy1.y"
+#include <stdlib.h>
+
+typedef enum {cGLOBAL, cLOCAL} class;
+typedef enum {tREAL, tINTEGER} type;
+typedef char * name;
+
+struct symbol { class c; type t; name id; };
+typedef struct symbol symbol;
+
+struct namelist { symbol *s; struct namelist *next; };
+typedef struct namelist namelist;
+
+struct parser_param {
+ int *rtrn;
+ symbol ss;
+};
+
+extern symbol *mksymbol(type t, class c, name id);
+
+#ifdef YYBISON
+#define YYLEX_DECL() yylex(void)
+#define YYERROR_DECL() yyerror(const char *s)
+#endif
+#line 50 "btyacc_destroy1.y"
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+#line 160 "btyacc_destroy1.tab.c"
+
+/* compatibility with bison */
+#ifdef YYPARSE_PARAM
+/* compatibility with FreeBSD */
+# ifdef YYPARSE_PARAM_TYPE
+# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
+# else
+# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
+# endif
+#else
+# define YYPARSE_DECL() yyparse(struct parser_param *param, int flag)
+#endif
+
+/* Parameters sent to lex. */
+#ifdef YYLEX_PARAM
+# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
+# define YYLEX yylex(YYLEX_PARAM)
+#else
+# define YYLEX_DECL() yylex(void)
+# define YYLEX yylex()
+#endif
+
+/* Parameters sent to yyerror. */
+#ifndef YYERROR_DECL
+#define YYERROR_DECL() yyerror(struct parser_param *param, int flag, const char *s)
+#endif
+#ifndef YYERROR_CALL
+#define YYERROR_CALL(msg) yyerror(param, flag, msg)
+#endif
+
+#ifndef YYDESTRUCT_DECL
+#define YYDESTRUCT_DECL() yydestruct(const char *msg, int psymb, YYSTYPE *val, struct parser_param *param, int flag)
+#endif
+#ifndef YYDESTRUCT_CALL
+#define YYDESTRUCT_CALL(msg, psymb, val) yydestruct(msg, psymb, val, param, flag)
+#endif
+
+extern int YYPARSE_DECL();
+
+#define GLOBAL 257
+#define LOCAL 258
+#define REAL 259
+#define INTEGER 260
+#define NAME 261
+#define YYERRCODE 256
+typedef short YYINT;
+static const YYINT destroy1_lhs[] = { -1,
+ 0, 0, 2, 2, 3, 3, 4, 4, 1,
+};
+static const YYINT destroy1_len[] = { 2,
+ 8, 5, 1, 1, 1, 1, 2, 1, 6,
+};
+static const YYINT destroy1_defred[] = { 0,
+ 3, 4, 5, 6, 0, 0, 0, 0, 8, 0,
+ 0, 0, 0, 7, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 9, 1,
+};
+static const YYINT destroy1_stos[] = { 0,
+ 257, 258, 259, 260, 263, 265, 266, 266, 261, 264,
+ 267, 267, 40, 261, 40, 40, 265, 258, 265, 41,
+ 44, 44, 266, 266, 41, 41,
+};
+static const YYINT destroy1_dgoto[] = { 5,
+ 10, 6, 7, 11,
+};
+static const YYINT destroy1_sindex[] = { -254,
+ 0, 0, 0, 0, 0, -251, -248, -248, 0, -26,
+ -40, -39, -246, 0, -243, -246, -25, -24, -23, 0,
+ -251, -251, -22, -19, 0, 0,
+};
+static const YYINT destroy1_rindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+};
+#if YYBTYACC
+static const YYINT destroy1_cindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+};
+#endif
+static const YYINT destroy1_gindex[] = { 0,
+ 0, -6, -4, 15,
+};
+#define YYTABLESIZE 222
+static const YYINT destroy1_table[] = { 15,
+ 16, 8, 1, 2, 3, 4, 17, 3, 4, 19,
+ 1, 2, 9, 13, 18, 20, 23, 24, 25, 21,
+ 22, 26, 12, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 14, 14,
+};
+static const YYINT destroy1_check[] = { 40,
+ 40, 6, 257, 258, 259, 260, 13, 259, 260, 16,
+ 257, 258, 261, 40, 258, 41, 21, 22, 41, 44,
+ 44, 41, 8, -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,
+ 261, 261,
+};
+#if YYBTYACC
+static const YYINT destroy1_ctable[] = { -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,
+};
+#endif
+#define YYFINAL 5
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 261
+#define YYUNDFTOKEN 268
+#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
+#if YYDEBUG
+static const char *const destroy1_name[] = {
+
+"$end",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"error","GLOBAL","LOCAL",
+"REAL","INTEGER","NAME","$accept","declaration","locnamelist","class","type",
+"namelist","illegal-symbol",
+};
+static const char *const destroy1_rule[] = {
+"$accept : declaration",
+"declaration : class type namelist '(' class ',' type ')'",
+"declaration : type locnamelist '(' class ')'",
+"class : GLOBAL",
+"class : LOCAL",
+"type : REAL",
+"type : INTEGER",
+"namelist : namelist NAME",
+"namelist : NAME",
+"locnamelist : namelist '(' LOCAL ',' type ')'",
+
+};
+#endif
+
+int yydebug;
+int yynerrs;
+
+int yyerrflag;
+int yychar;
+YYSTYPE yyval;
+YYSTYPE yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+YYLTYPE yyloc; /* position returned by actions */
+YYLTYPE yylloc; /* position from the lexer */
+#endif
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+#ifndef YYLLOC_DEFAULT
+#define YYLLOC_DEFAULT(loc, rhs, n) \
+do \
+{ \
+ if (n == 0) \
+ { \
+ (loc).first_line = ((rhs)[-1]).last_line; \
+ (loc).first_column = ((rhs)[-1]).last_column; \
+ (loc).last_line = ((rhs)[-1]).last_line; \
+ (loc).last_column = ((rhs)[-1]).last_column; \
+ } \
+ else \
+ { \
+ (loc).first_line = ((rhs)[ 0 ]).first_line; \
+ (loc).first_column = ((rhs)[ 0 ]).first_column; \
+ (loc).last_line = ((rhs)[n-1]).last_line; \
+ (loc).last_column = ((rhs)[n-1]).last_column; \
+ } \
+} while (0)
+#endif /* YYLLOC_DEFAULT */
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#if YYBTYACC
+
+#ifndef YYLVQUEUEGROWTH
+#define YYLVQUEUEGROWTH 32
+#endif
+#endif /* YYBTYACC */
+
+/* define the initial stack-sizes */
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+
+#ifndef YYINITSTACKSIZE
+#define YYINITSTACKSIZE 200
+#endif
+
+typedef struct {
+ unsigned stacksize;
+ short *s_base;
+ short *s_mark;
+ short *s_last;
+ YYSTYPE *l_base;
+ YYSTYPE *l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *p_base;
+ YYLTYPE *p_mark;
+#endif
+} YYSTACKDATA;
+#if YYBTYACC
+
+struct YYParseState_s
+{
+ struct YYParseState_s *save; /* Previously saved parser state */
+ YYSTACKDATA yystack; /* saved parser stack */
+ int state; /* saved parser state */
+ int errflag; /* saved error recovery status */
+ int lexeme; /* saved index of the conflict lexeme in the lexical queue */
+ YYINT ctry; /* saved index in yyctable[] for this conflict */
+};
+typedef struct YYParseState_s YYParseState;
+#endif /* YYBTYACC */
+/* variables for the parser stack */
+static YYSTACKDATA yystack;
+#if YYBTYACC
+
+/* Current parser state */
+static YYParseState *yyps = 0;
+
+/* yypath != NULL: do the full parse, starting at *yypath parser state. */
+static YYParseState *yypath = 0;
+
+/* Base of the lexical value queue */
+static YYSTYPE *yylvals = 0;
+
+/* Current position at lexical value queue */
+static YYSTYPE *yylvp = 0;
+
+/* End position of lexical value queue */
+static YYSTYPE *yylve = 0;
+
+/* The last allocated position at the lexical value queue */
+static YYSTYPE *yylvlim = 0;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+/* Base of the lexical position queue */
+static YYLTYPE *yylpsns = 0;
+
+/* Current position at lexical position queue */
+static YYLTYPE *yylpp = 0;
+
+/* End position of lexical position queue */
+static YYLTYPE *yylpe = 0;
+
+/* The last allocated position at the lexical position queue */
+static YYLTYPE *yylplim = 0;
+#endif
+
+/* Current position at lexical token queue */
+static short *yylexp = 0;
+
+static short *yylexemes = 0;
+#endif /* YYBTYACC */
+#line 89 "btyacc_destroy1.y"
+
+extern int YYLEX_DECL();
+extern void YYERROR_DECL();
+#line 487 "btyacc_destroy1.tab.c"
+
+/* Release memory associated with symbol. */
+#if ! defined YYDESTRUCT_IS_DECLARED
+static void
+YYDESTRUCT_DECL()
+{
+ switch (psymb)
+ {
+ case 263:
+#line 41 "btyacc_destroy1.y"
+ {
+ namelist *p = (*val).nlist;
+ while (p != NULL)
+ { namelist *pp = p;
+ p = p->next;
+ free(pp->s); free(pp);
+ }
+ }
+ break;
+#line 507 "btyacc_destroy1.tab.c"
+ }
+}
+#define YYDESTRUCT_IS_DECLARED 1
+#endif
+
+/* For use in generated program */
+#define yydepth (int)(yystack.s_mark - yystack.s_base)
+#if YYBTYACC
+#define yytrial (yyps->save)
+#endif /* YYBTYACC */
+
+#if YYDEBUG
+#include <stdio.h> /* needed for printf */
+#endif
+
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
+
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+static int yygrowstack(YYSTACKDATA *data)
+{
+ int i;
+ unsigned newsize;
+ short *newss;
+ YYSTYPE *newvs;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *newps;
+#endif
+
+ if ((newsize = data->stacksize) == 0)
+ newsize = YYINITSTACKSIZE;
+ else if (newsize >= YYMAXDEPTH)
+ return YYENOMEM;
+ else if ((newsize *= 2) > YYMAXDEPTH)
+ newsize = YYMAXDEPTH;
+
+ i = (int) (data->s_mark - data->s_base);
+ newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
+ if (newss == 0)
+ return YYENOMEM;
+
+ data->s_base = newss;
+ data->s_mark = newss + i;
+
+ newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
+ if (newvs == 0)
+ return YYENOMEM;
+
+ data->l_base = newvs;
+ data->l_mark = newvs + i;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ newps = (YYLTYPE *)realloc(data->p_base, newsize * sizeof(*newps));
+ if (newps == 0)
+ return YYENOMEM;
+
+ data->p_base = newps;
+ data->p_mark = newps + i;
+#endif
+
+ data->stacksize = newsize;
+ data->s_last = data->s_base + newsize - 1;
+
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%sdebug: stack size increased to %d\n", YYPREFIX, newsize);
+#endif
+ return 0;
+}
+
+#if YYPURE || defined(YY_NO_LEAKS)
+static void yyfreestack(YYSTACKDATA *data)
+{
+ free(data->s_base);
+ free(data->l_base);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ free(data->p_base);
+#endif
+ memset(data, 0, sizeof(*data));
+}
+#else
+#define yyfreestack(data) /* nothing */
+#endif /* YYPURE || defined(YY_NO_LEAKS) */
+#if YYBTYACC
+
+static YYParseState *
+yyNewState(unsigned size)
+{
+ YYParseState *p = (YYParseState *) malloc(sizeof(YYParseState));
+ if (p == NULL) return NULL;
+
+ p->yystack.stacksize = size;
+ if (size == 0)
+ {
+ p->yystack.s_base = NULL;
+ p->yystack.l_base = NULL;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ p->yystack.p_base = NULL;
+#endif
+ return p;
+ }
+ p->yystack.s_base = (short *) malloc(size * sizeof(short));
+ if (p->yystack.s_base == NULL) return NULL;
+ p->yystack.l_base = (YYSTYPE *) malloc(size * sizeof(YYSTYPE));
+ if (p->yystack.l_base == NULL) return NULL;
+ memset(p->yystack.l_base, 0, size * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ p->yystack.p_base = (YYLTYPE *) malloc(size * sizeof(YYLTYPE));
+ if (p->yystack.p_base == NULL) return NULL;
+ memset(p->yystack.p_base, 0, size * sizeof(YYLTYPE));
+#endif
+
+ return p;
+}
+
+static void
+yyFreeState(YYParseState *p)
+{
+ yyfreestack(&p->yystack);
+ free(p);
+}
+#endif /* YYBTYACC */
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+#if YYBTYACC
+#define YYVALID do { if (yyps->save) goto yyvalid; } while(0)
+#define YYVALID_NESTED do { if (yyps->save && \
+ yyps->save->save == 0) goto yyvalid; } while(0)
+#endif /* YYBTYACC */
+
+int
+YYPARSE_DECL()
+{
+ int yym, yyn, yystate, yyresult;
+#if YYBTYACC
+ int yynewerrflag;
+ YYParseState *yyerrctx = NULL;
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE yyerror_loc_range[2]; /* position of error start & end */
+#endif
+#if YYDEBUG
+ const char *yys;
+
+ if ((yys = getenv("YYDEBUG")) != 0)
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+ if (yydebug)
+ fprintf(stderr, "%sdebug[<# of symbols on state stack>]\n", YYPREFIX);
+#endif
+
+#if YYBTYACC
+ yyps = yyNewState(0); if (yyps == 0) goto yyenomem;
+ yyps->save = 0;
+#endif /* YYBTYACC */
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = YYEMPTY;
+ yystate = 0;
+
+#if YYPURE
+ memset(&yystack, 0, sizeof(yystack));
+#endif
+
+ if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystack.s_mark = yystack.s_base;
+ yystack.l_mark = yystack.l_base;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base;
+#endif
+ yystate = 0;
+ *yystack.s_mark = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+#if YYBTYACC
+ do {
+ if (yylvp < yylve)
+ {
+ /* we're currently re-reading tokens */
+ yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = *yylpp++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ if (yyps->save)
+ {
+ /* in trial mode; save scanner results for future parse attempts */
+ if (yylvp == yylvlim)
+ { /* Enlarge lexical value queue */
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
+
+ s += YYLVQUEUEGROWTH;
+ if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
+ if ((yylvals = (YYSTYPE *) realloc(yylvals, s * sizeof(YYSTYPE))) == NULL) goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ if ((yylpsns = (YYLTYPE *) realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL) goto yyenomem;
+#endif
+ yylvp = yylve = yylvals + p;
+ yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns + p;
+ yylplim = yylpsns + s;
+#endif
+ yylexp = yylexemes + p;
+ }
+ *yylexp = (short) YYLEX;
+ *yylvp++ = yylval;
+ yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpp++ = yylloc;
+ yylpe++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+ yychar = YYLEX;
+#if YYBTYACC
+ } while (0);
+#endif /* YYBTYACC */
+ if (yychar < 0) yychar = YYEOF;
+ /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, reading token %d (%s)",
+ YYDEBUGSTR, yydepth, yystate, yychar, yys);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, " <%s>", YYSTYPE_TOSTRING(yychar, yylval));
+#endif
+ fputc('\n', stderr);
+ }
+#endif
+ }
+#if YYBTYACC
+
+ /* Do we have a conflict? */
+ if (((yyn = yycindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+ YYINT ctry;
+
+ if (yypath)
+ {
+ YYParseState *save;
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: CONFLICT in state %d: following successful trial parse\n",
+ YYDEBUGSTR, yydepth, yystate);
+#endif
+ /* Switch to the next conflict context */
+ save = yypath;
+ yypath = save->save;
+ save->save = NULL;
+ ctry = save->ctry;
+ if (save->state != yystate) YYABORT;
+ yyFreeState(save);
+
+ }
+ else
+ {
+
+ /* Unresolved conflict - start/continue trial parse */
+ YYParseState *save;
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: CONFLICT in state %d. ", YYDEBUGSTR, yydepth, yystate);
+ if (yyps->save)
+ fputs("ALREADY in conflict, continuing trial parse.\n", stderr);
+ else
+ fputs("Starting trial parse.\n", stderr);
+ }
+#endif
+ save = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+ if (save == NULL) goto yyenomem;
+ save->save = yyps->save;
+ save->state = yystate;
+ save->errflag = yyerrflag;
+ save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ ctry = yytable[yyn];
+ if (yyctable[ctry] == -1)
+ {
+#if YYDEBUG
+ if (yydebug && yychar >= YYEOF)
+ fprintf(stderr, "%s[%d]: backtracking 1 token\n", YYDEBUGSTR, yydepth);
+#endif
+ ctry++;
+ }
+ save->ctry = ctry;
+ if (yyps->save == NULL)
+ {
+ /* If this is a first conflict in the stack, start saving lexemes */
+ if (!yylexemes)
+ {
+ yylexemes = (short *) malloc((YYLVQUEUEGROWTH) * sizeof(short));
+ if (yylexemes == NULL) goto yyenomem;
+ yylvals = (YYSTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYSTYPE));
+ if (yylvals == NULL) goto yyenomem;
+ yylvlim = yylvals + YYLVQUEUEGROWTH;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpsns = (YYLTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYLTYPE));
+ if (yylpsns == NULL) goto yyenomem;
+ yylplim = yylpsns + YYLVQUEUEGROWTH;
+#endif
+ }
+ if (yylvp == yylve)
+ {
+ yylvp = yylve = yylvals;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns;
+#endif
+ yylexp = yylexemes;
+ if (yychar >= YYEOF)
+ {
+ *yylve++ = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpe++ = yylloc;
+#endif
+ *yylexp = (short) yychar;
+ yychar = YYEMPTY;
+ }
+ }
+ }
+ if (yychar >= YYEOF)
+ {
+ yylvp--;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp--;
+#endif
+ yylexp--;
+ yychar = YYEMPTY;
+ }
+ save->lexeme = (int) (yylvp - yylvals);
+ yyps->save = save;
+ }
+ if (yytable[yyn] == ctry)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+ YYDEBUGSTR, yydepth, yystate, yyctable[ctry]);
+#endif
+ if (yychar < 0)
+ {
+ yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp++;
+#endif
+ yylexp++;
+ }
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
+ goto yyoverflow;
+ yystate = yyctable[ctry];
+ *++yystack.s_mark = (short) yystate;
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yylloc;
+#endif
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ else
+ {
+ yyn = yyctable[ctry];
+ goto yyreduce;
+ }
+ } /* End of code dealing with conflicts */
+#endif /* YYBTYACC */
+ if (((yyn = yysindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+ YYDEBUGSTR, yydepth, yystate, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yylloc;
+#endif
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if (((yyn = yyrindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag != 0) goto yyinrecovery;
+#if YYBTYACC
+
+ yynewerrflag = 1;
+ goto yyerrhandler;
+ goto yyerrlab;
+
+yyerrlab:
+ yynewerrflag = 0;
+yyerrhandler:
+ while (yyps->save)
+ {
+ int ctry;
+ YYParseState *save = yyps->save;
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: ERROR in state %d, CONFLICT BACKTRACKING to state %d, %d tokens\n",
+ YYDEBUGSTR, yydepth, yystate, yyps->save->state,
+ (int)(yylvp - yylvals - yyps->save->lexeme));
+#endif
+ /* Memorize most forward-looking error state in case it's really an error. */
+ if (yyerrctx == NULL || yyerrctx->lexeme < yylvp - yylvals)
+ {
+ /* Free old saved error context state */
+ if (yyerrctx) yyFreeState(yyerrctx);
+ /* Create and fill out new saved error context state */
+ yyerrctx = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+ if (yyerrctx == NULL) goto yyenomem;
+ yyerrctx->save = yyps->save;
+ yyerrctx->state = yystate;
+ yyerrctx->errflag = yyerrflag;
+ yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
+ }
+ yylvp = yylvals + save->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + save->lexeme;
+#endif
+ yylexp = yylexemes + save->lexeme;
+ yychar = YYEMPTY;
+ yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ ctry = ++save->ctry;
+ yystate = save->state;
+ /* We tried shift, try reduce now */
+ if ((yyn = yyctable[ctry]) >= 0) goto yyreduce;
+ yyps->save = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+
+ /* Nothing left on the stack -- error */
+ if (!yyps->save)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%sdebug[%d,trial]: trial parse FAILED, entering ERROR mode\n",
+ YYPREFIX, yydepth);
+#endif
+ /* Restore state as it was in the most forward-advanced error */
+ yylvp = yylvals + yyerrctx->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + yyerrctx->lexeme;
+#endif
+ yylexp = yylexemes + yyerrctx->lexeme;
+ yychar = yylexp[-1];
+ yylval = yylvp[-1];
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = yylpp[-1];
+#endif
+ yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yystate = yyerrctx->state;
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ yynewerrflag = 1;
+ }
+ if (yynewerrflag == 0) goto yyinrecovery;
+#endif /* YYBTYACC */
+
+ YYERROR_CALL("syntax error");
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yyerror_loc_range[0] = yylloc; /* lookahead position is error start position */
+#endif
+
+#if !YYBTYACC
+ goto yyerrlab;
+yyerrlab:
+#endif
+ ++yynerrs;
+
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if (((yyn = yysindex[*yystack.s_mark]) != 0) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, error recovery shifting to state %d\n",
+ YYDEBUGSTR, yydepth, *yystack.s_mark, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ /* lookahead position is error end position */
+ yyerror_loc_range[1] = yylloc;
+ YYLLOC_DEFAULT(yyloc, yyerror_loc_range, 2); /* position of error span */
+ *++yystack.p_mark = yyloc;
+#endif
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: error recovery discarding state %d\n",
+ YYDEBUGSTR, yydepth, *yystack.s_mark);
+#endif
+ if (yystack.s_mark <= yystack.s_base) goto yyabort;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ /* the current TOS position is the error start position */
+ yyerror_loc_range[0] = *yystack.p_mark;
+#endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("error: discarding state",
+ yystos[*yystack.s_mark], yystack.l_mark, yystack.p_mark);
+#else
+ YYDESTRUCT_CALL("error: discarding state",
+ yystos[*yystack.s_mark], yystack.l_mark);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
+ --yystack.s_mark;
+ --yystack.l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ --yystack.p_mark;
+#endif
+ }
+ }
+ }
+ else
+ {
+ if (yychar == YYEOF) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, error recovery discarding token %d (%s)\n",
+ YYDEBUGSTR, yydepth, yystate, yychar, yys);
+ }
+#endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("error: discarding token", yychar, &yylval, &yylloc);
+#else
+ YYDESTRUCT_CALL("error: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
+ yychar = YYEMPTY;
+ goto yyloop;
+ }
+
+yyreduce:
+ yym = yylen[yyn];
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: state %d, reducing by rule %d (%s)",
+ YYDEBUGSTR, yydepth, yystate, yyn, yyrule[yyn]);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ if (yym > 0)
+ {
+ int i;
+ fputc('<', stderr);
+ for (i = yym; i > 0; i--)
+ {
+ if (i != yym) fputs(", ", stderr);
+ fputs(YYSTYPE_TOSTRING(yystos[yystack.s_mark[1-i]],
+ yystack.l_mark[1-i]), stderr);
+ }
+ fputc('>', stderr);
+ }
+#endif
+ fputc('\n', stderr);
+ }
+#endif
+ if (yym > 0)
+ yyval = yystack.l_mark[1-yym];
+ else
+ memset(&yyval, 0, sizeof yyval);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+
+ /* Perform position reduction */
+ memset(&yyloc, 0, sizeof(yyloc));
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ {
+ YYLLOC_DEFAULT(yyloc, &yystack.p_mark[1-yym], yym);
+ /* just in case YYERROR is invoked within the action, save
+ the start of the rhs as the error start position */
+ yyerror_loc_range[0] = yystack.p_mark[1-yym];
+ }
+#endif
+
+ switch (yyn)
+ {
+case 1:
+ if (!yytrial)
+#line 62 "btyacc_destroy1.y"
+ { yyval.nlist = yystack.l_mark[-5].nlist; }
+break;
+case 2:
+ if (!yytrial)
+#line 64 "btyacc_destroy1.y"
+ { yyval.nlist = yystack.l_mark[-3].nlist; }
+break;
+case 3:
+ if (!yytrial)
+#line 67 "btyacc_destroy1.y"
+ { yyval.cval = cGLOBAL; }
+break;
+case 4:
+ if (!yytrial)
+#line 68 "btyacc_destroy1.y"
+ { yyval.cval = cLOCAL; }
+break;
+case 5:
+ if (!yytrial)
+#line 71 "btyacc_destroy1.y"
+ { yyval.tval = tREAL; }
+break;
+case 6:
+ if (!yytrial)
+#line 72 "btyacc_destroy1.y"
+ { yyval.tval = tINTEGER; }
+break;
+case 7:
+ if (!yytrial)
+#line 76 "btyacc_destroy1.y"
+ { yyval.nlist->s = mksymbol(yystack.l_mark[-2].tval, yystack.l_mark[-2].cval, yystack.l_mark[0].id);
+ yyval.nlist->next = yystack.l_mark[-1].nlist;
+ }
+break;
+case 8:
+ if (!yytrial)
+#line 80 "btyacc_destroy1.y"
+ { yyval.nlist->s = mksymbol(0, 0, yystack.l_mark[0].id);
+ yyval.nlist->next = NULL;
+ }
+break;
+case 9:
+ if (!yytrial)
+#line 86 "btyacc_destroy1.y"
+ { yyval.nlist = yystack.l_mark[-5].nlist; }
+break;
+#line 1217 "btyacc_destroy1.tab.c"
+ default:
+ break;
+ }
+ yystack.s_mark -= yym;
+ yystate = *yystack.s_mark;
+ yystack.l_mark -= yym;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark -= yym;
+#endif
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[YYFINAL], yyval));
+#endif
+ fprintf(stderr, "shifting from state 0 to final state %d\n", YYFINAL);
+ }
+#endif
+ yystate = YYFINAL;
+ *++yystack.s_mark = YYFINAL;
+ *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yyloc;
+#endif
+ if (yychar < 0)
+ {
+#if YYBTYACC
+ do {
+ if (yylvp < yylve)
+ {
+ /* we're currently re-reading tokens */
+ yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = *yylpp++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ if (yyps->save)
+ {
+ /* in trial mode; save scanner results for future parse attempts */
+ if (yylvp == yylvlim)
+ { /* Enlarge lexical value queue */
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
+
+ s += YYLVQUEUEGROWTH;
+ if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
+ goto yyenomem;
+ if ((yylvals = (YYSTYPE *) realloc(yylvals, s * sizeof(YYSTYPE))) == NULL)
+ goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ if ((yylpsns = (YYLTYPE *) realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL)
+ goto yyenomem;
+#endif
+ yylvp = yylve = yylvals + p;
+ yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns + p;
+ yylplim = yylpsns + s;
+#endif
+ yylexp = yylexemes + p;
+ }
+ *yylexp = (short) YYLEX;
+ *yylvp++ = yylval;
+ yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpp++ = yylloc;
+ yylpe++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+ yychar = YYLEX;
+#if YYBTYACC
+ } while (0);
+#endif /* YYBTYACC */
+ if (yychar < 0) yychar = YYEOF;
+ /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, reading %d (%s)\n",
+ YYDEBUGSTR, yydepth, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == YYEOF) goto yyaccept;
+ goto yyloop;
+ }
+ if (((yyn = yygindex[yym]) != 0) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[yystate], yyval));
+#endif
+ fprintf(stderr, "shifting from state %d to state %d\n", *yystack.s_mark, yystate);
+ }
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ *++yystack.s_mark = (short) yystate;
+ *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yyloc;
+#endif
+ goto yyloop;
+#if YYBTYACC
+
+ /* Reduction declares that this path is valid. Set yypath and do a full parse */
+yyvalid:
+ if (yypath) YYABORT;
+ while (yyps->save)
+ {
+ YYParseState *save = yyps->save;
+ yyps->save = save->save;
+ save->save = yypath;
+ yypath = save;
+ }
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, CONFLICT trial successful, backtracking to state %d, %d tokens\n",
+ YYDEBUGSTR, yydepth, yystate, yypath->state, (int)(yylvp - yylvals - yypath->lexeme));
+#endif
+ if (yyerrctx)
+ {
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ yylvp = yylvals + yypath->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + yypath->lexeme;
+#endif
+ yylexp = yylexemes + yypath->lexeme;
+ yychar = YYEMPTY;
+ yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yystate = yypath->state;
+ goto yyloop;
+#endif /* YYBTYACC */
+
+yyoverflow:
+ YYERROR_CALL("yacc stack overflow");
+#if YYBTYACC
+ goto yyabort_nomem;
+yyenomem:
+ YYERROR_CALL("memory exhausted");
+yyabort_nomem:
+#endif /* YYBTYACC */
+ yyresult = 2;
+ goto yyreturn;
+
+yyabort:
+ yyresult = 1;
+ goto yyreturn;
+
+yyaccept:
+#if YYBTYACC
+ if (yyps->save) goto yyvalid;
+#endif /* YYBTYACC */
+ yyresult = 0;
+
+yyreturn:
+#if defined(YYDESTRUCT_CALL)
+ if (yychar != YYEOF && yychar != YYEMPTY)
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval, &yylloc);
+#else
+ YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+
+ {
+ YYSTYPE *pv;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *pp;
+
+ for (pv = yystack.l_base, pp = yystack.p_base; pv <= yystack.l_mark; ++pv, ++pp)
+ YYDESTRUCT_CALL("cleanup: discarding state",
+ yystos[*(yystack.s_base + (pv - yystack.l_base))], pv, pp);
+#else
+ for (pv = yystack.l_base; pv <= yystack.l_mark; ++pv)
+ YYDESTRUCT_CALL("cleanup: discarding state",
+ yystos[*(yystack.s_base + (pv - yystack.l_base))], pv);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+ }
+#endif /* defined(YYDESTRUCT_CALL) */
+
+#if YYBTYACC
+ if (yyerrctx)
+ {
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ while (yyps)
+ {
+ YYParseState *save = yyps;
+ yyps = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+ }
+ while (yypath)
+ {
+ YYParseState *save = yypath;
+ yypath = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+ }
+#endif /* YYBTYACC */
+ yyfreestack(&yystack);
+ return (yyresult);
+}
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy1.tab.h b/contrib/byacc/test/btyacc/btyacc_destroy1.tab.h
new file mode 100644
index 0000000..21b0bc2
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy1.tab.h
@@ -0,0 +1,25 @@
+#ifndef _destroy1__defines_h_
+#define _destroy1__defines_h_
+
+#define GLOBAL 257
+#define LOCAL 258
+#define REAL 259
+#define INTEGER 260
+#define NAME 261
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+extern YYSTYPE destroy1_lval;
+
+#endif /* _destroy1__defines_h_ */
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy2.error b/contrib/byacc/test/btyacc/btyacc_destroy2.error
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy2.error
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy2.output b/contrib/byacc/test/btyacc/btyacc_destroy2.output
new file mode 100644
index 0000000..918354c
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy2.output
@@ -0,0 +1,247 @@
+ 0 $accept : declaration $end
+
+ 1 declaration : class type namelist '(' class ',' type ')'
+ 2 | type locnamelist '(' class ')'
+
+ 3 class : GLOBAL
+ 4 | LOCAL
+
+ 5 type : REAL
+ 6 | INTEGER
+
+ 7 namelist : namelist NAME
+ 8 | NAME
+
+ 9 locnamelist : namelist '(' LOCAL ',' type ')'
+
+state 0
+ $accept : . declaration $end (0)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ declaration goto 5
+ class goto 6
+ type goto 7
+
+
+state 1
+ class : GLOBAL . (3)
+
+ . reduce 3
+
+
+state 2
+ class : LOCAL . (4)
+
+ . reduce 4
+
+
+state 3
+ type : REAL . (5)
+
+ . reduce 5
+
+
+state 4
+ type : INTEGER . (6)
+
+ . reduce 6
+
+
+state 5
+ $accept : declaration . $end (0)
+
+ $end accept
+
+
+state 6
+ declaration : class . type namelist '(' class ',' type ')' (1)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 8
+
+
+state 7
+ declaration : type . locnamelist '(' class ')' (2)
+
+ NAME shift 9
+ . error
+
+ locnamelist goto 10
+ namelist goto 11
+
+
+state 8
+ declaration : class type . namelist '(' class ',' type ')' (1)
+
+ NAME shift 9
+ . error
+
+ namelist goto 12
+
+
+state 9
+ namelist : NAME . (8)
+
+ . reduce 8
+
+
+state 10
+ declaration : type locnamelist . '(' class ')' (2)
+
+ '(' shift 13
+ . error
+
+
+state 11
+ namelist : namelist . NAME (7)
+ locnamelist : namelist . '(' LOCAL ',' type ')' (9)
+
+ NAME shift 14
+ '(' shift 15
+ . error
+
+
+state 12
+ declaration : class type namelist . '(' class ',' type ')' (1)
+ namelist : namelist . NAME (7)
+
+ NAME shift 14
+ '(' shift 16
+ . error
+
+
+state 13
+ declaration : type locnamelist '(' . class ')' (2)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ . error
+
+ class goto 17
+
+
+state 14
+ namelist : namelist NAME . (7)
+
+ . reduce 7
+
+
+state 15
+ locnamelist : namelist '(' . LOCAL ',' type ')' (9)
+
+ LOCAL shift 18
+ . error
+
+
+state 16
+ declaration : class type namelist '(' . class ',' type ')' (1)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ . error
+
+ class goto 19
+
+
+state 17
+ declaration : type locnamelist '(' class . ')' (2)
+
+ ')' shift 20
+ . error
+
+
+state 18
+ locnamelist : namelist '(' LOCAL . ',' type ')' (9)
+
+ ',' shift 21
+ . error
+
+
+state 19
+ declaration : class type namelist '(' class . ',' type ')' (1)
+
+ ',' shift 22
+ . error
+
+
+state 20
+ declaration : type locnamelist '(' class ')' . (2)
+
+ . reduce 2
+
+
+state 21
+ locnamelist : namelist '(' LOCAL ',' . type ')' (9)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 23
+
+
+state 22
+ declaration : class type namelist '(' class ',' . type ')' (1)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 24
+
+
+state 23
+ locnamelist : namelist '(' LOCAL ',' type . ')' (9)
+
+ ')' shift 25
+ . error
+
+
+state 24
+ declaration : class type namelist '(' class ',' type . ')' (1)
+
+ ')' shift 26
+ . error
+
+
+state 25
+ locnamelist : namelist '(' LOCAL ',' type ')' . (9)
+
+ . reduce 9
+
+
+state 26
+ declaration : class type namelist '(' class ',' type ')' . (1)
+
+ . reduce 1
+
+
+10 terminals, 6 nonterminals
+10 grammar rules, 27 states
+
+grammar parser grammar
+symbol# value# symbol
+ 0 0 $end
+ 1 256 error
+ 2 257 GLOBAL
+ 3 258 LOCAL
+ 4 259 REAL
+ 5 260 INTEGER
+ 6 261 NAME
+ 7 40 '('
+ 8 44 ','
+ 9 41 ')'
+ 10 262 $accept
+ 11 263 declaration
+ 12 264 locnamelist
+ 13 265 class
+ 14 266 type
+ 15 267 namelist
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy2.tab.c b/contrib/byacc/test/btyacc/btyacc_destroy2.tab.c
new file mode 100644
index 0000000..2441008
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy2.tab.c
@@ -0,0 +1,1451 @@
+/* original parser id follows */
+/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
+
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYCHECK "yyyymmdd"
+
+#define YYEMPTY (-1)
+#define yyclearin (yychar = YYEMPTY)
+#define yyerrok (yyerrflag = 0)
+#define YYRECOVERING() (yyerrflag != 0)
+#define YYENOMEM (-2)
+#define YYEOF 0
+#undef YYBTYACC
+#define YYBTYACC 1
+#define YYDEBUGSTR (yytrial ? YYPREFIX "debug(trial)" : YYPREFIX "debug")
+
+#ifndef yyparse
+#define yyparse destroy2_parse
+#endif /* yyparse */
+
+#ifndef yylex
+#define yylex destroy2_lex
+#endif /* yylex */
+
+#ifndef yyerror
+#define yyerror destroy2_error
+#endif /* yyerror */
+
+#ifndef yychar
+#define yychar destroy2_char
+#endif /* yychar */
+
+#ifndef yyval
+#define yyval destroy2_val
+#endif /* yyval */
+
+#ifndef yylval
+#define yylval destroy2_lval
+#endif /* yylval */
+
+#ifndef yydebug
+#define yydebug destroy2_debug
+#endif /* yydebug */
+
+#ifndef yynerrs
+#define yynerrs destroy2_nerrs
+#endif /* yynerrs */
+
+#ifndef yyerrflag
+#define yyerrflag destroy2_errflag
+#endif /* yyerrflag */
+
+#ifndef yylhs
+#define yylhs destroy2_lhs
+#endif /* yylhs */
+
+#ifndef yylen
+#define yylen destroy2_len
+#endif /* yylen */
+
+#ifndef yydefred
+#define yydefred destroy2_defred
+#endif /* yydefred */
+
+#ifndef yystos
+#define yystos destroy2_stos
+#endif /* yystos */
+
+#ifndef yydgoto
+#define yydgoto destroy2_dgoto
+#endif /* yydgoto */
+
+#ifndef yysindex
+#define yysindex destroy2_sindex
+#endif /* yysindex */
+
+#ifndef yyrindex
+#define yyrindex destroy2_rindex
+#endif /* yyrindex */
+
+#ifndef yygindex
+#define yygindex destroy2_gindex
+#endif /* yygindex */
+
+#ifndef yytable
+#define yytable destroy2_table
+#endif /* yytable */
+
+#ifndef yycheck
+#define yycheck destroy2_check
+#endif /* yycheck */
+
+#ifndef yyname
+#define yyname destroy2_name
+#endif /* yyname */
+
+#ifndef yyrule
+#define yyrule destroy2_rule
+#endif /* yyrule */
+
+#if YYBTYACC
+
+#ifndef yycindex
+#define yycindex destroy2_cindex
+#endif /* yycindex */
+
+#ifndef yyctable
+#define yyctable destroy2_ctable
+#endif /* yyctable */
+
+#endif /* YYBTYACC */
+
+#define YYPREFIX "destroy2_"
+
+#define YYPURE 0
+
+#line 4 "btyacc_destroy2.y"
+#include <stdlib.h>
+
+typedef enum {cGLOBAL, cLOCAL} class;
+typedef enum {tREAL, tINTEGER} type;
+typedef char * name;
+
+struct symbol { class c; type t; name id; };
+typedef struct symbol symbol;
+
+struct namelist { symbol *s; struct namelist *next; };
+typedef struct namelist namelist;
+
+struct parser_param {
+ int *rtrn;
+ symbol ss;
+};
+
+extern symbol *mksymbol(type t, class c, name id);
+
+#ifdef YYBISON
+#define YYLEX_DECL() yylex(void)
+#define YYERROR_DECL() yyerror(const char *s)
+#endif
+#line 50 "btyacc_destroy2.y"
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+#line 160 "btyacc_destroy2.tab.c"
+
+/* compatibility with bison */
+#ifdef YYPARSE_PARAM
+/* compatibility with FreeBSD */
+# ifdef YYPARSE_PARAM_TYPE
+# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
+# else
+# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
+# endif
+#else
+# define YYPARSE_DECL() yyparse(struct parser_param *param, int flag)
+#endif
+
+/* Parameters sent to lex. */
+#ifdef YYLEX_PARAM
+# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
+# define YYLEX yylex(YYLEX_PARAM)
+#else
+# define YYLEX_DECL() yylex(void)
+# define YYLEX yylex()
+#endif
+
+/* Parameters sent to yyerror. */
+#ifndef YYERROR_DECL
+#define YYERROR_DECL() yyerror(struct parser_param *param, int flag, const char *s)
+#endif
+#ifndef YYERROR_CALL
+#define YYERROR_CALL(msg) yyerror(param, flag, msg)
+#endif
+
+#ifndef YYDESTRUCT_DECL
+#define YYDESTRUCT_DECL() yydestruct(const char *msg, int psymb, YYSTYPE *val, struct parser_param *param, int flag)
+#endif
+#ifndef YYDESTRUCT_CALL
+#define YYDESTRUCT_CALL(msg, psymb, val) yydestruct(msg, psymb, val, param, flag)
+#endif
+
+extern int YYPARSE_DECL();
+
+#define GLOBAL 257
+#define LOCAL 258
+#define REAL 259
+#define INTEGER 260
+#define NAME 261
+#define YYERRCODE 256
+typedef short YYINT;
+static const YYINT destroy2_lhs[] = { -1,
+ 0, 0, 2, 2, 3, 3, 4, 4, 1,
+};
+static const YYINT destroy2_len[] = { 2,
+ 8, 5, 1, 1, 1, 1, 2, 1, 6,
+};
+static const YYINT destroy2_defred[] = { 0,
+ 3, 4, 5, 6, 0, 0, 0, 0, 8, 0,
+ 0, 0, 0, 7, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 9, 1,
+};
+static const YYINT destroy2_stos[] = { 0,
+ 257, 258, 259, 260, 263, 265, 266, 266, 261, 264,
+ 267, 267, 40, 261, 40, 40, 265, 258, 265, 41,
+ 44, 44, 266, 266, 41, 41,
+};
+static const YYINT destroy2_dgoto[] = { 5,
+ 10, 6, 7, 11,
+};
+static const YYINT destroy2_sindex[] = { -254,
+ 0, 0, 0, 0, 0, -251, -248, -248, 0, -26,
+ -40, -39, -246, 0, -243, -246, -25, -24, -23, 0,
+ -251, -251, -22, -19, 0, 0,
+};
+static const YYINT destroy2_rindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+};
+#if YYBTYACC
+static const YYINT destroy2_cindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+};
+#endif
+static const YYINT destroy2_gindex[] = { 0,
+ 0, -6, -4, 15,
+};
+#define YYTABLESIZE 222
+static const YYINT destroy2_table[] = { 15,
+ 16, 8, 1, 2, 3, 4, 17, 3, 4, 19,
+ 1, 2, 9, 13, 18, 20, 23, 24, 25, 21,
+ 22, 26, 12, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 14, 14,
+};
+static const YYINT destroy2_check[] = { 40,
+ 40, 6, 257, 258, 259, 260, 13, 259, 260, 16,
+ 257, 258, 261, 40, 258, 41, 21, 22, 41, 44,
+ 44, 41, 8, -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,
+ 261, 261,
+};
+#if YYBTYACC
+static const YYINT destroy2_ctable[] = { -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,
+};
+#endif
+#define YYFINAL 5
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 261
+#define YYUNDFTOKEN 268
+#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
+#if YYDEBUG
+static const char *const destroy2_name[] = {
+
+"$end",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"error","GLOBAL","LOCAL",
+"REAL","INTEGER","NAME","$accept","declaration","locnamelist","class","type",
+"namelist","illegal-symbol",
+};
+static const char *const destroy2_rule[] = {
+"$accept : declaration",
+"declaration : class type namelist '(' class ',' type ')'",
+"declaration : type locnamelist '(' class ')'",
+"class : GLOBAL",
+"class : LOCAL",
+"type : REAL",
+"type : INTEGER",
+"namelist : namelist NAME",
+"namelist : NAME",
+"locnamelist : namelist '(' LOCAL ',' type ')'",
+
+};
+#endif
+
+int yydebug;
+int yynerrs;
+
+int yyerrflag;
+int yychar;
+YYSTYPE yyval;
+YYSTYPE yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+YYLTYPE yyloc; /* position returned by actions */
+YYLTYPE yylloc; /* position from the lexer */
+#endif
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+#ifndef YYLLOC_DEFAULT
+#define YYLLOC_DEFAULT(loc, rhs, n) \
+do \
+{ \
+ if (n == 0) \
+ { \
+ (loc).first_line = ((rhs)[-1]).last_line; \
+ (loc).first_column = ((rhs)[-1]).last_column; \
+ (loc).last_line = ((rhs)[-1]).last_line; \
+ (loc).last_column = ((rhs)[-1]).last_column; \
+ } \
+ else \
+ { \
+ (loc).first_line = ((rhs)[ 0 ]).first_line; \
+ (loc).first_column = ((rhs)[ 0 ]).first_column; \
+ (loc).last_line = ((rhs)[n-1]).last_line; \
+ (loc).last_column = ((rhs)[n-1]).last_column; \
+ } \
+} while (0)
+#endif /* YYLLOC_DEFAULT */
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#if YYBTYACC
+
+#ifndef YYLVQUEUEGROWTH
+#define YYLVQUEUEGROWTH 32
+#endif
+#endif /* YYBTYACC */
+
+/* define the initial stack-sizes */
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+
+#ifndef YYINITSTACKSIZE
+#define YYINITSTACKSIZE 200
+#endif
+
+typedef struct {
+ unsigned stacksize;
+ short *s_base;
+ short *s_mark;
+ short *s_last;
+ YYSTYPE *l_base;
+ YYSTYPE *l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *p_base;
+ YYLTYPE *p_mark;
+#endif
+} YYSTACKDATA;
+#if YYBTYACC
+
+struct YYParseState_s
+{
+ struct YYParseState_s *save; /* Previously saved parser state */
+ YYSTACKDATA yystack; /* saved parser stack */
+ int state; /* saved parser state */
+ int errflag; /* saved error recovery status */
+ int lexeme; /* saved index of the conflict lexeme in the lexical queue */
+ YYINT ctry; /* saved index in yyctable[] for this conflict */
+};
+typedef struct YYParseState_s YYParseState;
+#endif /* YYBTYACC */
+/* variables for the parser stack */
+static YYSTACKDATA yystack;
+#if YYBTYACC
+
+/* Current parser state */
+static YYParseState *yyps = 0;
+
+/* yypath != NULL: do the full parse, starting at *yypath parser state. */
+static YYParseState *yypath = 0;
+
+/* Base of the lexical value queue */
+static YYSTYPE *yylvals = 0;
+
+/* Current position at lexical value queue */
+static YYSTYPE *yylvp = 0;
+
+/* End position of lexical value queue */
+static YYSTYPE *yylve = 0;
+
+/* The last allocated position at the lexical value queue */
+static YYSTYPE *yylvlim = 0;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+/* Base of the lexical position queue */
+static YYLTYPE *yylpsns = 0;
+
+/* Current position at lexical position queue */
+static YYLTYPE *yylpp = 0;
+
+/* End position of lexical position queue */
+static YYLTYPE *yylpe = 0;
+
+/* The last allocated position at the lexical position queue */
+static YYLTYPE *yylplim = 0;
+#endif
+
+/* Current position at lexical token queue */
+static short *yylexp = 0;
+
+static short *yylexemes = 0;
+#endif /* YYBTYACC */
+#line 89 "btyacc_destroy2.y"
+
+extern int YYLEX_DECL();
+extern void YYERROR_DECL();
+#line 487 "btyacc_destroy2.tab.c"
+
+/* Release memory associated with symbol. */
+#if ! defined YYDESTRUCT_IS_DECLARED
+static void
+YYDESTRUCT_DECL()
+{
+ switch (psymb)
+ {
+ case 263:
+#line 41 "btyacc_destroy2.y"
+ {
+ namelist *p = (*val).nlist;
+ while (p != NULL)
+ { namelist *pp = p;
+ p = p->next;
+ free(pp->s); free(pp);
+ }
+ }
+ break;
+#line 507 "btyacc_destroy2.tab.c"
+ }
+}
+#define YYDESTRUCT_IS_DECLARED 1
+#endif
+
+/* For use in generated program */
+#define yydepth (int)(yystack.s_mark - yystack.s_base)
+#if YYBTYACC
+#define yytrial (yyps->save)
+#endif /* YYBTYACC */
+
+#if YYDEBUG
+#include <stdio.h> /* needed for printf */
+#endif
+
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
+
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+static int yygrowstack(YYSTACKDATA *data)
+{
+ int i;
+ unsigned newsize;
+ short *newss;
+ YYSTYPE *newvs;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *newps;
+#endif
+
+ if ((newsize = data->stacksize) == 0)
+ newsize = YYINITSTACKSIZE;
+ else if (newsize >= YYMAXDEPTH)
+ return YYENOMEM;
+ else if ((newsize *= 2) > YYMAXDEPTH)
+ newsize = YYMAXDEPTH;
+
+ i = (int) (data->s_mark - data->s_base);
+ newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
+ if (newss == 0)
+ return YYENOMEM;
+
+ data->s_base = newss;
+ data->s_mark = newss + i;
+
+ newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
+ if (newvs == 0)
+ return YYENOMEM;
+
+ data->l_base = newvs;
+ data->l_mark = newvs + i;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ newps = (YYLTYPE *)realloc(data->p_base, newsize * sizeof(*newps));
+ if (newps == 0)
+ return YYENOMEM;
+
+ data->p_base = newps;
+ data->p_mark = newps + i;
+#endif
+
+ data->stacksize = newsize;
+ data->s_last = data->s_base + newsize - 1;
+
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%sdebug: stack size increased to %d\n", YYPREFIX, newsize);
+#endif
+ return 0;
+}
+
+#if YYPURE || defined(YY_NO_LEAKS)
+static void yyfreestack(YYSTACKDATA *data)
+{
+ free(data->s_base);
+ free(data->l_base);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ free(data->p_base);
+#endif
+ memset(data, 0, sizeof(*data));
+}
+#else
+#define yyfreestack(data) /* nothing */
+#endif /* YYPURE || defined(YY_NO_LEAKS) */
+#if YYBTYACC
+
+static YYParseState *
+yyNewState(unsigned size)
+{
+ YYParseState *p = (YYParseState *) malloc(sizeof(YYParseState));
+ if (p == NULL) return NULL;
+
+ p->yystack.stacksize = size;
+ if (size == 0)
+ {
+ p->yystack.s_base = NULL;
+ p->yystack.l_base = NULL;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ p->yystack.p_base = NULL;
+#endif
+ return p;
+ }
+ p->yystack.s_base = (short *) malloc(size * sizeof(short));
+ if (p->yystack.s_base == NULL) return NULL;
+ p->yystack.l_base = (YYSTYPE *) malloc(size * sizeof(YYSTYPE));
+ if (p->yystack.l_base == NULL) return NULL;
+ memset(p->yystack.l_base, 0, size * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ p->yystack.p_base = (YYLTYPE *) malloc(size * sizeof(YYLTYPE));
+ if (p->yystack.p_base == NULL) return NULL;
+ memset(p->yystack.p_base, 0, size * sizeof(YYLTYPE));
+#endif
+
+ return p;
+}
+
+static void
+yyFreeState(YYParseState *p)
+{
+ yyfreestack(&p->yystack);
+ free(p);
+}
+#endif /* YYBTYACC */
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+#if YYBTYACC
+#define YYVALID do { if (yyps->save) goto yyvalid; } while(0)
+#define YYVALID_NESTED do { if (yyps->save && \
+ yyps->save->save == 0) goto yyvalid; } while(0)
+#endif /* YYBTYACC */
+
+int
+YYPARSE_DECL()
+{
+ int yym, yyn, yystate, yyresult;
+#if YYBTYACC
+ int yynewerrflag;
+ YYParseState *yyerrctx = NULL;
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE yyerror_loc_range[2]; /* position of error start & end */
+#endif
+#if YYDEBUG
+ const char *yys;
+
+ if ((yys = getenv("YYDEBUG")) != 0)
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+ if (yydebug)
+ fprintf(stderr, "%sdebug[<# of symbols on state stack>]\n", YYPREFIX);
+#endif
+
+#if YYBTYACC
+ yyps = yyNewState(0); if (yyps == 0) goto yyenomem;
+ yyps->save = 0;
+#endif /* YYBTYACC */
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = YYEMPTY;
+ yystate = 0;
+
+#if YYPURE
+ memset(&yystack, 0, sizeof(yystack));
+#endif
+
+ if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystack.s_mark = yystack.s_base;
+ yystack.l_mark = yystack.l_base;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base;
+#endif
+ yystate = 0;
+ *yystack.s_mark = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+#if YYBTYACC
+ do {
+ if (yylvp < yylve)
+ {
+ /* we're currently re-reading tokens */
+ yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = *yylpp++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ if (yyps->save)
+ {
+ /* in trial mode; save scanner results for future parse attempts */
+ if (yylvp == yylvlim)
+ { /* Enlarge lexical value queue */
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
+
+ s += YYLVQUEUEGROWTH;
+ if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
+ if ((yylvals = (YYSTYPE *) realloc(yylvals, s * sizeof(YYSTYPE))) == NULL) goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ if ((yylpsns = (YYLTYPE *) realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL) goto yyenomem;
+#endif
+ yylvp = yylve = yylvals + p;
+ yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns + p;
+ yylplim = yylpsns + s;
+#endif
+ yylexp = yylexemes + p;
+ }
+ *yylexp = (short) YYLEX;
+ *yylvp++ = yylval;
+ yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpp++ = yylloc;
+ yylpe++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+ yychar = YYLEX;
+#if YYBTYACC
+ } while (0);
+#endif /* YYBTYACC */
+ if (yychar < 0) yychar = YYEOF;
+ /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, reading token %d (%s)",
+ YYDEBUGSTR, yydepth, yystate, yychar, yys);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, " <%s>", YYSTYPE_TOSTRING(yychar, yylval));
+#endif
+ fputc('\n', stderr);
+ }
+#endif
+ }
+#if YYBTYACC
+
+ /* Do we have a conflict? */
+ if (((yyn = yycindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+ YYINT ctry;
+
+ if (yypath)
+ {
+ YYParseState *save;
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: CONFLICT in state %d: following successful trial parse\n",
+ YYDEBUGSTR, yydepth, yystate);
+#endif
+ /* Switch to the next conflict context */
+ save = yypath;
+ yypath = save->save;
+ save->save = NULL;
+ ctry = save->ctry;
+ if (save->state != yystate) YYABORT;
+ yyFreeState(save);
+
+ }
+ else
+ {
+
+ /* Unresolved conflict - start/continue trial parse */
+ YYParseState *save;
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: CONFLICT in state %d. ", YYDEBUGSTR, yydepth, yystate);
+ if (yyps->save)
+ fputs("ALREADY in conflict, continuing trial parse.\n", stderr);
+ else
+ fputs("Starting trial parse.\n", stderr);
+ }
+#endif
+ save = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+ if (save == NULL) goto yyenomem;
+ save->save = yyps->save;
+ save->state = yystate;
+ save->errflag = yyerrflag;
+ save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ ctry = yytable[yyn];
+ if (yyctable[ctry] == -1)
+ {
+#if YYDEBUG
+ if (yydebug && yychar >= YYEOF)
+ fprintf(stderr, "%s[%d]: backtracking 1 token\n", YYDEBUGSTR, yydepth);
+#endif
+ ctry++;
+ }
+ save->ctry = ctry;
+ if (yyps->save == NULL)
+ {
+ /* If this is a first conflict in the stack, start saving lexemes */
+ if (!yylexemes)
+ {
+ yylexemes = (short *) malloc((YYLVQUEUEGROWTH) * sizeof(short));
+ if (yylexemes == NULL) goto yyenomem;
+ yylvals = (YYSTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYSTYPE));
+ if (yylvals == NULL) goto yyenomem;
+ yylvlim = yylvals + YYLVQUEUEGROWTH;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpsns = (YYLTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYLTYPE));
+ if (yylpsns == NULL) goto yyenomem;
+ yylplim = yylpsns + YYLVQUEUEGROWTH;
+#endif
+ }
+ if (yylvp == yylve)
+ {
+ yylvp = yylve = yylvals;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns;
+#endif
+ yylexp = yylexemes;
+ if (yychar >= YYEOF)
+ {
+ *yylve++ = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpe++ = yylloc;
+#endif
+ *yylexp = (short) yychar;
+ yychar = YYEMPTY;
+ }
+ }
+ }
+ if (yychar >= YYEOF)
+ {
+ yylvp--;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp--;
+#endif
+ yylexp--;
+ yychar = YYEMPTY;
+ }
+ save->lexeme = (int) (yylvp - yylvals);
+ yyps->save = save;
+ }
+ if (yytable[yyn] == ctry)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+ YYDEBUGSTR, yydepth, yystate, yyctable[ctry]);
+#endif
+ if (yychar < 0)
+ {
+ yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp++;
+#endif
+ yylexp++;
+ }
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
+ goto yyoverflow;
+ yystate = yyctable[ctry];
+ *++yystack.s_mark = (short) yystate;
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yylloc;
+#endif
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ else
+ {
+ yyn = yyctable[ctry];
+ goto yyreduce;
+ }
+ } /* End of code dealing with conflicts */
+#endif /* YYBTYACC */
+ if (((yyn = yysindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+ YYDEBUGSTR, yydepth, yystate, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yylloc;
+#endif
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if (((yyn = yyrindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag != 0) goto yyinrecovery;
+#if YYBTYACC
+
+ yynewerrflag = 1;
+ goto yyerrhandler;
+ goto yyerrlab;
+
+yyerrlab:
+ yynewerrflag = 0;
+yyerrhandler:
+ while (yyps->save)
+ {
+ int ctry;
+ YYParseState *save = yyps->save;
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: ERROR in state %d, CONFLICT BACKTRACKING to state %d, %d tokens\n",
+ YYDEBUGSTR, yydepth, yystate, yyps->save->state,
+ (int)(yylvp - yylvals - yyps->save->lexeme));
+#endif
+ /* Memorize most forward-looking error state in case it's really an error. */
+ if (yyerrctx == NULL || yyerrctx->lexeme < yylvp - yylvals)
+ {
+ /* Free old saved error context state */
+ if (yyerrctx) yyFreeState(yyerrctx);
+ /* Create and fill out new saved error context state */
+ yyerrctx = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+ if (yyerrctx == NULL) goto yyenomem;
+ yyerrctx->save = yyps->save;
+ yyerrctx->state = yystate;
+ yyerrctx->errflag = yyerrflag;
+ yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
+ }
+ yylvp = yylvals + save->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + save->lexeme;
+#endif
+ yylexp = yylexemes + save->lexeme;
+ yychar = YYEMPTY;
+ yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ ctry = ++save->ctry;
+ yystate = save->state;
+ /* We tried shift, try reduce now */
+ if ((yyn = yyctable[ctry]) >= 0) goto yyreduce;
+ yyps->save = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+
+ /* Nothing left on the stack -- error */
+ if (!yyps->save)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%sdebug[%d,trial]: trial parse FAILED, entering ERROR mode\n",
+ YYPREFIX, yydepth);
+#endif
+ /* Restore state as it was in the most forward-advanced error */
+ yylvp = yylvals + yyerrctx->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + yyerrctx->lexeme;
+#endif
+ yylexp = yylexemes + yyerrctx->lexeme;
+ yychar = yylexp[-1];
+ yylval = yylvp[-1];
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = yylpp[-1];
+#endif
+ yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yystate = yyerrctx->state;
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ yynewerrflag = 1;
+ }
+ if (yynewerrflag == 0) goto yyinrecovery;
+#endif /* YYBTYACC */
+
+ YYERROR_CALL("syntax error");
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yyerror_loc_range[0] = yylloc; /* lookahead position is error start position */
+#endif
+
+#if !YYBTYACC
+ goto yyerrlab;
+yyerrlab:
+#endif
+ ++yynerrs;
+
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if (((yyn = yysindex[*yystack.s_mark]) != 0) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, error recovery shifting to state %d\n",
+ YYDEBUGSTR, yydepth, *yystack.s_mark, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ /* lookahead position is error end position */
+ yyerror_loc_range[1] = yylloc;
+ YYLLOC_DEFAULT(yyloc, yyerror_loc_range, 2); /* position of error span */
+ *++yystack.p_mark = yyloc;
+#endif
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: error recovery discarding state %d\n",
+ YYDEBUGSTR, yydepth, *yystack.s_mark);
+#endif
+ if (yystack.s_mark <= yystack.s_base) goto yyabort;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ /* the current TOS position is the error start position */
+ yyerror_loc_range[0] = *yystack.p_mark;
+#endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("error: discarding state",
+ yystos[*yystack.s_mark], yystack.l_mark, yystack.p_mark);
+#else
+ YYDESTRUCT_CALL("error: discarding state",
+ yystos[*yystack.s_mark], yystack.l_mark);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
+ --yystack.s_mark;
+ --yystack.l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ --yystack.p_mark;
+#endif
+ }
+ }
+ }
+ else
+ {
+ if (yychar == YYEOF) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, error recovery discarding token %d (%s)\n",
+ YYDEBUGSTR, yydepth, yystate, yychar, yys);
+ }
+#endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("error: discarding token", yychar, &yylval, &yylloc);
+#else
+ YYDESTRUCT_CALL("error: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
+ yychar = YYEMPTY;
+ goto yyloop;
+ }
+
+yyreduce:
+ yym = yylen[yyn];
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: state %d, reducing by rule %d (%s)",
+ YYDEBUGSTR, yydepth, yystate, yyn, yyrule[yyn]);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ if (yym > 0)
+ {
+ int i;
+ fputc('<', stderr);
+ for (i = yym; i > 0; i--)
+ {
+ if (i != yym) fputs(", ", stderr);
+ fputs(YYSTYPE_TOSTRING(yystos[yystack.s_mark[1-i]],
+ yystack.l_mark[1-i]), stderr);
+ }
+ fputc('>', stderr);
+ }
+#endif
+ fputc('\n', stderr);
+ }
+#endif
+ if (yym > 0)
+ yyval = yystack.l_mark[1-yym];
+ else
+ memset(&yyval, 0, sizeof yyval);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+
+ /* Perform position reduction */
+ memset(&yyloc, 0, sizeof(yyloc));
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ {
+ YYLLOC_DEFAULT(yyloc, &yystack.p_mark[1-yym], yym);
+ /* just in case YYERROR is invoked within the action, save
+ the start of the rhs as the error start position */
+ yyerror_loc_range[0] = yystack.p_mark[1-yym];
+ }
+#endif
+
+ switch (yyn)
+ {
+case 1:
+ if (!yytrial)
+#line 62 "btyacc_destroy2.y"
+ { yyval.nlist = yystack.l_mark[-5].nlist; }
+break;
+case 2:
+ if (!yytrial)
+#line 64 "btyacc_destroy2.y"
+ { yyval.nlist = yystack.l_mark[-3].nlist; }
+break;
+case 3:
+ if (!yytrial)
+#line 67 "btyacc_destroy2.y"
+ { yyval.cval = cGLOBAL; }
+break;
+case 4:
+ if (!yytrial)
+#line 68 "btyacc_destroy2.y"
+ { yyval.cval = cLOCAL; }
+break;
+case 5:
+ if (!yytrial)
+#line 71 "btyacc_destroy2.y"
+ { yyval.tval = tREAL; }
+break;
+case 6:
+ if (!yytrial)
+#line 72 "btyacc_destroy2.y"
+ { yyval.tval = tINTEGER; }
+break;
+case 7:
+ if (!yytrial)
+#line 76 "btyacc_destroy2.y"
+ { yyval.nlist->s = mksymbol(yystack.l_mark[-2].tval, yystack.l_mark[-2].cval, yystack.l_mark[0].id);
+ yyval.nlist->next = yystack.l_mark[-1].nlist;
+ }
+break;
+case 8:
+ if (!yytrial)
+#line 80 "btyacc_destroy2.y"
+ { yyval.nlist->s = mksymbol(0, 0, yystack.l_mark[0].id);
+ yyval.nlist->next = NULL;
+ }
+break;
+case 9:
+ if (!yytrial)
+#line 86 "btyacc_destroy2.y"
+ { yyval.nlist = yystack.l_mark[-5].nlist; }
+break;
+#line 1217 "btyacc_destroy2.tab.c"
+ default:
+ break;
+ }
+ yystack.s_mark -= yym;
+ yystate = *yystack.s_mark;
+ yystack.l_mark -= yym;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark -= yym;
+#endif
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[YYFINAL], yyval));
+#endif
+ fprintf(stderr, "shifting from state 0 to final state %d\n", YYFINAL);
+ }
+#endif
+ yystate = YYFINAL;
+ *++yystack.s_mark = YYFINAL;
+ *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yyloc;
+#endif
+ if (yychar < 0)
+ {
+#if YYBTYACC
+ do {
+ if (yylvp < yylve)
+ {
+ /* we're currently re-reading tokens */
+ yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = *yylpp++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ if (yyps->save)
+ {
+ /* in trial mode; save scanner results for future parse attempts */
+ if (yylvp == yylvlim)
+ { /* Enlarge lexical value queue */
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
+
+ s += YYLVQUEUEGROWTH;
+ if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
+ goto yyenomem;
+ if ((yylvals = (YYSTYPE *) realloc(yylvals, s * sizeof(YYSTYPE))) == NULL)
+ goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ if ((yylpsns = (YYLTYPE *) realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL)
+ goto yyenomem;
+#endif
+ yylvp = yylve = yylvals + p;
+ yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns + p;
+ yylplim = yylpsns + s;
+#endif
+ yylexp = yylexemes + p;
+ }
+ *yylexp = (short) YYLEX;
+ *yylvp++ = yylval;
+ yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpp++ = yylloc;
+ yylpe++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+ yychar = YYLEX;
+#if YYBTYACC
+ } while (0);
+#endif /* YYBTYACC */
+ if (yychar < 0) yychar = YYEOF;
+ /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, reading %d (%s)\n",
+ YYDEBUGSTR, yydepth, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == YYEOF) goto yyaccept;
+ goto yyloop;
+ }
+ if (((yyn = yygindex[yym]) != 0) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[yystate], yyval));
+#endif
+ fprintf(stderr, "shifting from state %d to state %d\n", *yystack.s_mark, yystate);
+ }
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ *++yystack.s_mark = (short) yystate;
+ *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yyloc;
+#endif
+ goto yyloop;
+#if YYBTYACC
+
+ /* Reduction declares that this path is valid. Set yypath and do a full parse */
+yyvalid:
+ if (yypath) YYABORT;
+ while (yyps->save)
+ {
+ YYParseState *save = yyps->save;
+ yyps->save = save->save;
+ save->save = yypath;
+ yypath = save;
+ }
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, CONFLICT trial successful, backtracking to state %d, %d tokens\n",
+ YYDEBUGSTR, yydepth, yystate, yypath->state, (int)(yylvp - yylvals - yypath->lexeme));
+#endif
+ if (yyerrctx)
+ {
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ yylvp = yylvals + yypath->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + yypath->lexeme;
+#endif
+ yylexp = yylexemes + yypath->lexeme;
+ yychar = YYEMPTY;
+ yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yystate = yypath->state;
+ goto yyloop;
+#endif /* YYBTYACC */
+
+yyoverflow:
+ YYERROR_CALL("yacc stack overflow");
+#if YYBTYACC
+ goto yyabort_nomem;
+yyenomem:
+ YYERROR_CALL("memory exhausted");
+yyabort_nomem:
+#endif /* YYBTYACC */
+ yyresult = 2;
+ goto yyreturn;
+
+yyabort:
+ yyresult = 1;
+ goto yyreturn;
+
+yyaccept:
+#if YYBTYACC
+ if (yyps->save) goto yyvalid;
+#endif /* YYBTYACC */
+ yyresult = 0;
+
+yyreturn:
+#if defined(YYDESTRUCT_CALL)
+ if (yychar != YYEOF && yychar != YYEMPTY)
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval, &yylloc);
+#else
+ YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+
+ {
+ YYSTYPE *pv;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *pp;
+
+ for (pv = yystack.l_base, pp = yystack.p_base; pv <= yystack.l_mark; ++pv, ++pp)
+ YYDESTRUCT_CALL("cleanup: discarding state",
+ yystos[*(yystack.s_base + (pv - yystack.l_base))], pv, pp);
+#else
+ for (pv = yystack.l_base; pv <= yystack.l_mark; ++pv)
+ YYDESTRUCT_CALL("cleanup: discarding state",
+ yystos[*(yystack.s_base + (pv - yystack.l_base))], pv);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+ }
+#endif /* defined(YYDESTRUCT_CALL) */
+
+#if YYBTYACC
+ if (yyerrctx)
+ {
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ while (yyps)
+ {
+ YYParseState *save = yyps;
+ yyps = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+ }
+ while (yypath)
+ {
+ YYParseState *save = yypath;
+ yypath = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+ }
+#endif /* YYBTYACC */
+ yyfreestack(&yystack);
+ return (yyresult);
+}
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy2.tab.h b/contrib/byacc/test/btyacc/btyacc_destroy2.tab.h
new file mode 100644
index 0000000..6f8c2b0
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy2.tab.h
@@ -0,0 +1,25 @@
+#ifndef _destroy2__defines_h_
+#define _destroy2__defines_h_
+
+#define GLOBAL 257
+#define LOCAL 258
+#define REAL 259
+#define INTEGER 260
+#define NAME 261
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+extern YYSTYPE destroy2_lval;
+
+#endif /* _destroy2__defines_h_ */
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy3.error b/contrib/byacc/test/btyacc/btyacc_destroy3.error
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy3.error
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy3.output b/contrib/byacc/test/btyacc/btyacc_destroy3.output
new file mode 100644
index 0000000..918354c
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy3.output
@@ -0,0 +1,247 @@
+ 0 $accept : declaration $end
+
+ 1 declaration : class type namelist '(' class ',' type ')'
+ 2 | type locnamelist '(' class ')'
+
+ 3 class : GLOBAL
+ 4 | LOCAL
+
+ 5 type : REAL
+ 6 | INTEGER
+
+ 7 namelist : namelist NAME
+ 8 | NAME
+
+ 9 locnamelist : namelist '(' LOCAL ',' type ')'
+
+state 0
+ $accept : . declaration $end (0)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ declaration goto 5
+ class goto 6
+ type goto 7
+
+
+state 1
+ class : GLOBAL . (3)
+
+ . reduce 3
+
+
+state 2
+ class : LOCAL . (4)
+
+ . reduce 4
+
+
+state 3
+ type : REAL . (5)
+
+ . reduce 5
+
+
+state 4
+ type : INTEGER . (6)
+
+ . reduce 6
+
+
+state 5
+ $accept : declaration . $end (0)
+
+ $end accept
+
+
+state 6
+ declaration : class . type namelist '(' class ',' type ')' (1)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 8
+
+
+state 7
+ declaration : type . locnamelist '(' class ')' (2)
+
+ NAME shift 9
+ . error
+
+ locnamelist goto 10
+ namelist goto 11
+
+
+state 8
+ declaration : class type . namelist '(' class ',' type ')' (1)
+
+ NAME shift 9
+ . error
+
+ namelist goto 12
+
+
+state 9
+ namelist : NAME . (8)
+
+ . reduce 8
+
+
+state 10
+ declaration : type locnamelist . '(' class ')' (2)
+
+ '(' shift 13
+ . error
+
+
+state 11
+ namelist : namelist . NAME (7)
+ locnamelist : namelist . '(' LOCAL ',' type ')' (9)
+
+ NAME shift 14
+ '(' shift 15
+ . error
+
+
+state 12
+ declaration : class type namelist . '(' class ',' type ')' (1)
+ namelist : namelist . NAME (7)
+
+ NAME shift 14
+ '(' shift 16
+ . error
+
+
+state 13
+ declaration : type locnamelist '(' . class ')' (2)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ . error
+
+ class goto 17
+
+
+state 14
+ namelist : namelist NAME . (7)
+
+ . reduce 7
+
+
+state 15
+ locnamelist : namelist '(' . LOCAL ',' type ')' (9)
+
+ LOCAL shift 18
+ . error
+
+
+state 16
+ declaration : class type namelist '(' . class ',' type ')' (1)
+
+ GLOBAL shift 1
+ LOCAL shift 2
+ . error
+
+ class goto 19
+
+
+state 17
+ declaration : type locnamelist '(' class . ')' (2)
+
+ ')' shift 20
+ . error
+
+
+state 18
+ locnamelist : namelist '(' LOCAL . ',' type ')' (9)
+
+ ',' shift 21
+ . error
+
+
+state 19
+ declaration : class type namelist '(' class . ',' type ')' (1)
+
+ ',' shift 22
+ . error
+
+
+state 20
+ declaration : type locnamelist '(' class ')' . (2)
+
+ . reduce 2
+
+
+state 21
+ locnamelist : namelist '(' LOCAL ',' . type ')' (9)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 23
+
+
+state 22
+ declaration : class type namelist '(' class ',' . type ')' (1)
+
+ REAL shift 3
+ INTEGER shift 4
+ . error
+
+ type goto 24
+
+
+state 23
+ locnamelist : namelist '(' LOCAL ',' type . ')' (9)
+
+ ')' shift 25
+ . error
+
+
+state 24
+ declaration : class type namelist '(' class ',' type . ')' (1)
+
+ ')' shift 26
+ . error
+
+
+state 25
+ locnamelist : namelist '(' LOCAL ',' type ')' . (9)
+
+ . reduce 9
+
+
+state 26
+ declaration : class type namelist '(' class ',' type ')' . (1)
+
+ . reduce 1
+
+
+10 terminals, 6 nonterminals
+10 grammar rules, 27 states
+
+grammar parser grammar
+symbol# value# symbol
+ 0 0 $end
+ 1 256 error
+ 2 257 GLOBAL
+ 3 258 LOCAL
+ 4 259 REAL
+ 5 260 INTEGER
+ 6 261 NAME
+ 7 40 '('
+ 8 44 ','
+ 9 41 ')'
+ 10 262 $accept
+ 11 263 declaration
+ 12 264 locnamelist
+ 13 265 class
+ 14 266 type
+ 15 267 namelist
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy3.tab.c b/contrib/byacc/test/btyacc/btyacc_destroy3.tab.c
new file mode 100644
index 0000000..9fec701
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy3.tab.c
@@ -0,0 +1,1451 @@
+/* original parser id follows */
+/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
+
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYCHECK "yyyymmdd"
+
+#define YYEMPTY (-1)
+#define yyclearin (yychar = YYEMPTY)
+#define yyerrok (yyerrflag = 0)
+#define YYRECOVERING() (yyerrflag != 0)
+#define YYENOMEM (-2)
+#define YYEOF 0
+#undef YYBTYACC
+#define YYBTYACC 1
+#define YYDEBUGSTR (yytrial ? YYPREFIX "debug(trial)" : YYPREFIX "debug")
+
+#ifndef yyparse
+#define yyparse destroy3_parse
+#endif /* yyparse */
+
+#ifndef yylex
+#define yylex destroy3_lex
+#endif /* yylex */
+
+#ifndef yyerror
+#define yyerror destroy3_error
+#endif /* yyerror */
+
+#ifndef yychar
+#define yychar destroy3_char
+#endif /* yychar */
+
+#ifndef yyval
+#define yyval destroy3_val
+#endif /* yyval */
+
+#ifndef yylval
+#define yylval destroy3_lval
+#endif /* yylval */
+
+#ifndef yydebug
+#define yydebug destroy3_debug
+#endif /* yydebug */
+
+#ifndef yynerrs
+#define yynerrs destroy3_nerrs
+#endif /* yynerrs */
+
+#ifndef yyerrflag
+#define yyerrflag destroy3_errflag
+#endif /* yyerrflag */
+
+#ifndef yylhs
+#define yylhs destroy3_lhs
+#endif /* yylhs */
+
+#ifndef yylen
+#define yylen destroy3_len
+#endif /* yylen */
+
+#ifndef yydefred
+#define yydefred destroy3_defred
+#endif /* yydefred */
+
+#ifndef yystos
+#define yystos destroy3_stos
+#endif /* yystos */
+
+#ifndef yydgoto
+#define yydgoto destroy3_dgoto
+#endif /* yydgoto */
+
+#ifndef yysindex
+#define yysindex destroy3_sindex
+#endif /* yysindex */
+
+#ifndef yyrindex
+#define yyrindex destroy3_rindex
+#endif /* yyrindex */
+
+#ifndef yygindex
+#define yygindex destroy3_gindex
+#endif /* yygindex */
+
+#ifndef yytable
+#define yytable destroy3_table
+#endif /* yytable */
+
+#ifndef yycheck
+#define yycheck destroy3_check
+#endif /* yycheck */
+
+#ifndef yyname
+#define yyname destroy3_name
+#endif /* yyname */
+
+#ifndef yyrule
+#define yyrule destroy3_rule
+#endif /* yyrule */
+
+#if YYBTYACC
+
+#ifndef yycindex
+#define yycindex destroy3_cindex
+#endif /* yycindex */
+
+#ifndef yyctable
+#define yyctable destroy3_ctable
+#endif /* yyctable */
+
+#endif /* YYBTYACC */
+
+#define YYPREFIX "destroy3_"
+
+#define YYPURE 0
+
+#line 7 "btyacc_destroy3.y"
+#include <stdlib.h>
+
+typedef enum {cGLOBAL, cLOCAL} class;
+typedef enum {tREAL, tINTEGER} type;
+typedef char * name;
+
+struct symbol { class c; type t; name id; };
+typedef struct symbol symbol;
+
+struct namelist { symbol *s; struct namelist *next; };
+typedef struct namelist namelist;
+
+struct parser_param {
+ int *rtrn;
+ symbol ss;
+};
+
+extern symbol *mksymbol(type t, class c, name id);
+
+#ifdef YYBISON
+#define YYLEX_DECL() yylex(void)
+#define YYERROR_DECL() yyerror(const char *s)
+#endif
+#line 53 "btyacc_destroy3.y"
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+#line 160 "btyacc_destroy3.tab.c"
+
+/* compatibility with bison */
+#ifdef YYPARSE_PARAM
+/* compatibility with FreeBSD */
+# ifdef YYPARSE_PARAM_TYPE
+# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
+# else
+# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
+# endif
+#else
+# define YYPARSE_DECL() yyparse(struct parser_param *param, int flag)
+#endif
+
+/* Parameters sent to lex. */
+#ifdef YYLEX_PARAM
+# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
+# define YYLEX yylex(YYLEX_PARAM)
+#else
+# define YYLEX_DECL() yylex(void)
+# define YYLEX yylex()
+#endif
+
+/* Parameters sent to yyerror. */
+#ifndef YYERROR_DECL
+#define YYERROR_DECL() yyerror(struct parser_param *param, int flag, const char *s)
+#endif
+#ifndef YYERROR_CALL
+#define YYERROR_CALL(msg) yyerror(param, flag, msg)
+#endif
+
+#ifndef YYDESTRUCT_DECL
+#define YYDESTRUCT_DECL() yydestruct(const char *msg, int psymb, YYSTYPE *val, struct parser_param *param, int flag)
+#endif
+#ifndef YYDESTRUCT_CALL
+#define YYDESTRUCT_CALL(msg, psymb, val) yydestruct(msg, psymb, val, param, flag)
+#endif
+
+extern int YYPARSE_DECL();
+
+#define GLOBAL 257
+#define LOCAL 258
+#define REAL 259
+#define INTEGER 260
+#define NAME 261
+#define YYERRCODE 256
+typedef short YYINT;
+static const YYINT destroy3_lhs[] = { -1,
+ 0, 0, 2, 2, 3, 3, 4, 4, 1,
+};
+static const YYINT destroy3_len[] = { 2,
+ 8, 5, 1, 1, 1, 1, 2, 1, 6,
+};
+static const YYINT destroy3_defred[] = { 0,
+ 3, 4, 5, 6, 0, 0, 0, 0, 8, 0,
+ 0, 0, 0, 7, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 9, 1,
+};
+static const YYINT destroy3_stos[] = { 0,
+ 257, 258, 259, 260, 263, 265, 266, 266, 261, 264,
+ 267, 267, 40, 261, 40, 40, 265, 258, 265, 41,
+ 44, 44, 266, 266, 41, 41,
+};
+static const YYINT destroy3_dgoto[] = { 5,
+ 10, 6, 7, 11,
+};
+static const YYINT destroy3_sindex[] = { -254,
+ 0, 0, 0, 0, 0, -251, -248, -248, 0, -26,
+ -40, -39, -246, 0, -243, -246, -25, -24, -23, 0,
+ -251, -251, -22, -19, 0, 0,
+};
+static const YYINT destroy3_rindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+};
+#if YYBTYACC
+static const YYINT destroy3_cindex[] = { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+};
+#endif
+static const YYINT destroy3_gindex[] = { 0,
+ 0, -6, -4, 15,
+};
+#define YYTABLESIZE 222
+static const YYINT destroy3_table[] = { 15,
+ 16, 8, 1, 2, 3, 4, 17, 3, 4, 19,
+ 1, 2, 9, 13, 18, 20, 23, 24, 25, 21,
+ 22, 26, 12, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 14, 14,
+};
+static const YYINT destroy3_check[] = { 40,
+ 40, 6, 257, 258, 259, 260, 13, 259, 260, 16,
+ 257, 258, 261, 40, 258, 41, 21, 22, 41, 44,
+ 44, 41, 8, -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,
+ 261, 261,
+};
+#if YYBTYACC
+static const YYINT destroy3_ctable[] = { -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,
+};
+#endif
+#define YYFINAL 5
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 261
+#define YYUNDFTOKEN 268
+#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
+#if YYDEBUG
+static const char *const destroy3_name[] = {
+
+"$end",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"error","GLOBAL","LOCAL",
+"REAL","INTEGER","NAME","$accept","declaration","locnamelist","class","type",
+"namelist","illegal-symbol",
+};
+static const char *const destroy3_rule[] = {
+"$accept : declaration",
+"declaration : class type namelist '(' class ',' type ')'",
+"declaration : type locnamelist '(' class ')'",
+"class : GLOBAL",
+"class : LOCAL",
+"type : REAL",
+"type : INTEGER",
+"namelist : namelist NAME",
+"namelist : NAME",
+"locnamelist : namelist '(' LOCAL ',' type ')'",
+
+};
+#endif
+
+int yydebug;
+int yynerrs;
+
+int yyerrflag;
+int yychar;
+YYSTYPE yyval;
+YYSTYPE yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+YYLTYPE yyloc; /* position returned by actions */
+YYLTYPE yylloc; /* position from the lexer */
+#endif
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+#ifndef YYLLOC_DEFAULT
+#define YYLLOC_DEFAULT(loc, rhs, n) \
+do \
+{ \
+ if (n == 0) \
+ { \
+ (loc).first_line = ((rhs)[-1]).last_line; \
+ (loc).first_column = ((rhs)[-1]).last_column; \
+ (loc).last_line = ((rhs)[-1]).last_line; \
+ (loc).last_column = ((rhs)[-1]).last_column; \
+ } \
+ else \
+ { \
+ (loc).first_line = ((rhs)[ 0 ]).first_line; \
+ (loc).first_column = ((rhs)[ 0 ]).first_column; \
+ (loc).last_line = ((rhs)[n-1]).last_line; \
+ (loc).last_column = ((rhs)[n-1]).last_column; \
+ } \
+} while (0)
+#endif /* YYLLOC_DEFAULT */
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#if YYBTYACC
+
+#ifndef YYLVQUEUEGROWTH
+#define YYLVQUEUEGROWTH 32
+#endif
+#endif /* YYBTYACC */
+
+/* define the initial stack-sizes */
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+
+#ifndef YYINITSTACKSIZE
+#define YYINITSTACKSIZE 200
+#endif
+
+typedef struct {
+ unsigned stacksize;
+ short *s_base;
+ short *s_mark;
+ short *s_last;
+ YYSTYPE *l_base;
+ YYSTYPE *l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *p_base;
+ YYLTYPE *p_mark;
+#endif
+} YYSTACKDATA;
+#if YYBTYACC
+
+struct YYParseState_s
+{
+ struct YYParseState_s *save; /* Previously saved parser state */
+ YYSTACKDATA yystack; /* saved parser stack */
+ int state; /* saved parser state */
+ int errflag; /* saved error recovery status */
+ int lexeme; /* saved index of the conflict lexeme in the lexical queue */
+ YYINT ctry; /* saved index in yyctable[] for this conflict */
+};
+typedef struct YYParseState_s YYParseState;
+#endif /* YYBTYACC */
+/* variables for the parser stack */
+static YYSTACKDATA yystack;
+#if YYBTYACC
+
+/* Current parser state */
+static YYParseState *yyps = 0;
+
+/* yypath != NULL: do the full parse, starting at *yypath parser state. */
+static YYParseState *yypath = 0;
+
+/* Base of the lexical value queue */
+static YYSTYPE *yylvals = 0;
+
+/* Current position at lexical value queue */
+static YYSTYPE *yylvp = 0;
+
+/* End position of lexical value queue */
+static YYSTYPE *yylve = 0;
+
+/* The last allocated position at the lexical value queue */
+static YYSTYPE *yylvlim = 0;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+/* Base of the lexical position queue */
+static YYLTYPE *yylpsns = 0;
+
+/* Current position at lexical position queue */
+static YYLTYPE *yylpp = 0;
+
+/* End position of lexical position queue */
+static YYLTYPE *yylpe = 0;
+
+/* The last allocated position at the lexical position queue */
+static YYLTYPE *yylplim = 0;
+#endif
+
+/* Current position at lexical token queue */
+static short *yylexp = 0;
+
+static short *yylexemes = 0;
+#endif /* YYBTYACC */
+#line 92 "btyacc_destroy3.y"
+
+extern int YYLEX_DECL();
+extern void YYERROR_DECL();
+#line 487 "btyacc_destroy3.tab.c"
+
+/* Release memory associated with symbol. */
+#if ! defined YYDESTRUCT_IS_DECLARED
+static void
+YYDESTRUCT_DECL()
+{
+ switch (psymb)
+ {
+ case 263:
+#line 44 "btyacc_destroy3.y"
+ {
+ namelist *p = (*val).nlist;
+ while (p != NULL)
+ { namelist *pp = p;
+ p = p->next;
+ free(pp->s); free(pp);
+ }
+ }
+ break;
+#line 507 "btyacc_destroy3.tab.c"
+ }
+}
+#define YYDESTRUCT_IS_DECLARED 1
+#endif
+
+/* For use in generated program */
+#define yydepth (int)(yystack.s_mark - yystack.s_base)
+#if YYBTYACC
+#define yytrial (yyps->save)
+#endif /* YYBTYACC */
+
+#if YYDEBUG
+#include <stdio.h> /* needed for printf */
+#endif
+
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
+
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+static int yygrowstack(YYSTACKDATA *data)
+{
+ int i;
+ unsigned newsize;
+ short *newss;
+ YYSTYPE *newvs;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *newps;
+#endif
+
+ if ((newsize = data->stacksize) == 0)
+ newsize = YYINITSTACKSIZE;
+ else if (newsize >= YYMAXDEPTH)
+ return YYENOMEM;
+ else if ((newsize *= 2) > YYMAXDEPTH)
+ newsize = YYMAXDEPTH;
+
+ i = (int) (data->s_mark - data->s_base);
+ newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
+ if (newss == 0)
+ return YYENOMEM;
+
+ data->s_base = newss;
+ data->s_mark = newss + i;
+
+ newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
+ if (newvs == 0)
+ return YYENOMEM;
+
+ data->l_base = newvs;
+ data->l_mark = newvs + i;
+
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ newps = (YYLTYPE *)realloc(data->p_base, newsize * sizeof(*newps));
+ if (newps == 0)
+ return YYENOMEM;
+
+ data->p_base = newps;
+ data->p_mark = newps + i;
+#endif
+
+ data->stacksize = newsize;
+ data->s_last = data->s_base + newsize - 1;
+
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%sdebug: stack size increased to %d\n", YYPREFIX, newsize);
+#endif
+ return 0;
+}
+
+#if YYPURE || defined(YY_NO_LEAKS)
+static void yyfreestack(YYSTACKDATA *data)
+{
+ free(data->s_base);
+ free(data->l_base);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ free(data->p_base);
+#endif
+ memset(data, 0, sizeof(*data));
+}
+#else
+#define yyfreestack(data) /* nothing */
+#endif /* YYPURE || defined(YY_NO_LEAKS) */
+#if YYBTYACC
+
+static YYParseState *
+yyNewState(unsigned size)
+{
+ YYParseState *p = (YYParseState *) malloc(sizeof(YYParseState));
+ if (p == NULL) return NULL;
+
+ p->yystack.stacksize = size;
+ if (size == 0)
+ {
+ p->yystack.s_base = NULL;
+ p->yystack.l_base = NULL;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ p->yystack.p_base = NULL;
+#endif
+ return p;
+ }
+ p->yystack.s_base = (short *) malloc(size * sizeof(short));
+ if (p->yystack.s_base == NULL) return NULL;
+ p->yystack.l_base = (YYSTYPE *) malloc(size * sizeof(YYSTYPE));
+ if (p->yystack.l_base == NULL) return NULL;
+ memset(p->yystack.l_base, 0, size * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ p->yystack.p_base = (YYLTYPE *) malloc(size * sizeof(YYLTYPE));
+ if (p->yystack.p_base == NULL) return NULL;
+ memset(p->yystack.p_base, 0, size * sizeof(YYLTYPE));
+#endif
+
+ return p;
+}
+
+static void
+yyFreeState(YYParseState *p)
+{
+ yyfreestack(&p->yystack);
+ free(p);
+}
+#endif /* YYBTYACC */
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+#if YYBTYACC
+#define YYVALID do { if (yyps->save) goto yyvalid; } while(0)
+#define YYVALID_NESTED do { if (yyps->save && \
+ yyps->save->save == 0) goto yyvalid; } while(0)
+#endif /* YYBTYACC */
+
+int
+YYPARSE_DECL()
+{
+ int yym, yyn, yystate, yyresult;
+#if YYBTYACC
+ int yynewerrflag;
+ YYParseState *yyerrctx = NULL;
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE yyerror_loc_range[2]; /* position of error start & end */
+#endif
+#if YYDEBUG
+ const char *yys;
+
+ if ((yys = getenv("YYDEBUG")) != 0)
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+ if (yydebug)
+ fprintf(stderr, "%sdebug[<# of symbols on state stack>]\n", YYPREFIX);
+#endif
+
+#if YYBTYACC
+ yyps = yyNewState(0); if (yyps == 0) goto yyenomem;
+ yyps->save = 0;
+#endif /* YYBTYACC */
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = YYEMPTY;
+ yystate = 0;
+
+#if YYPURE
+ memset(&yystack, 0, sizeof(yystack));
+#endif
+
+ if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystack.s_mark = yystack.s_base;
+ yystack.l_mark = yystack.l_base;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base;
+#endif
+ yystate = 0;
+ *yystack.s_mark = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+#if YYBTYACC
+ do {
+ if (yylvp < yylve)
+ {
+ /* we're currently re-reading tokens */
+ yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = *yylpp++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ if (yyps->save)
+ {
+ /* in trial mode; save scanner results for future parse attempts */
+ if (yylvp == yylvlim)
+ { /* Enlarge lexical value queue */
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
+
+ s += YYLVQUEUEGROWTH;
+ if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
+ if ((yylvals = (YYSTYPE *) realloc(yylvals, s * sizeof(YYSTYPE))) == NULL) goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ if ((yylpsns = (YYLTYPE *) realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL) goto yyenomem;
+#endif
+ yylvp = yylve = yylvals + p;
+ yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns + p;
+ yylplim = yylpsns + s;
+#endif
+ yylexp = yylexemes + p;
+ }
+ *yylexp = (short) YYLEX;
+ *yylvp++ = yylval;
+ yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpp++ = yylloc;
+ yylpe++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+ yychar = YYLEX;
+#if YYBTYACC
+ } while (0);
+#endif /* YYBTYACC */
+ if (yychar < 0) yychar = YYEOF;
+ /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, reading token %d (%s)",
+ YYDEBUGSTR, yydepth, yystate, yychar, yys);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, " <%s>", YYSTYPE_TOSTRING(yychar, yylval));
+#endif
+ fputc('\n', stderr);
+ }
+#endif
+ }
+#if YYBTYACC
+
+ /* Do we have a conflict? */
+ if (((yyn = yycindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+ YYINT ctry;
+
+ if (yypath)
+ {
+ YYParseState *save;
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: CONFLICT in state %d: following successful trial parse\n",
+ YYDEBUGSTR, yydepth, yystate);
+#endif
+ /* Switch to the next conflict context */
+ save = yypath;
+ yypath = save->save;
+ save->save = NULL;
+ ctry = save->ctry;
+ if (save->state != yystate) YYABORT;
+ yyFreeState(save);
+
+ }
+ else
+ {
+
+ /* Unresolved conflict - start/continue trial parse */
+ YYParseState *save;
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: CONFLICT in state %d. ", YYDEBUGSTR, yydepth, yystate);
+ if (yyps->save)
+ fputs("ALREADY in conflict, continuing trial parse.\n", stderr);
+ else
+ fputs("Starting trial parse.\n", stderr);
+ }
+#endif
+ save = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+ if (save == NULL) goto yyenomem;
+ save->save = yyps->save;
+ save->state = yystate;
+ save->errflag = yyerrflag;
+ save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ ctry = yytable[yyn];
+ if (yyctable[ctry] == -1)
+ {
+#if YYDEBUG
+ if (yydebug && yychar >= YYEOF)
+ fprintf(stderr, "%s[%d]: backtracking 1 token\n", YYDEBUGSTR, yydepth);
+#endif
+ ctry++;
+ }
+ save->ctry = ctry;
+ if (yyps->save == NULL)
+ {
+ /* If this is a first conflict in the stack, start saving lexemes */
+ if (!yylexemes)
+ {
+ yylexemes = (short *) malloc((YYLVQUEUEGROWTH) * sizeof(short));
+ if (yylexemes == NULL) goto yyenomem;
+ yylvals = (YYSTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYSTYPE));
+ if (yylvals == NULL) goto yyenomem;
+ yylvlim = yylvals + YYLVQUEUEGROWTH;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpsns = (YYLTYPE *) malloc((YYLVQUEUEGROWTH) * sizeof(YYLTYPE));
+ if (yylpsns == NULL) goto yyenomem;
+ yylplim = yylpsns + YYLVQUEUEGROWTH;
+#endif
+ }
+ if (yylvp == yylve)
+ {
+ yylvp = yylve = yylvals;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns;
+#endif
+ yylexp = yylexemes;
+ if (yychar >= YYEOF)
+ {
+ *yylve++ = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpe++ = yylloc;
+#endif
+ *yylexp = (short) yychar;
+ yychar = YYEMPTY;
+ }
+ }
+ }
+ if (yychar >= YYEOF)
+ {
+ yylvp--;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp--;
+#endif
+ yylexp--;
+ yychar = YYEMPTY;
+ }
+ save->lexeme = (int) (yylvp - yylvals);
+ yyps->save = save;
+ }
+ if (yytable[yyn] == ctry)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+ YYDEBUGSTR, yydepth, yystate, yyctable[ctry]);
+#endif
+ if (yychar < 0)
+ {
+ yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp++;
+#endif
+ yylexp++;
+ }
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM)
+ goto yyoverflow;
+ yystate = yyctable[ctry];
+ *++yystack.s_mark = (short) yystate;
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yylloc;
+#endif
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ else
+ {
+ yyn = yyctable[ctry];
+ goto yyreduce;
+ }
+ } /* End of code dealing with conflicts */
+#endif /* YYBTYACC */
+ if (((yyn = yysindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, shifting to state %d\n",
+ YYDEBUGSTR, yydepth, yystate, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yylloc;
+#endif
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if (((yyn = yyrindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag != 0) goto yyinrecovery;
+#if YYBTYACC
+
+ yynewerrflag = 1;
+ goto yyerrhandler;
+ goto yyerrlab;
+
+yyerrlab:
+ yynewerrflag = 0;
+yyerrhandler:
+ while (yyps->save)
+ {
+ int ctry;
+ YYParseState *save = yyps->save;
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: ERROR in state %d, CONFLICT BACKTRACKING to state %d, %d tokens\n",
+ YYDEBUGSTR, yydepth, yystate, yyps->save->state,
+ (int)(yylvp - yylvals - yyps->save->lexeme));
+#endif
+ /* Memorize most forward-looking error state in case it's really an error. */
+ if (yyerrctx == NULL || yyerrctx->lexeme < yylvp - yylvals)
+ {
+ /* Free old saved error context state */
+ if (yyerrctx) yyFreeState(yyerrctx);
+ /* Create and fill out new saved error context state */
+ yyerrctx = yyNewState((unsigned)(yystack.s_mark - yystack.s_base + 1));
+ if (yyerrctx == NULL) goto yyenomem;
+ yyerrctx->save = yyps->save;
+ yyerrctx->state = yystate;
+ yyerrctx->errflag = yyerrflag;
+ yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
+ }
+ yylvp = yylvals + save->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + save->lexeme;
+#endif
+ yylexp = yylexemes + save->lexeme;
+ yychar = YYEMPTY;
+ yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ ctry = ++save->ctry;
+ yystate = save->state;
+ /* We tried shift, try reduce now */
+ if ((yyn = yyctable[ctry]) >= 0) goto yyreduce;
+ yyps->save = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+
+ /* Nothing left on the stack -- error */
+ if (!yyps->save)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%sdebug[%d,trial]: trial parse FAILED, entering ERROR mode\n",
+ YYPREFIX, yydepth);
+#endif
+ /* Restore state as it was in the most forward-advanced error */
+ yylvp = yylvals + yyerrctx->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + yyerrctx->lexeme;
+#endif
+ yylexp = yylexemes + yyerrctx->lexeme;
+ yychar = yylexp[-1];
+ yylval = yylvp[-1];
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = yylpp[-1];
+#endif
+ yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yystate = yyerrctx->state;
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ yynewerrflag = 1;
+ }
+ if (yynewerrflag == 0) goto yyinrecovery;
+#endif /* YYBTYACC */
+
+ YYERROR_CALL("syntax error");
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yyerror_loc_range[0] = yylloc; /* lookahead position is error start position */
+#endif
+
+#if !YYBTYACC
+ goto yyerrlab;
+yyerrlab:
+#endif
+ ++yynerrs;
+
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if (((yyn = yysindex[*yystack.s_mark]) != 0) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, error recovery shifting to state %d\n",
+ YYDEBUGSTR, yydepth, *yystack.s_mark, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ /* lookahead position is error end position */
+ yyerror_loc_range[1] = yylloc;
+ YYLLOC_DEFAULT(yyloc, yyerror_loc_range, 2); /* position of error span */
+ *++yystack.p_mark = yyloc;
+#endif
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: error recovery discarding state %d\n",
+ YYDEBUGSTR, yydepth, *yystack.s_mark);
+#endif
+ if (yystack.s_mark <= yystack.s_base) goto yyabort;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ /* the current TOS position is the error start position */
+ yyerror_loc_range[0] = *yystack.p_mark;
+#endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("error: discarding state",
+ yystos[*yystack.s_mark], yystack.l_mark, yystack.p_mark);
+#else
+ YYDESTRUCT_CALL("error: discarding state",
+ yystos[*yystack.s_mark], yystack.l_mark);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
+ --yystack.s_mark;
+ --yystack.l_mark;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ --yystack.p_mark;
+#endif
+ }
+ }
+ }
+ else
+ {
+ if (yychar == YYEOF) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, error recovery discarding token %d (%s)\n",
+ YYDEBUGSTR, yydepth, yystate, yychar, yys);
+ }
+#endif
+#if defined(YYDESTRUCT_CALL)
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("error: discarding token", yychar, &yylval, &yylloc);
+#else
+ YYDESTRUCT_CALL("error: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+#endif /* defined(YYDESTRUCT_CALL) */
+ yychar = YYEMPTY;
+ goto yyloop;
+ }
+
+yyreduce:
+ yym = yylen[yyn];
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: state %d, reducing by rule %d (%s)",
+ YYDEBUGSTR, yydepth, yystate, yyn, yyrule[yyn]);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ if (yym > 0)
+ {
+ int i;
+ fputc('<', stderr);
+ for (i = yym; i > 0; i--)
+ {
+ if (i != yym) fputs(", ", stderr);
+ fputs(YYSTYPE_TOSTRING(yystos[yystack.s_mark[1-i]],
+ yystack.l_mark[1-i]), stderr);
+ }
+ fputc('>', stderr);
+ }
+#endif
+ fputc('\n', stderr);
+ }
+#endif
+ if (yym > 0)
+ yyval = yystack.l_mark[1-yym];
+ else
+ memset(&yyval, 0, sizeof yyval);
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+
+ /* Perform position reduction */
+ memset(&yyloc, 0, sizeof(yyloc));
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ {
+ YYLLOC_DEFAULT(yyloc, &yystack.p_mark[1-yym], yym);
+ /* just in case YYERROR is invoked within the action, save
+ the start of the rhs as the error start position */
+ yyerror_loc_range[0] = yystack.p_mark[1-yym];
+ }
+#endif
+
+ switch (yyn)
+ {
+case 1:
+ if (!yytrial)
+#line 65 "btyacc_destroy3.y"
+ { yyval.nlist = yystack.l_mark[-5].nlist; }
+break;
+case 2:
+ if (!yytrial)
+#line 67 "btyacc_destroy3.y"
+ { yyval.nlist = yystack.l_mark[-3].nlist; }
+break;
+case 3:
+ if (!yytrial)
+#line 70 "btyacc_destroy3.y"
+ { yyval.cval = cGLOBAL; }
+break;
+case 4:
+ if (!yytrial)
+#line 71 "btyacc_destroy3.y"
+ { yyval.cval = cLOCAL; }
+break;
+case 5:
+ if (!yytrial)
+#line 74 "btyacc_destroy3.y"
+ { yyval.tval = tREAL; }
+break;
+case 6:
+ if (!yytrial)
+#line 75 "btyacc_destroy3.y"
+ { yyval.tval = tINTEGER; }
+break;
+case 7:
+ if (!yytrial)
+#line 79 "btyacc_destroy3.y"
+ { yyval.nlist->s = mksymbol(yystack.l_mark[-2].tval, yystack.l_mark[-2].cval, yystack.l_mark[0].id);
+ yyval.nlist->next = yystack.l_mark[-1].nlist;
+ }
+break;
+case 8:
+ if (!yytrial)
+#line 83 "btyacc_destroy3.y"
+ { yyval.nlist->s = mksymbol(0, 0, yystack.l_mark[0].id);
+ yyval.nlist->next = NULL;
+ }
+break;
+case 9:
+ if (!yytrial)
+#line 89 "btyacc_destroy3.y"
+ { yyval.nlist = yystack.l_mark[-5].nlist; }
+break;
+#line 1217 "btyacc_destroy3.tab.c"
+ default:
+ break;
+ }
+ yystack.s_mark -= yym;
+ yystate = *yystack.s_mark;
+ yystack.l_mark -= yym;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark -= yym;
+#endif
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[YYFINAL], yyval));
+#endif
+ fprintf(stderr, "shifting from state 0 to final state %d\n", YYFINAL);
+ }
+#endif
+ yystate = YYFINAL;
+ *++yystack.s_mark = YYFINAL;
+ *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yyloc;
+#endif
+ if (yychar < 0)
+ {
+#if YYBTYACC
+ do {
+ if (yylvp < yylve)
+ {
+ /* we're currently re-reading tokens */
+ yylval = *yylvp++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylloc = *yylpp++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ if (yyps->save)
+ {
+ /* in trial mode; save scanner results for future parse attempts */
+ if (yylvp == yylvlim)
+ { /* Enlarge lexical value queue */
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
+
+ s += YYLVQUEUEGROWTH;
+ if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
+ goto yyenomem;
+ if ((yylvals = (YYSTYPE *) realloc(yylvals, s * sizeof(YYSTYPE))) == NULL)
+ goto yyenomem;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ if ((yylpsns = (YYLTYPE *) realloc(yylpsns, s * sizeof(YYLTYPE))) == NULL)
+ goto yyenomem;
+#endif
+ yylvp = yylve = yylvals + p;
+ yylvlim = yylvals + s;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpe = yylpsns + p;
+ yylplim = yylpsns + s;
+#endif
+ yylexp = yylexemes + p;
+ }
+ *yylexp = (short) YYLEX;
+ *yylvp++ = yylval;
+ yylve++;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *yylpp++ = yylloc;
+ yylpe++;
+#endif
+ yychar = *yylexp++;
+ break;
+ }
+ /* normal operation, no conflict encountered */
+#endif /* YYBTYACC */
+ yychar = YYLEX;
+#if YYBTYACC
+ } while (0);
+#endif /* YYBTYACC */
+ if (yychar < 0) yychar = YYEOF;
+ /* if ((yychar = YYLEX) < 0) yychar = YYEOF; */
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = yyname[YYTRANSLATE(yychar)];
+ fprintf(stderr, "%s[%d]: state %d, reading %d (%s)\n",
+ YYDEBUGSTR, yydepth, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == YYEOF) goto yyaccept;
+ goto yyloop;
+ }
+ if (((yyn = yygindex[yym]) != 0) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ {
+ fprintf(stderr, "%s[%d]: after reduction, ", YYDEBUGSTR, yydepth);
+#ifdef YYSTYPE_TOSTRING
+#if YYBTYACC
+ if (!yytrial)
+#endif /* YYBTYACC */
+ fprintf(stderr, "result is <%s>, ", YYSTYPE_TOSTRING(yystos[yystate], yyval));
+#endif
+ fprintf(stderr, "shifting from state %d to state %d\n", *yystack.s_mark, yystate);
+ }
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ *++yystack.s_mark = (short) yystate;
+ *++yystack.l_mark = yyval;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ *++yystack.p_mark = yyloc;
+#endif
+ goto yyloop;
+#if YYBTYACC
+
+ /* Reduction declares that this path is valid. Set yypath and do a full parse */
+yyvalid:
+ if (yypath) YYABORT;
+ while (yyps->save)
+ {
+ YYParseState *save = yyps->save;
+ yyps->save = save->save;
+ save->save = yypath;
+ yypath = save;
+ }
+#if YYDEBUG
+ if (yydebug)
+ fprintf(stderr, "%s[%d]: state %d, CONFLICT trial successful, backtracking to state %d, %d tokens\n",
+ YYDEBUGSTR, yydepth, yystate, yypath->state, (int)(yylvp - yylvals - yypath->lexeme));
+#endif
+ if (yyerrctx)
+ {
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ yylvp = yylvals + yypath->lexeme;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yylpp = yylpsns + yypath->lexeme;
+#endif
+ yylexp = yylexemes + yypath->lexeme;
+ yychar = YYEMPTY;
+ yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+#endif
+ yystate = yypath->state;
+ goto yyloop;
+#endif /* YYBTYACC */
+
+yyoverflow:
+ YYERROR_CALL("yacc stack overflow");
+#if YYBTYACC
+ goto yyabort_nomem;
+yyenomem:
+ YYERROR_CALL("memory exhausted");
+yyabort_nomem:
+#endif /* YYBTYACC */
+ yyresult = 2;
+ goto yyreturn;
+
+yyabort:
+ yyresult = 1;
+ goto yyreturn;
+
+yyaccept:
+#if YYBTYACC
+ if (yyps->save) goto yyvalid;
+#endif /* YYBTYACC */
+ yyresult = 0;
+
+yyreturn:
+#if defined(YYDESTRUCT_CALL)
+ if (yychar != YYEOF && yychar != YYEMPTY)
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval, &yylloc);
+#else
+ YYDESTRUCT_CALL("cleanup: discarding token", yychar, &yylval);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+
+ {
+ YYSTYPE *pv;
+#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
+ YYLTYPE *pp;
+
+ for (pv = yystack.l_base, pp = yystack.p_base; pv <= yystack.l_mark; ++pv, ++pp)
+ YYDESTRUCT_CALL("cleanup: discarding state",
+ yystos[*(yystack.s_base + (pv - yystack.l_base))], pv, pp);
+#else
+ for (pv = yystack.l_base; pv <= yystack.l_mark; ++pv)
+ YYDESTRUCT_CALL("cleanup: discarding state",
+ yystos[*(yystack.s_base + (pv - yystack.l_base))], pv);
+#endif /* defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED) */
+ }
+#endif /* defined(YYDESTRUCT_CALL) */
+
+#if YYBTYACC
+ if (yyerrctx)
+ {
+ yyFreeState(yyerrctx);
+ yyerrctx = NULL;
+ }
+ while (yyps)
+ {
+ YYParseState *save = yyps;
+ yyps = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+ }
+ while (yypath)
+ {
+ YYParseState *save = yypath;
+ yypath = save->save;
+ save->save = NULL;
+ yyFreeState(save);
+ }
+#endif /* YYBTYACC */
+ yyfreestack(&yystack);
+ return (yyresult);
+}
diff --git a/contrib/byacc/test/btyacc/btyacc_destroy3.tab.h b/contrib/byacc/test/btyacc/btyacc_destroy3.tab.h
new file mode 100644
index 0000000..1ef7d6b
--- /dev/null
+++ b/contrib/byacc/test/btyacc/btyacc_destroy3.tab.h
@@ -0,0 +1,25 @@
+#ifndef _destroy3__defines_h_
+#define _destroy3__defines_h_
+
+#define GLOBAL 257
+#define LOCAL 258
+#define REAL 259
+#define INTEGER 260
+#define NAME 261
+#ifdef YYSTYPE
+#undef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+#endif
+#ifndef YYSTYPE_IS_DECLARED
+#define YYSTYPE_IS_DECLARED 1
+typedef union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+} YYSTYPE;
+#endif /* !YYSTYPE_IS_DECLARED */
+extern YYSTYPE destroy3_lval;
+
+#endif /* _destroy3__defines_h_ */
diff --git a/contrib/byacc/test/btyacc/calc.tab.c b/contrib/byacc/test/btyacc/calc.tab.c
index ceb2ed1..d0df560 100644
--- a/contrib/byacc/test/btyacc/calc.tab.c
+++ b/contrib/byacc/test/btyacc/calc.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -266,6 +266,32 @@ static const YYINT calc_check[] = { 40,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 256, 257, 258, 257, 258,
};
+#if YYBTYACC
+static const YYINT calc_ctable[] = { -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,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -476,7 +502,7 @@ yylex(void)
}
return( c );
}
-#line 480 "calc.tab.c"
+#line 506 "calc.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -485,11 +511,11 @@ yylex(void)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -673,8 +699,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -770,12 +796,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -830,7 +856,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -924,14 +950,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -940,12 +966,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -975,12 +1001,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1193,7 +1219,7 @@ case 18:
#line 63 "calc.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1197 "calc.tab.c"
+#line 1223 "calc.tab.c"
default:
break;
}
@@ -1244,8 +1270,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1348,12 +1374,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/calc1.tab.c b/contrib/byacc/test/btyacc/calc1.tab.c
index fd86a90..78fb73f 100644
--- a/contrib/byacc/test/btyacc/calc1.tab.c
+++ b/contrib/byacc/test/btyacc/calc1.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -310,6 +310,33 @@ static const YYINT calc1_check[] = { 40,
-1, -1, -1, -1, -1, 256, 257, 258, 259, 257,
258, 259, 257, -1, 259,
};
+#if YYBTYACC
+static const YYINT calc1_ctable[] = { -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,
+};
+#endif
#define YYFINAL 7
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -619,7 +646,7 @@ vdiv(double a, double b, INTERVAL v)
{
return (hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo));
}
-#line 623 "calc1.tab.c"
+#line 650 "calc1.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -628,11 +655,11 @@ vdiv(double a, double b, INTERVAL v)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -816,8 +843,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -913,12 +940,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -973,7 +1000,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -1067,14 +1094,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -1083,12 +1110,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -1118,12 +1145,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1439,7 +1466,7 @@ case 28:
yyval.vval = yystack.l_mark[-1].vval;
}
break;
-#line 1443 "calc1.tab.c"
+#line 1470 "calc1.tab.c"
default:
break;
}
@@ -1490,8 +1517,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1594,12 +1621,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/calc2.tab.c b/contrib/byacc/test/btyacc/calc2.tab.c
index 73e295a..68ffc38 100644
--- a/contrib/byacc/test/btyacc/calc2.tab.c
+++ b/contrib/byacc/test/btyacc/calc2.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -146,7 +146,7 @@ typedef int YYSTYPE;
# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
-# define YYPARSE_DECL() yyparse(int regs[26], int * base)
+# define YYPARSE_DECL() yyparse(int regs[26], int *base)
#endif
/* Parameters sent to lex. */
@@ -154,13 +154,13 @@ typedef int YYSTYPE;
# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
# define YYLEX yylex(YYLEX_PARAM)
#else
-# define YYLEX_DECL() yylex(int * base)
+# define YYLEX_DECL() yylex(int *base)
# define YYLEX yylex(base)
#endif
/* Parameters sent to yyerror. */
#ifndef YYERROR_DECL
-#define YYERROR_DECL() yyerror(int regs[26], int * base, const char *s)
+#define YYERROR_DECL() yyerror(int regs[26], int *base, const char *s)
#endif
#ifndef YYERROR_CALL
#define YYERROR_CALL(msg) yyerror(regs, base, msg)
@@ -268,6 +268,32 @@ static const YYINT calc2_check[] = { 40,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 256, 257, 258, 257, 258,
};
+#if YYBTYACC
+static const YYINT calc2_ctable[] = { -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,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -489,7 +515,7 @@ YYLEX_DECL()
}
return( c );
}
-#line 493 "calc2.tab.c"
+#line 519 "calc2.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -498,11 +524,11 @@ YYLEX_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -686,8 +712,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -783,12 +809,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -843,7 +869,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -937,14 +963,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -953,12 +979,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -988,12 +1014,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1206,7 +1232,7 @@ case 18:
#line 70 "calc2.y"
{ yyval = (*base) * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1210 "calc2.tab.c"
+#line 1236 "calc2.tab.c"
default:
break;
}
@@ -1257,8 +1283,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1361,12 +1387,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/calc3.tab.c b/contrib/byacc/test/btyacc/calc3.tab.c
index f1e4bc5..c9ca77f 100644
--- a/contrib/byacc/test/btyacc/calc3.tab.c
+++ b/contrib/byacc/test/btyacc/calc3.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -147,7 +147,7 @@ typedef int YYSTYPE;
# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
-# define YYPARSE_DECL() yyparse(int regs[26], int * base)
+# define YYPARSE_DECL() yyparse(int regs[26], int *base)
#endif
/* Parameters sent to lex. */
@@ -159,13 +159,13 @@ typedef int YYSTYPE;
# endif
# define YYLEX yylex(&yylval, YYLEX_PARAM)
#else
-# define YYLEX_DECL() yylex(YYSTYPE *yylval, int * base)
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, int *base)
# define YYLEX yylex(&yylval, base)
#endif
/* Parameters sent to yyerror. */
#ifndef YYERROR_DECL
-#define YYERROR_DECL() yyerror(int regs[26], int * base, const char *s)
+#define YYERROR_DECL() yyerror(int regs[26], int *base, const char *s)
#endif
#ifndef YYERROR_CALL
#define YYERROR_CALL(msg) yyerror(regs, base, msg)
@@ -273,6 +273,32 @@ static const YYINT calc3_check[] = { 40,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 256, 257, 258, 257, 258,
};
+#if YYBTYACC
+static const YYINT calc3_ctable[] = { -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,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -444,7 +470,7 @@ YYLEX_DECL()
}
return( c );
}
-#line 448 "calc3.tab.c"
+#line 474 "calc3.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -453,11 +479,11 @@ YYLEX_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -691,8 +717,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -788,12 +814,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -848,7 +874,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -942,14 +968,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -958,12 +984,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -993,12 +1019,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1211,7 +1237,7 @@ case 18:
#line 73 "calc3.y"
{ yyval = (*base) * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1215 "calc3.tab.c"
+#line 1241 "calc3.tab.c"
default:
break;
}
@@ -1262,8 +1288,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1366,12 +1392,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/code_calc.code.c b/contrib/byacc/test/btyacc/code_calc.code.c
index e69cced..1c08290 100644
--- a/contrib/byacc/test/btyacc/code_calc.code.c
+++ b/contrib/byacc/test/btyacc/code_calc.code.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -382,11 +382,11 @@ yylex(void)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -570,8 +570,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -667,12 +667,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -727,7 +727,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -821,14 +821,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -837,12 +837,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -872,12 +872,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1141,8 +1141,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1245,12 +1245,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/code_calc.tab.c b/contrib/byacc/test/btyacc/code_calc.tab.c
index 9ac746a..876b1dc 100644
--- a/contrib/byacc/test/btyacc/code_calc.tab.c
+++ b/contrib/byacc/test/btyacc/code_calc.tab.c
@@ -96,6 +96,32 @@ const YYINT calc_check[] = { 40,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 256, 257, 258, 257, 258,
};
+#if YYBTYACC
+const YYINT calc_ctable[] = { -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,
+};
+#endif
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
diff --git a/contrib/byacc/test/btyacc/code_error.code.c b/contrib/byacc/test/btyacc/code_error.code.c
index 5fceee5..883e3ab 100644
--- a/contrib/byacc/test/btyacc/code_error.code.c
+++ b/contrib/byacc/test/btyacc/code_error.code.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -354,11 +354,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -542,8 +542,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -639,12 +639,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -699,7 +699,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -793,14 +793,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -809,12 +809,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -844,12 +844,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1052,8 +1052,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1156,12 +1156,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/code_error.tab.c b/contrib/byacc/test/btyacc/code_error.tab.c
index 3a66ac6..d5288b2 100644
--- a/contrib/byacc/test/btyacc/code_error.tab.c
+++ b/contrib/byacc/test/btyacc/code_error.tab.c
@@ -33,6 +33,10 @@ const YYINT error_table[] = { 1,
};
const YYINT error_check[] = { 256,
};
+#if YYBTYACC
+const YYINT error_ctable[] = { -1,
+};
+#endif
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
diff --git a/contrib/byacc/test/btyacc/empty.tab.c b/contrib/byacc/test/btyacc/empty.tab.c
index cb487f7..06ecdcc 100644
--- a/contrib/byacc/test/btyacc/empty.tab.c
+++ b/contrib/byacc/test/btyacc/empty.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -197,6 +197,10 @@ static const YYINT empty_table[] = { 0,
};
static const YYINT empty_check[] = { -1,
};
+#if YYBTYACC
+static const YYINT empty_ctable[] = { -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -360,7 +364,7 @@ static void
YYERROR_DECL() {
printf("%s\n",s);
}
-#line 364 "empty.tab.c"
+#line 368 "empty.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -369,11 +373,11 @@ YYERROR_DECL() {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -557,8 +561,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -654,12 +658,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -714,7 +718,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -808,14 +812,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -824,12 +828,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -859,12 +863,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1067,8 +1071,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1171,12 +1175,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_inherit1.tab.c b/contrib/byacc/test/btyacc/err_inherit1.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_inherit1.tab.c
+++ b/contrib/byacc/test/btyacc/err_inherit1.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_inherit2.tab.c b/contrib/byacc/test/btyacc/err_inherit2.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_inherit2.tab.c
+++ b/contrib/byacc/test/btyacc/err_inherit2.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_inherit3.tab.c b/contrib/byacc/test/btyacc/err_inherit3.tab.c
index 58b3177..93b2706 100644
--- a/contrib/byacc/test/btyacc/err_inherit3.tab.c
+++ b/contrib/byacc/test/btyacc/err_inherit3.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -243,6 +243,11 @@ static const YYINT err_inherit3_check[] = { 257,
258, 259, 260, 14, 259, 260, 17, 261, 261, 6,
12,
};
+#if YYBTYACC
+static const YYINT err_inherit3_ctable[] = { -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 5
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -411,7 +416,7 @@ static short *yylexemes = 0;
extern int YYLEX_DECL();
extern void YYERROR_DECL();
-#line 415 "err_inherit3.tab.c"
+#line 420 "err_inherit3.tab.c"
/* Release memory associated with symbol. */
#if ! defined YYDESTRUCT_IS_DECLARED
@@ -431,7 +436,7 @@ YYDESTRUCT_DECL()
}
}
break;
-#line 435 "err_inherit3.tab.c"
+#line 440 "err_inherit3.tab.c"
case 264:
#line 30 "err_inherit3.y"
{
@@ -443,7 +448,7 @@ YYDESTRUCT_DECL()
}
}
break;
-#line 447 "err_inherit3.tab.c"
+#line 452 "err_inherit3.tab.c"
case 265:
#line 30 "err_inherit3.y"
{
@@ -455,7 +460,7 @@ YYDESTRUCT_DECL()
}
}
break;
-#line 459 "err_inherit3.tab.c"
+#line 464 "err_inherit3.tab.c"
}
}
#define YYDESTRUCT_IS_DECLARED 1
@@ -468,11 +473,11 @@ YYDESTRUCT_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -656,8 +661,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -753,12 +758,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -813,7 +818,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -907,14 +912,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -923,12 +928,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -958,12 +963,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1176,7 +1181,7 @@ case 14:
#line 75 "err_inherit3.y"
{ yyval.nlist = yystack.l_mark[0].nlist; }
break;
-#line 1180 "err_inherit3.tab.c"
+#line 1185 "err_inherit3.tab.c"
default:
break;
}
@@ -1227,8 +1232,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1331,12 +1336,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_inherit4.tab.c b/contrib/byacc/test/btyacc/err_inherit4.tab.c
index dfbb172..7e8e042 100644
--- a/contrib/byacc/test/btyacc/err_inherit4.tab.c
+++ b/contrib/byacc/test/btyacc/err_inherit4.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -263,6 +263,11 @@ static const YYINT err_inherit4_check[] = { 257,
258, 259, 260, 259, 260, 0, 261, 261, 0, 14,
6,
};
+#if YYBTYACC
+static const YYINT err_inherit4_ctable[] = { -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 5
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -429,7 +434,7 @@ static short *yylexemes = 0;
extern int YYLEX_DECL();
extern void YYERROR_DECL();
-#line 433 "err_inherit4.tab.c"
+#line 438 "err_inherit4.tab.c"
/* Release memory associated with symbol. */
#if ! defined YYDESTRUCT_IS_DECLARED
@@ -442,17 +447,17 @@ YYDESTRUCT_DECL()
#line 28 "err_inherit4.y"
{ }
break;
-#line 446 "err_inherit4.tab.c"
+#line 451 "err_inherit4.tab.c"
case 264:
#line 28 "err_inherit4.y"
{ }
break;
-#line 451 "err_inherit4.tab.c"
+#line 456 "err_inherit4.tab.c"
case 265:
#line 28 "err_inherit4.y"
{ }
break;
-#line 456 "err_inherit4.tab.c"
+#line 461 "err_inherit4.tab.c"
}
}
#define YYDESTRUCT_IS_DECLARED 1
@@ -465,11 +470,11 @@ YYDESTRUCT_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -653,8 +658,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -750,12 +755,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -810,7 +815,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -904,14 +909,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -920,12 +925,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -955,12 +960,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1165,7 +1170,7 @@ case 12:
#line 77 "err_inherit4.y"
{ yyval.nlist = yystack.l_mark[0].nlist; yyloc = yystack.p_mark[1]; }
break;
-#line 1169 "err_inherit4.tab.c"
+#line 1174 "err_inherit4.tab.c"
default:
break;
}
@@ -1216,8 +1221,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1320,12 +1325,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_inherit5.tab.c b/contrib/byacc/test/btyacc/err_inherit5.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_inherit5.tab.c
+++ b/contrib/byacc/test/btyacc/err_inherit5.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax1.tab.c b/contrib/byacc/test/btyacc/err_syntax1.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax1.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax1.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax10.tab.c b/contrib/byacc/test/btyacc/err_syntax10.tab.c
index 5c86453..4ec0d56e 100644
--- a/contrib/byacc/test/btyacc/err_syntax10.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax10.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -187,6 +187,10 @@ static const YYINT err_syntax10_table[] = { 1,
};
static const YYINT err_syntax10_check[] = { 256,
};
+#if YYBTYACC
+static const YYINT err_syntax10_ctable[] = { -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -359,7 +363,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 363 "err_syntax10.tab.c"
+#line 367 "err_syntax10.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -368,11 +372,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -556,8 +560,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -653,12 +657,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -713,7 +717,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -807,14 +811,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -823,12 +827,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -858,12 +862,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1066,8 +1070,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1170,12 +1174,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_syntax11.tab.c b/contrib/byacc/test/btyacc/err_syntax11.tab.c
index dfd0e9a..d1b51a1 100644
--- a/contrib/byacc/test/btyacc/err_syntax11.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax11.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -193,6 +193,10 @@ static const YYINT err_syntax11_table[] = { 1,
};
static const YYINT err_syntax11_check[] = { 256,
};
+#if YYBTYACC
+static const YYINT err_syntax11_ctable[] = { -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -365,7 +369,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 369 "err_syntax11.tab.c"
+#line 373 "err_syntax11.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -374,11 +378,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -562,8 +566,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -659,12 +663,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -719,7 +723,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -813,14 +817,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -829,12 +833,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -864,12 +868,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1072,8 +1076,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1176,12 +1180,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_syntax12.tab.c b/contrib/byacc/test/btyacc/err_syntax12.tab.c
index 86c01c2..6de4586 100644
--- a/contrib/byacc/test/btyacc/err_syntax12.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax12.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -194,6 +194,10 @@ static const YYINT err_syntax12_table[] = { 1,
};
static const YYINT err_syntax12_check[] = { 256,
};
+#if YYBTYACC
+static const YYINT err_syntax12_ctable[] = { -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -371,7 +375,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 375 "err_syntax12.tab.c"
+#line 379 "err_syntax12.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -380,11 +384,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -568,8 +572,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -665,12 +669,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -725,7 +729,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -819,14 +823,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -835,12 +839,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -870,12 +874,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1078,8 +1082,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1182,12 +1186,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_syntax13.tab.c b/contrib/byacc/test/btyacc/err_syntax13.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax13.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax13.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax14.tab.c b/contrib/byacc/test/btyacc/err_syntax14.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax14.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax14.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax15.tab.c b/contrib/byacc/test/btyacc/err_syntax15.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax15.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax15.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax16.tab.c b/contrib/byacc/test/btyacc/err_syntax16.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax16.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax16.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax17.tab.c b/contrib/byacc/test/btyacc/err_syntax17.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax17.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax17.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax18.tab.c b/contrib/byacc/test/btyacc/err_syntax18.tab.c
index 2a8a109..45e8e71 100644
--- a/contrib/byacc/test/btyacc/err_syntax18.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax18.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -195,6 +195,11 @@ static const YYINT err_syntax18_table[] = { 1,
static const YYINT err_syntax18_check[] = { 40,
-1, 41, 1,
};
+#if YYBTYACC
+static const YYINT err_syntax18_ctable[] = { -1,
+ -1, -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -367,7 +372,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 371 "err_syntax18.tab.c"
+#line 376 "err_syntax18.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -376,11 +381,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -564,8 +569,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -661,12 +666,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -721,7 +726,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -815,14 +820,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -831,12 +836,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -866,12 +871,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1028,7 +1033,7 @@ case 1:
#line 9 "err_syntax18.y"
{ yyval = yystack.l_mark[1]; }
break;
-#line 1032 "err_syntax18.tab.c"
+#line 1037 "err_syntax18.tab.c"
default:
break;
}
@@ -1079,8 +1084,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1183,12 +1188,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_syntax19.tab.c b/contrib/byacc/test/btyacc/err_syntax19.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax19.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax19.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax2.tab.c b/contrib/byacc/test/btyacc/err_syntax2.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax2.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax2.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax20.tab.c b/contrib/byacc/test/btyacc/err_syntax20.tab.c
index 80ec2ed..6505438 100644
--- a/contrib/byacc/test/btyacc/err_syntax20.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax20.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -190,6 +190,11 @@ static const YYINT err_syntax20_table[] = { 1,
static const YYINT err_syntax20_check[] = { 40,
257, 41,
};
+#if YYBTYACC
+static const YYINT err_syntax20_ctable[] = { -1,
+ -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -362,7 +367,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 366 "err_syntax20.tab.c"
+#line 371 "err_syntax20.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -371,11 +376,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -559,8 +564,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -656,12 +661,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -716,7 +721,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -810,14 +815,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -826,12 +831,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -861,12 +866,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1023,7 +1028,7 @@ case 1:
#line 12 "err_syntax20.y"
{ yystack.l_mark[-1].rechk = 3; }
break;
-#line 1027 "err_syntax20.tab.c"
+#line 1032 "err_syntax20.tab.c"
default:
break;
}
@@ -1074,8 +1079,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1178,12 +1183,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/err_syntax21.tab.c b/contrib/byacc/test/btyacc/err_syntax21.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax21.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax21.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax22.tab.c b/contrib/byacc/test/btyacc/err_syntax22.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax22.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax22.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax23.tab.c b/contrib/byacc/test/btyacc/err_syntax23.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax23.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax23.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax24.tab.c b/contrib/byacc/test/btyacc/err_syntax24.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax24.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax24.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax25.tab.c b/contrib/byacc/test/btyacc/err_syntax25.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax25.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax25.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax26.tab.c b/contrib/byacc/test/btyacc/err_syntax26.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax26.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax26.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax27.tab.c b/contrib/byacc/test/btyacc/err_syntax27.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax27.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax27.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax3.tab.c b/contrib/byacc/test/btyacc/err_syntax3.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax3.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax3.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax4.tab.c b/contrib/byacc/test/btyacc/err_syntax4.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax4.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax4.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax5.tab.c b/contrib/byacc/test/btyacc/err_syntax5.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax5.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax5.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax6.tab.c b/contrib/byacc/test/btyacc/err_syntax6.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax6.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax6.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax7.tab.c b/contrib/byacc/test/btyacc/err_syntax7.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax7.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax7.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax7a.tab.c b/contrib/byacc/test/btyacc/err_syntax7a.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax7a.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax7a.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax7b.tab.c b/contrib/byacc/test/btyacc/err_syntax7b.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax7b.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax7b.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax8.tab.c b/contrib/byacc/test/btyacc/err_syntax8.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax8.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax8.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax8a.tab.c b/contrib/byacc/test/btyacc/err_syntax8a.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax8a.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax8a.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/err_syntax9.tab.c b/contrib/byacc/test/btyacc/err_syntax9.tab.c
index 6c35f23..ac0ad3a 100644
--- a/contrib/byacc/test/btyacc/err_syntax9.tab.c
+++ b/contrib/byacc/test/btyacc/err_syntax9.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
diff --git a/contrib/byacc/test/btyacc/error.tab.c b/contrib/byacc/test/btyacc/error.tab.c
index 17cd75c..d5c10eb 100644
--- a/contrib/byacc/test/btyacc/error.tab.c
+++ b/contrib/byacc/test/btyacc/error.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -193,6 +193,10 @@ static const YYINT error_table[] = { 1,
};
static const YYINT error_check[] = { 256,
};
+#if YYBTYACC
+static const YYINT error_ctable[] = { -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -364,7 +368,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 368 "error.tab.c"
+#line 372 "error.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -373,11 +377,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -561,8 +565,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -658,12 +662,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -718,7 +722,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -812,14 +816,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -828,12 +832,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -863,12 +867,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1071,8 +1075,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1175,12 +1179,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/grammar.tab.c b/contrib/byacc/test/btyacc/grammar.tab.c
index fc5270a..238bcaa 100644
--- a/contrib/byacc/test/btyacc/grammar.tab.c
+++ b/contrib/byacc/test/btyacc/grammar.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -794,6 +794,103 @@ static const YYINT grammar_check[] = { 38,
269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
279, 280, 281, 282,
};
+#if YYBTYACC
+static const YYINT grammar_ctable[] = { -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, -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, -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, -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,
+};
+#endif
#define YYFINAL 33
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -1244,7 +1341,7 @@ free_parser(void)
#endif
}
#endif
-#line 1248 "grammar.tab.c"
+#line 1345 "grammar.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -1253,11 +1350,11 @@ free_parser(void)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -1441,8 +1538,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -1538,12 +1635,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -1598,7 +1695,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -1692,14 +1789,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -1708,12 +1805,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -1743,12 +1840,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -2575,7 +2672,7 @@ case 114:
yyval.declarator->func_def = FUNC_ANSI;
}
break;
-#line 2579 "grammar.tab.c"
+#line 2676 "grammar.tab.c"
default:
break;
}
@@ -2626,8 +2723,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -2730,12 +2827,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/inherit0.tab.c b/contrib/byacc/test/btyacc/inherit0.tab.c
index 238d5ab..7308584 100644
--- a/contrib/byacc/test/btyacc/inherit0.tab.c
+++ b/contrib/byacc/test/btyacc/inherit0.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -217,6 +217,11 @@ static const YYINT inherit0_check[] = { 257,
258, 259, 260, 259, 260, 0, 261, 261, 0, 6,
13,
};
+#if YYBTYACC
+static const YYINT inherit0_ctable[] = { -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 5
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -382,7 +387,7 @@ static short *yylexemes = 0;
extern int YYLEX_DECL();
extern void YYERROR_DECL();
-#line 386 "inherit0.tab.c"
+#line 391 "inherit0.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -391,11 +396,11 @@ extern void YYERROR_DECL();
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -579,8 +584,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -676,12 +681,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -736,7 +741,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -830,14 +835,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -846,12 +851,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -881,12 +886,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1083,7 +1088,7 @@ case 11:
#line 43 "inherit0.y"
{ yyval = yystack.l_mark[0]; }
break;
-#line 1087 "inherit0.tab.c"
+#line 1092 "inherit0.tab.c"
default:
break;
}
@@ -1134,8 +1139,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1238,12 +1243,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/inherit1.tab.c b/contrib/byacc/test/btyacc/inherit1.tab.c
index 126812e..2c0f958 100644
--- a/contrib/byacc/test/btyacc/inherit1.tab.c
+++ b/contrib/byacc/test/btyacc/inherit1.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -238,6 +238,11 @@ static const YYINT inherit1_check[] = { 257,
258, 259, 260, 259, 260, 0, 261, 261, 0, 13,
6,
};
+#if YYBTYACC
+static const YYINT inherit1_ctable[] = { -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 5
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -403,7 +408,7 @@ static short *yylexemes = 0;
extern int YYLEX_DECL();
extern void YYERROR_DECL();
-#line 407 "inherit1.tab.c"
+#line 412 "inherit1.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -412,11 +417,11 @@ extern void YYERROR_DECL();
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -600,8 +605,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -697,12 +702,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -757,7 +762,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -851,14 +856,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -867,12 +872,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -902,12 +907,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1108,7 +1113,7 @@ case 11:
#line 71 "inherit1.y"
{ yyval.nlist = yystack.l_mark[0].nlist; }
break;
-#line 1112 "inherit1.tab.c"
+#line 1117 "inherit1.tab.c"
default:
break;
}
@@ -1159,8 +1164,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1263,12 +1268,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/inherit2.tab.c b/contrib/byacc/test/btyacc/inherit2.tab.c
index d32cbe7..67eb0bd 100644
--- a/contrib/byacc/test/btyacc/inherit2.tab.c
+++ b/contrib/byacc/test/btyacc/inherit2.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -243,6 +243,12 @@ static const YYINT inherit2_check[] = { 257,
258, 259, 260, 259, 260, 0, 261, 261, 0, 14,
6, -1, 12,
};
+#if YYBTYACC
+static const YYINT inherit2_ctable[] = { -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1,
+};
+#endif
#define YYFINAL 5
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -410,7 +416,7 @@ static short *yylexemes = 0;
extern int YYLEX_DECL();
extern void YYERROR_DECL();
-#line 414 "inherit2.tab.c"
+#line 420 "inherit2.tab.c"
/* Release memory associated with symbol. */
#if ! defined YYDESTRUCT_IS_DECLARED
@@ -430,7 +436,7 @@ YYDESTRUCT_DECL()
}
}
break;
-#line 434 "inherit2.tab.c"
+#line 440 "inherit2.tab.c"
case 264:
#line 30 "inherit2.y"
{
@@ -442,7 +448,7 @@ YYDESTRUCT_DECL()
}
}
break;
-#line 446 "inherit2.tab.c"
+#line 452 "inherit2.tab.c"
case 265:
#line 30 "inherit2.y"
{
@@ -454,7 +460,7 @@ YYDESTRUCT_DECL()
}
}
break;
-#line 458 "inherit2.tab.c"
+#line 464 "inherit2.tab.c"
}
}
#define YYDESTRUCT_IS_DECLARED 1
@@ -467,11 +473,11 @@ YYDESTRUCT_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -655,8 +661,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -752,12 +758,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -812,7 +818,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -906,14 +912,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -922,12 +928,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -957,12 +963,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1171,7 +1177,7 @@ case 13:
#line 75 "inherit2.y"
{ yyval.nlist = yystack.l_mark[0].nlist; }
break;
-#line 1175 "inherit2.tab.c"
+#line 1181 "inherit2.tab.c"
default:
break;
}
@@ -1222,8 +1228,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1326,12 +1332,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/ok_syntax1.tab.c b/contrib/byacc/test/btyacc/ok_syntax1.tab.c
index 37e0828..5ecb9f9 100644
--- a/contrib/byacc/test/btyacc/ok_syntax1.tab.c
+++ b/contrib/byacc/test/btyacc/ok_syntax1.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -155,7 +155,7 @@ typedef union
# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
-# define YYPARSE_DECL() yyparse(int regs[26], int * base)
+# define YYPARSE_DECL() yyparse(int regs[26], int *base)
#endif
/* Parameters sent to lex. */
@@ -167,13 +167,13 @@ typedef union
# endif
# define YYLEX yylex(&yylval, YYLEX_PARAM)
#else
-# define YYLEX_DECL() yylex(YYSTYPE *yylval, int * base)
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, int *base)
# define YYLEX yylex(&yylval, base)
#endif
/* Parameters sent to yyerror. */
#ifndef YYERROR_DECL
-#define YYERROR_DECL() yyerror(int regs[26], int * base, const char *s)
+#define YYERROR_DECL() yyerror(int regs[26], int *base, const char *s)
#endif
#ifndef YYERROR_CALL
#define YYERROR_CALL(msg) yyerror(regs, base, msg)
@@ -294,6 +294,32 @@ static const YYINT ok_syntax1_check[] = { 40,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 256, 257, 258, 257, 258,
};
+#if YYBTYACC
+static const YYINT ok_syntax1_ctable[] = { -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,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -467,7 +493,7 @@ YYLEX_DECL()
}
return( c );
}
-#line 471 "ok_syntax1.tab.c"
+#line 497 "ok_syntax1.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -476,11 +502,11 @@ YYLEX_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -714,8 +740,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -811,12 +837,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -871,7 +897,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -965,14 +991,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -981,12 +1007,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -1016,12 +1042,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1234,7 +1260,7 @@ case 18:
#line 101 "ok_syntax1.y"
{ yyval.ival = (*base) * yystack.l_mark[-1].ival + yystack.l_mark[0].ival; }
break;
-#line 1238 "ok_syntax1.tab.c"
+#line 1264 "ok_syntax1.tab.c"
default:
break;
}
@@ -1285,8 +1311,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1389,12 +1415,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/pure_calc.tab.c b/contrib/byacc/test/btyacc/pure_calc.tab.c
index 28de5d6..00dbd72 100644
--- a/contrib/byacc/test/btyacc/pure_calc.tab.c
+++ b/contrib/byacc/test/btyacc/pure_calc.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -276,6 +276,32 @@ static const YYINT calc_check[] = { 40,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 256, 257, 258, 257, 258,
};
+#if YYBTYACC
+static const YYINT calc_ctable[] = { -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,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -440,7 +466,7 @@ YYLEX_DECL()
}
return( c );
}
-#line 444 "pure_calc.tab.c"
+#line 470 "pure_calc.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -449,11 +475,11 @@ YYLEX_DECL()
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -687,8 +713,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -784,12 +810,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -844,7 +870,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -938,14 +964,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -954,12 +980,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -989,12 +1015,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1207,7 +1233,7 @@ case 18:
#line 69 "pure_calc.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1211 "pure_calc.tab.c"
+#line 1237 "pure_calc.tab.c"
default:
break;
}
@@ -1258,8 +1284,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1362,12 +1388,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/pure_error.tab.c b/contrib/byacc/test/btyacc/pure_error.tab.c
index 2f3b697..9fcd309 100644
--- a/contrib/byacc/test/btyacc/pure_error.tab.c
+++ b/contrib/byacc/test/btyacc/pure_error.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -205,6 +205,10 @@ static const YYINT error_table[] = { 1,
};
static const YYINT error_check[] = { 256,
};
+#if YYBTYACC
+static const YYINT error_ctable[] = { -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -330,7 +334,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 334 "pure_error.tab.c"
+#line 338 "pure_error.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -339,11 +343,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -577,8 +581,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -674,12 +678,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -734,7 +738,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -828,14 +832,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -844,12 +848,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -879,12 +883,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1087,8 +1091,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1191,12 +1195,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc-s.tab.c b/contrib/byacc/test/btyacc/quote_calc-s.tab.c
index 93d94ad..3462a45 100644
--- a/contrib/byacc/test/btyacc/quote_calc-s.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc-s.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -280,6 +280,36 @@ static const YYINT quote_calc_check[] = { 10,
263, -1, 265, -1, 267, -1, 257, 257, 259, 259,
261, 261, 263, 263, 265, 265, 267, 267,
};
+#if YYBTYACC
+static const YYINT quote_calc_ctable[] = { -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, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -490,7 +520,7 @@ yylex(void) {
}
return( c );
}
-#line 494 "quote_calc-s.tab.c"
+#line 524 "quote_calc-s.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -499,11 +529,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -687,8 +717,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -784,12 +814,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -844,7 +874,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -938,14 +968,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -954,12 +984,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -989,12 +1019,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1207,7 +1237,7 @@ case 18:
#line 70 "quote_calc.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1211 "quote_calc-s.tab.c"
+#line 1241 "quote_calc-s.tab.c"
default:
break;
}
@@ -1258,8 +1288,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1362,12 +1392,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc.tab.c b/contrib/byacc/test/btyacc/quote_calc.tab.c
index 56c7abc..350252e 100644
--- a/contrib/byacc/test/btyacc/quote_calc.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -286,6 +286,36 @@ static const YYINT quote_calc_check[] = { 10,
263, -1, 265, -1, 267, -1, 257, 257, 259, 259,
261, 261, 263, 263, 265, 265, 267, 267,
};
+#if YYBTYACC
+static const YYINT quote_calc_ctable[] = { -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, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -496,7 +526,7 @@ yylex(void) {
}
return( c );
}
-#line 500 "quote_calc.tab.c"
+#line 530 "quote_calc.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -505,11 +535,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -693,8 +723,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -790,12 +820,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -850,7 +880,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -944,14 +974,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -960,12 +990,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -995,12 +1025,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1213,7 +1243,7 @@ case 18:
#line 70 "quote_calc.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1217 "quote_calc.tab.c"
+#line 1247 "quote_calc.tab.c"
default:
break;
}
@@ -1264,8 +1294,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1368,12 +1398,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc2-s.tab.c b/contrib/byacc/test/btyacc/quote_calc2-s.tab.c
index be41425..c5b4cf9 100644
--- a/contrib/byacc/test/btyacc/quote_calc2-s.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc2-s.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -280,6 +280,36 @@ static const YYINT quote_calc2_check[] = { 10,
264, -1, 266, -1, 268, -1, -1, 258, 258, 260,
260, 262, 262, 264, 264, 266, 266, 268, 268,
};
+#if YYBTYACC
+static const YYINT quote_calc2_ctable[] = { -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, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -490,7 +520,7 @@ yylex(void) {
}
return( c );
}
-#line 494 "quote_calc2-s.tab.c"
+#line 524 "quote_calc2-s.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -499,11 +529,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -687,8 +717,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -784,12 +814,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -844,7 +874,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -938,14 +968,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -954,12 +984,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -989,12 +1019,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1207,7 +1237,7 @@ case 18:
#line 70 "quote_calc2.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1211 "quote_calc2-s.tab.c"
+#line 1241 "quote_calc2-s.tab.c"
default:
break;
}
@@ -1258,8 +1288,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1362,12 +1392,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc2.tab.c b/contrib/byacc/test/btyacc/quote_calc2.tab.c
index 496926e..703e60f 100644
--- a/contrib/byacc/test/btyacc/quote_calc2.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc2.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -286,6 +286,36 @@ static const YYINT quote_calc2_check[] = { 10,
264, -1, 266, -1, 268, -1, -1, 258, 258, 260,
260, 262, 262, 264, 264, 266, 266, 268, 268,
};
+#if YYBTYACC
+static const YYINT quote_calc2_ctable[] = { -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, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -496,7 +526,7 @@ yylex(void) {
}
return( c );
}
-#line 500 "quote_calc2.tab.c"
+#line 530 "quote_calc2.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -505,11 +535,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -693,8 +723,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -790,12 +820,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -850,7 +880,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -944,14 +974,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -960,12 +990,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -995,12 +1025,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1213,7 +1243,7 @@ case 18:
#line 70 "quote_calc2.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1217 "quote_calc2.tab.c"
+#line 1247 "quote_calc2.tab.c"
default:
break;
}
@@ -1264,8 +1294,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1368,12 +1398,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc3-s.tab.c b/contrib/byacc/test/btyacc/quote_calc3-s.tab.c
index a7072f9..080d917 100644
--- a/contrib/byacc/test/btyacc/quote_calc3-s.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc3-s.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -280,6 +280,36 @@ static const YYINT quote_calc3_check[] = { 10,
263, -1, 265, -1, 267, -1, 257, 257, 259, 259,
261, 261, 263, 263, 265, 265, 267, 267,
};
+#if YYBTYACC
+static const YYINT quote_calc3_ctable[] = { -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, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -491,7 +521,7 @@ yylex(void) {
}
return( c );
}
-#line 495 "quote_calc3-s.tab.c"
+#line 525 "quote_calc3-s.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -500,11 +530,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -688,8 +718,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -785,12 +815,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -845,7 +875,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -939,14 +969,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -955,12 +985,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -990,12 +1020,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1208,7 +1238,7 @@ case 18:
#line 70 "quote_calc3.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1212 "quote_calc3-s.tab.c"
+#line 1242 "quote_calc3-s.tab.c"
default:
break;
}
@@ -1259,8 +1289,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1363,12 +1393,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc3.tab.c b/contrib/byacc/test/btyacc/quote_calc3.tab.c
index 6b13314..12bfcba 100644
--- a/contrib/byacc/test/btyacc/quote_calc3.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc3.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -280,6 +280,36 @@ static const YYINT quote_calc3_check[] = { 10,
263, -1, 265, -1, 267, -1, 257, 257, 259, 259,
261, 261, 263, 263, 265, 265, 267, 267,
};
+#if YYBTYACC
+static const YYINT quote_calc3_ctable[] = { -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, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -491,7 +521,7 @@ yylex(void) {
}
return( c );
}
-#line 495 "quote_calc3.tab.c"
+#line 525 "quote_calc3.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -500,11 +530,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -688,8 +718,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -785,12 +815,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -845,7 +875,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -939,14 +969,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -955,12 +985,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -990,12 +1020,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1208,7 +1238,7 @@ case 18:
#line 70 "quote_calc3.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1212 "quote_calc3.tab.c"
+#line 1242 "quote_calc3.tab.c"
default:
break;
}
@@ -1259,8 +1289,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1363,12 +1393,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc4-s.tab.c b/contrib/byacc/test/btyacc/quote_calc4-s.tab.c
index df8a957..c7c41f6 100644
--- a/contrib/byacc/test/btyacc/quote_calc4-s.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc4-s.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -280,6 +280,36 @@ static const YYINT quote_calc4_check[] = { 10,
264, -1, 266, -1, 268, -1, -1, 258, 258, 260,
260, 262, 262, 264, 264, 266, 266, 268, 268,
};
+#if YYBTYACC
+static const YYINT quote_calc4_ctable[] = { -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, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -491,7 +521,7 @@ yylex(void) {
}
return( c );
}
-#line 495 "quote_calc4-s.tab.c"
+#line 525 "quote_calc4-s.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -500,11 +530,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -688,8 +718,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -785,12 +815,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -845,7 +875,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -939,14 +969,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -955,12 +985,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -990,12 +1020,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1208,7 +1238,7 @@ case 18:
#line 70 "quote_calc4.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1212 "quote_calc4-s.tab.c"
+#line 1242 "quote_calc4-s.tab.c"
default:
break;
}
@@ -1259,8 +1289,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1363,12 +1393,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/quote_calc4.tab.c b/contrib/byacc/test/btyacc/quote_calc4.tab.c
index 59e6d1f..b28a561 100644
--- a/contrib/byacc/test/btyacc/quote_calc4.tab.c
+++ b/contrib/byacc/test/btyacc/quote_calc4.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -280,6 +280,36 @@ static const YYINT quote_calc4_check[] = { 10,
264, -1, 266, -1, 268, -1, -1, 258, 258, 260,
260, 262, 262, 264, 264, 266, 266, 268, 268,
};
+#if YYBTYACC
+static const YYINT quote_calc4_ctable[] = { -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, -1, -1, -1, -1,
+};
+#endif
#define YYFINAL 1
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -491,7 +521,7 @@ yylex(void) {
}
return( c );
}
-#line 495 "quote_calc4.tab.c"
+#line 525 "quote_calc4.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -500,11 +530,11 @@ yylex(void) {
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -688,8 +718,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -785,12 +815,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -845,7 +875,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -939,14 +969,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -955,12 +985,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -990,12 +1020,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1208,7 +1238,7 @@ case 18:
#line 70 "quote_calc4.y"
{ yyval = base * yystack.l_mark[-1] + yystack.l_mark[0]; }
break;
-#line 1212 "quote_calc4.tab.c"
+#line 1242 "quote_calc4.tab.c"
default:
break;
}
@@ -1259,8 +1289,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1363,12 +1393,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/rename_debug.c b/contrib/byacc/test/btyacc/rename_debug.c
index 330e725..3964bf1 100644
--- a/contrib/byacc/test/btyacc/rename_debug.c
+++ b/contrib/byacc/test/btyacc/rename_debug.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -52,6 +52,10 @@ static const YYINT yytable[] = { 1,
};
static const YYINT yycheck[] = { 256,
};
+#if YYBTYACC
+static const YYINT yyctable[] = { -1,
+};
+#endif
#define YYFINAL 2
#ifndef YYDEBUG
#define YYDEBUG 1
@@ -227,7 +231,7 @@ yyerror(const char* s)
{
printf("%s\n", s);
}
-#line 232 "rename_debug.c"
+#line 236 "rename_debug.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -236,11 +240,11 @@ yyerror(const char* s)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -424,8 +428,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -521,12 +525,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -581,7 +585,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -675,14 +679,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -691,12 +695,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -726,12 +730,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -934,8 +938,8 @@ yyreduce:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1038,12 +1042,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc/varsyntax_calc1.tab.c b/contrib/byacc/test/btyacc/varsyntax_calc1.tab.c
index afab810..4a35a06f 100644
--- a/contrib/byacc/test/btyacc/varsyntax_calc1.tab.c
+++ b/contrib/byacc/test/btyacc/varsyntax_calc1.tab.c
@@ -1,6 +1,6 @@
/* original parser id follows */
/* yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93" */
-/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent of parser version) */
#define YYBYACC 1
#define YYMAJOR 1
@@ -311,6 +311,33 @@ static const YYINT varsyntax_calc1_check[] = { 40,
-1, -1, -1, -1, -1, 256, 257, 258, 259, 257,
258, 259, 257, -1, 259,
};
+#if YYBTYACC
+static const YYINT varsyntax_calc1_ctable[] = { -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,
+};
+#endif
#define YYFINAL 7
#ifndef YYDEBUG
#define YYDEBUG 0
@@ -620,7 +647,7 @@ vdiv(double a, double b, INTERVAL v)
{
return (hilo(a / v.hi, a / v.lo, b / v.hi, b / v.lo));
}
-#line 624 "varsyntax_calc1.tab.c"
+#line 651 "varsyntax_calc1.tab.c"
/* For use in generated program */
#define yydepth (int)(yystack.s_mark - yystack.s_base)
@@ -629,11 +656,11 @@ vdiv(double a, double b, INTERVAL v)
#endif /* YYBTYACC */
#if YYDEBUG
-#include <stdio.h> /* needed for printf */
+#include <stdio.h> /* needed for printf */
#endif
-#include <stdlib.h> /* needed for malloc, etc */
-#include <string.h> /* needed for memset */
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
static int yygrowstack(YYSTACKDATA *data)
@@ -817,8 +844,8 @@ yyloop:
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL) goto yyenomem;
@@ -914,12 +941,12 @@ yyloop:
save->state = yystate;
save->errflag = yyerrflag;
save->yystack.s_mark = save->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (save->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (save->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
save->yystack.l_mark = save->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (save->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (save->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
save->yystack.p_mark = save->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (save->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (save->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = yytable[yyn];
if (yyctable[ctry] == -1)
@@ -974,7 +1001,7 @@ yyloop:
yylexp--;
yychar = YYEMPTY;
}
- save->lexeme = yylvp - yylvals;
+ save->lexeme = (int) (yylvp - yylvals);
yyps->save = save;
}
if (yytable[yyn] == ctry)
@@ -1068,14 +1095,14 @@ yyerrhandler:
yyerrctx->state = yystate;
yyerrctx->errflag = yyerrflag;
yyerrctx->yystack.s_mark = yyerrctx->yystack.s_base + (yystack.s_mark - yystack.s_base);
- memcpy (yyerrctx->yystack.s_base, yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yyerrctx->yystack.s_base, yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yyerrctx->yystack.l_mark = yyerrctx->yystack.l_base + (yystack.l_mark - yystack.l_base);
- memcpy (yyerrctx->yystack.l_base, yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yyerrctx->yystack.l_base, yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yyerrctx->yystack.p_mark = yyerrctx->yystack.p_base + (yystack.p_mark - yystack.p_base);
- memcpy (yyerrctx->yystack.p_base, yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yyerrctx->yystack.p_base, yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
- yyerrctx->lexeme = yylvp - yylvals;
+ yyerrctx->lexeme = (int) (yylvp - yylvals);
}
yylvp = yylvals + save->lexeme;
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
@@ -1084,12 +1111,12 @@ yyerrhandler:
yylexp = yylexemes + save->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (save->yystack.s_mark - save->yystack.s_base);
- memcpy (yystack.s_base, save->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, save->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (save->yystack.l_mark - save->yystack.l_base);
- memcpy (yystack.l_base, save->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, save->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (save->yystack.p_mark - save->yystack.p_base);
- memcpy (yystack.p_base, save->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, save->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
ctry = ++save->ctry;
yystate = save->state;
@@ -1119,12 +1146,12 @@ yyerrhandler:
yylloc = yylpp[-1];
#endif
yystack.s_mark = yystack.s_base + (yyerrctx->yystack.s_mark - yyerrctx->yystack.s_base);
- memcpy (yystack.s_base, yyerrctx->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yyerrctx->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yyerrctx->yystack.l_mark - yyerrctx->yystack.l_base);
- memcpy (yystack.l_base, yyerrctx->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yyerrctx->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yyerrctx->yystack.p_mark - yyerrctx->yystack.p_base);
- memcpy (yystack.p_base, yyerrctx->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yyerrctx->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yyerrctx->state;
yyFreeState(yyerrctx);
@@ -1440,7 +1467,7 @@ case 28:
yyval.vval = yystack.l_mark[-1].vval;
}
break;
-#line 1444 "varsyntax_calc1.tab.c"
+#line 1471 "varsyntax_calc1.tab.c"
default:
break;
}
@@ -1491,8 +1518,8 @@ break;
/* in trial mode; save scanner results for future parse attempts */
if (yylvp == yylvlim)
{ /* Enlarge lexical value queue */
- int p = yylvp - yylvals;
- int s = yylvlim - yylvals;
+ size_t p = (size_t) (yylvp - yylvals);
+ size_t s = (size_t) (yylvlim - yylvals);
s += YYLVQUEUEGROWTH;
if ((yylexemes = (short *) realloc(yylexemes, s * sizeof(short))) == NULL)
@@ -1595,12 +1622,12 @@ yyvalid:
yylexp = yylexemes + yypath->lexeme;
yychar = YYEMPTY;
yystack.s_mark = yystack.s_base + (yypath->yystack.s_mark - yypath->yystack.s_base);
- memcpy (yystack.s_base, yypath->yystack.s_base, (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
+ memcpy (yystack.s_base, yypath->yystack.s_base, (size_t) (yystack.s_mark - yystack.s_base + 1) * sizeof(short));
yystack.l_mark = yystack.l_base + (yypath->yystack.l_mark - yypath->yystack.l_base);
- memcpy (yystack.l_base, yypath->yystack.l_base, (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
+ memcpy (yystack.l_base, yypath->yystack.l_base, (size_t) (yystack.l_mark - yystack.l_base + 1) * sizeof(YYSTYPE));
#if defined(YYLTYPE) || defined(YYLTYPE_IS_DECLARED)
yystack.p_mark = yystack.p_base + (yypath->yystack.p_mark - yypath->yystack.p_base);
- memcpy (yystack.p_base, yypath->yystack.p_base, (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
+ memcpy (yystack.p_base, yypath->yystack.p_base, (size_t) (yystack.p_mark - yystack.p_base + 1) * sizeof(YYLTYPE));
#endif
yystate = yypath->state;
goto yyloop;
diff --git a/contrib/byacc/test/btyacc_destroy1.y b/contrib/byacc/test/btyacc_destroy1.y
new file mode 100644
index 0000000..413066d
--- /dev/null
+++ b/contrib/byacc/test/btyacc_destroy1.y
@@ -0,0 +1,91 @@
+%parse-param { struct parser_param *param , int flag }
+
+%{
+#include <stdlib.h>
+
+typedef enum {cGLOBAL, cLOCAL} class;
+typedef enum {tREAL, tINTEGER} type;
+typedef char * name;
+
+struct symbol { class c; type t; name id; };
+typedef struct symbol symbol;
+
+struct namelist { symbol *s; struct namelist *next; };
+typedef struct namelist namelist;
+
+struct parser_param {
+ int *rtrn;
+ symbol ss;
+};
+
+extern symbol *mksymbol(type t, class c, name id);
+
+#ifdef YYBISON
+#define YYLEX_DECL() yylex(void)
+#define YYERROR_DECL() yyerror(const char *s)
+#endif
+%}
+
+%token <cval> GLOBAL LOCAL
+%token <tval> REAL INTEGER
+%token <id> NAME
+
+%type <nlist> declaration
+%type <nlist> locnamelist
+%type <cval> class
+%type <tval> type
+%type <nlist> namelist
+
+%destructor { if (!param->rtrn) close($$); } <file>
+
+%destructor {
+ namelist *p = $$;
+ while (p != NULL)
+ { namelist *pp = p;
+ p = p->next;
+ free(pp->s); free(pp);
+ }
+ } declaration
+
+%union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+}
+
+%start declaration
+
+%%
+declaration: class type namelist'(' class ',' type ')'
+ { $$ = $3; }
+ | type locnamelist '(' class ')'
+ { $$ = $2; }
+ ;
+
+class : GLOBAL { $$ = cGLOBAL; }
+ | LOCAL { $$ = cLOCAL; }
+ ;
+
+type : REAL { $$ = tREAL; }
+ | INTEGER { $$ = tINTEGER; }
+ ;
+
+namelist: namelist NAME
+ { $$->s = mksymbol($<tval>0, $<cval>0, $2);
+ $$->next = $1;
+ }
+ | NAME
+ { $$->s = mksymbol(0, 0, $1);
+ $$->next = NULL;
+ }
+ ;
+
+locnamelist: namelist '(' LOCAL ',' type ')'
+ { $$ = $1; }
+ ;
+%%
+
+extern int YYLEX_DECL();
+extern void YYERROR_DECL();
diff --git a/contrib/byacc/test/btyacc_destroy2.y b/contrib/byacc/test/btyacc_destroy2.y
new file mode 100644
index 0000000..883b9f5
--- /dev/null
+++ b/contrib/byacc/test/btyacc_destroy2.y
@@ -0,0 +1,91 @@
+%parse-param { struct parser_param *param } { int flag }
+
+%{
+#include <stdlib.h>
+
+typedef enum {cGLOBAL, cLOCAL} class;
+typedef enum {tREAL, tINTEGER} type;
+typedef char * name;
+
+struct symbol { class c; type t; name id; };
+typedef struct symbol symbol;
+
+struct namelist { symbol *s; struct namelist *next; };
+typedef struct namelist namelist;
+
+struct parser_param {
+ int *rtrn;
+ symbol ss;
+};
+
+extern symbol *mksymbol(type t, class c, name id);
+
+#ifdef YYBISON
+#define YYLEX_DECL() yylex(void)
+#define YYERROR_DECL() yyerror(const char *s)
+#endif
+%}
+
+%token <cval> GLOBAL LOCAL
+%token <tval> REAL INTEGER
+%token <id> NAME
+
+%type <nlist> declaration
+%type <nlist> locnamelist
+%type <cval> class
+%type <tval> type
+%type <nlist> namelist
+
+%destructor { if (!param->rtrn) close($$); } <file>
+
+%destructor {
+ namelist *p = $$;
+ while (p != NULL)
+ { namelist *pp = p;
+ p = p->next;
+ free(pp->s); free(pp);
+ }
+ } declaration
+
+%union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+}
+
+%start declaration
+
+%%
+declaration: class type namelist'(' class ',' type ')'
+ { $$ = $3; }
+ | type locnamelist '(' class ')'
+ { $$ = $2; }
+ ;
+
+class : GLOBAL { $$ = cGLOBAL; }
+ | LOCAL { $$ = cLOCAL; }
+ ;
+
+type : REAL { $$ = tREAL; }
+ | INTEGER { $$ = tINTEGER; }
+ ;
+
+namelist: namelist NAME
+ { $$->s = mksymbol($<tval>0, $<cval>0, $2);
+ $$->next = $1;
+ }
+ | NAME
+ { $$->s = mksymbol(0, 0, $1);
+ $$->next = NULL;
+ }
+ ;
+
+locnamelist: namelist '(' LOCAL ',' type ')'
+ { $$ = $1; }
+ ;
+%%
+
+extern int YYLEX_DECL();
+extern void YYERROR_DECL();
diff --git a/contrib/byacc/test/btyacc_destroy3.y b/contrib/byacc/test/btyacc_destroy3.y
new file mode 100644
index 0000000..c111273
--- /dev/null
+++ b/contrib/byacc/test/btyacc_destroy3.y
@@ -0,0 +1,94 @@
+%parse-param {
+ struct parser_param *param,
+ int flag
+ }
+
+%{
+#include <stdlib.h>
+
+typedef enum {cGLOBAL, cLOCAL} class;
+typedef enum {tREAL, tINTEGER} type;
+typedef char * name;
+
+struct symbol { class c; type t; name id; };
+typedef struct symbol symbol;
+
+struct namelist { symbol *s; struct namelist *next; };
+typedef struct namelist namelist;
+
+struct parser_param {
+ int *rtrn;
+ symbol ss;
+};
+
+extern symbol *mksymbol(type t, class c, name id);
+
+#ifdef YYBISON
+#define YYLEX_DECL() yylex(void)
+#define YYERROR_DECL() yyerror(const char *s)
+#endif
+%}
+
+%token <cval> GLOBAL LOCAL
+%token <tval> REAL INTEGER
+%token <id> NAME
+
+%type <nlist> declaration
+%type <nlist> locnamelist
+%type <cval> class
+%type <tval> type
+%type <nlist> namelist
+
+%destructor { if (!param->rtrn) close($$); } <file>
+
+%destructor {
+ namelist *p = $$;
+ while (p != NULL)
+ { namelist *pp = p;
+ p = p->next;
+ free(pp->s); free(pp);
+ }
+ } declaration
+
+%union
+{
+ class cval;
+ type tval;
+ namelist * nlist;
+ name id;
+}
+
+%start declaration
+
+%%
+declaration: class type namelist'(' class ',' type ')'
+ { $$ = $3; }
+ | type locnamelist '(' class ')'
+ { $$ = $2; }
+ ;
+
+class : GLOBAL { $$ = cGLOBAL; }
+ | LOCAL { $$ = cLOCAL; }
+ ;
+
+type : REAL { $$ = tREAL; }
+ | INTEGER { $$ = tINTEGER; }
+ ;
+
+namelist: namelist NAME
+ { $$->s = mksymbol($<tval>0, $<cval>0, $2);
+ $$->next = $1;
+ }
+ | NAME
+ { $$->s = mksymbol(0, 0, $1);
+ $$->next = NULL;
+ }
+ ;
+
+locnamelist: namelist '(' LOCAL ',' type ')'
+ { $$ = $1; }
+ ;
+%%
+
+extern int YYLEX_DECL();
+extern void YYERROR_DECL();
diff --git a/contrib/byacc/test/yacc/calc2.tab.c b/contrib/byacc/test/yacc/calc2.tab.c
index d85ea88..dc82b8e 100644
--- a/contrib/byacc/test/yacc/calc2.tab.c
+++ b/contrib/byacc/test/yacc/calc2.tab.c
@@ -126,7 +126,7 @@ typedef int YYSTYPE;
# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
-# define YYPARSE_DECL() yyparse(int regs[26], int * base)
+# define YYPARSE_DECL() yyparse(int regs[26], int *base)
#endif
/* Parameters sent to lex. */
@@ -134,13 +134,13 @@ typedef int YYSTYPE;
# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
# define YYLEX yylex(YYLEX_PARAM)
#else
-# define YYLEX_DECL() yylex(int * base)
+# define YYLEX_DECL() yylex(int *base)
# define YYLEX yylex(base)
#endif
/* Parameters sent to yyerror. */
#ifndef YYERROR_DECL
-#define YYERROR_DECL() yyerror(int regs[26], int * base, const char *s)
+#define YYERROR_DECL() yyerror(int regs[26], int *base, const char *s)
#endif
#ifndef YYERROR_CALL
#define YYERROR_CALL(msg) yyerror(regs, base, msg)
diff --git a/contrib/byacc/test/yacc/calc3.tab.c b/contrib/byacc/test/yacc/calc3.tab.c
index b5ca041..d13bc1a 100644
--- a/contrib/byacc/test/yacc/calc3.tab.c
+++ b/contrib/byacc/test/yacc/calc3.tab.c
@@ -127,7 +127,7 @@ typedef int YYSTYPE;
# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
-# define YYPARSE_DECL() yyparse(int regs[26], int * base)
+# define YYPARSE_DECL() yyparse(int regs[26], int *base)
#endif
/* Parameters sent to lex. */
@@ -139,13 +139,13 @@ typedef int YYSTYPE;
# endif
# define YYLEX yylex(&yylval, YYLEX_PARAM)
#else
-# define YYLEX_DECL() yylex(YYSTYPE *yylval, int * base)
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, int *base)
# define YYLEX yylex(&yylval, base)
#endif
/* Parameters sent to yyerror. */
#ifndef YYERROR_DECL
-#define YYERROR_DECL() yyerror(int regs[26], int * base, const char *s)
+#define YYERROR_DECL() yyerror(int regs[26], int *base, const char *s)
#endif
#ifndef YYERROR_CALL
#define YYERROR_CALL(msg) yyerror(regs, base, msg)
diff --git a/contrib/byacc/test/yacc/ok_syntax1.tab.c b/contrib/byacc/test/yacc/ok_syntax1.tab.c
index 990623e..94d67d9 100644
--- a/contrib/byacc/test/yacc/ok_syntax1.tab.c
+++ b/contrib/byacc/test/yacc/ok_syntax1.tab.c
@@ -135,7 +135,7 @@ typedef union
# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
# endif
#else
-# define YYPARSE_DECL() yyparse(int regs[26], int * base)
+# define YYPARSE_DECL() yyparse(int regs[26], int *base)
#endif
/* Parameters sent to lex. */
@@ -147,13 +147,13 @@ typedef union
# endif
# define YYLEX yylex(&yylval, YYLEX_PARAM)
#else
-# define YYLEX_DECL() yylex(YYSTYPE *yylval, int * base)
+# define YYLEX_DECL() yylex(YYSTYPE *yylval, int *base)
# define YYLEX yylex(&yylval, base)
#endif
/* Parameters sent to yyerror. */
#ifndef YYERROR_DECL
-#define YYERROR_DECL() yyerror(int regs[26], int * base, const char *s)
+#define YYERROR_DECL() yyerror(int regs[26], int *base, const char *s)
#endif
#ifndef YYERROR_CALL
#define YYERROR_CALL(msg) yyerror(regs, base, msg)
diff --git a/contrib/byacc/yacc.1 b/contrib/byacc/yacc.1
index 357426e..8076ab0 100644
--- a/contrib/byacc/yacc.1
+++ b/contrib/byacc/yacc.1
@@ -1,4 +1,4 @@
-.\" $Id: yacc.1,v 1.23 2014/04/09 09:48:50 tom Exp $
+.\" $Id: yacc.1,v 1.24 2014/10/06 00:03:48 tom Exp $
.\"
.\" .TH YACC 1 "July\ 15,\ 1990"
.\" .UC 6
@@ -23,7 +23,7 @@
.de bP
.IP \(bu 4
..
-.TH YACC 1 "January 1, 2014" "Berkeley Yacc" "User Commands"
+.TH YACC 1 "October 5, 2014" "Berkeley Yacc" "User Commands"
.SH NAME
Yacc \- an LALR(1) parser generator
.SH SYNOPSIS
@@ -339,6 +339,23 @@ relying on directives embedded in the grammar file.
.bP
Bison's \*(``\fB\-y\fP\*('' option does not affect bison's lack of support for
features of AT&T yacc which were deemed obsolescent.
+.bP
+\fBYacc\fP accepts multiple parameters with \fB%lex-param\fP and \fB%parse-param\fP
+in two forms
+.ES
+{type1 name1} {type2 name2} ...
+{type1 name1, type2 name2 ...}
+.XE
+.IP
+Bison accepts the latter (though undocumented), but depending on the
+release may generate bad code.
+.bP
+Like bison, \fByacc\fP will add parameters specified via \fB%parse-param\fP
+to \fByyparse\fP, \fByyerror\fP and (if configured for back-tracking)
+to the destructor declared using \fB%destructor\fP.
+Bison puts the additional parameters \fIfirst\fP for
+\fByyparse\fP and \fByyerror\fP but \fIlast\fP for destructors.
+\fBYacc\fP matches this behavior.
.
.SH DIAGNOSTICS
If there are rules that are never reduced, the number of such rules is
diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c
index 6ae46ef..fbf996b 100644
--- a/contrib/libpcap/inet.c
+++ b/contrib/libpcap/inet.c
@@ -737,6 +737,10 @@ pcap_lookupnet(device, netp, maskp, errbuf)
#ifdef PCAP_SUPPORT_USB
|| strstr(device, "usbmon") != NULL
#endif
+#ifdef PCAP_SUPPORT_NETMAP
+ || !strncmp(device, "netmap:", 7)
+ || !strncmp(device, "vale", 4)
+#endif
#ifdef HAVE_SNF_API
|| strstr(device, "snf") != NULL
#endif
diff --git a/contrib/libpcap/pcap.c b/contrib/libpcap/pcap.c
index be884b8..00d44a0 100644
--- a/contrib/libpcap/pcap.c
+++ b/contrib/libpcap/pcap.c
@@ -106,6 +106,10 @@ static const char rcsid[] _U_ =
#include "pcap-netfilter-linux.h"
#endif
+#ifdef PCAP_SUPPORT_NETMAP
+pcap_t* pcap_netmap_create(const char *device, char *ebuf, int *is_ours);
+#endif
+
int
pcap_not_initialized(pcap_t *pcap)
{
@@ -301,6 +305,9 @@ struct capture_source_type {
int (*findalldevs_op)(pcap_if_t **, char *);
pcap_t *(*create_op)(const char *, char *, int *);
} capture_source_types[] = {
+#ifdef PCAP_SUPPORT_NETMAP
+ { NULL, pcap_netmap_create },
+#endif
#ifdef HAVE_DAG_API
{ dag_findalldevs, dag_create },
#endif
diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c
index af34f88..7ca2cfe 100644
--- a/contrib/tcpdump/tcpdump.c
+++ b/contrib/tcpdump/tcpdump.c
@@ -1534,11 +1534,11 @@ main(int argc, char **argv)
static const unsigned long cmds[] = { BIOCGSTATS };
/*
- * the various libpcap devices use a combination of
- * read (bpf), ioctl (bpf, netmap), poll (netmap)
- * so we add the relevant access rights.
+ * The various libpcap devices use a combination of
+ * read (bpf), ioctl (bpf, netmap), poll (netmap).
+ * Grant the relevant access rights, sorted by name.
*/
- cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT);
+ cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ);
if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
errno != ENOSYS) {
error("unable to limit pcap descriptor");
diff --git a/etc/devd/Makefile b/etc/devd/Makefile
index 82a5000..6d1031e 100644
--- a/etc/devd/Makefile
+++ b/etc/devd/Makefile
@@ -11,7 +11,7 @@ FILES+= asus.conf
.endif
.if ${MK_USB} != "no"
-FILES+= uath.conf usb.conf
+FILES+= uath.conf ulpt.conf usb.conf
.endif
.if ${MK_ZFS} != "no"
diff --git a/etc/devd/ulpt.conf b/etc/devd/ulpt.conf
new file mode 100644
index 0000000..2082726
--- /dev/null
+++ b/etc/devd/ulpt.conf
@@ -0,0 +1,18 @@
+#
+# $FreeBSD$
+#
+
+#
+# Example devd configuration file for USB printers.
+# Uncomment the notify rule below to enable.
+#
+# Generic USB printer devices
+#notify 100 {
+# match "system" "USB";
+# match "subsystem" "INTERFACE";
+# match "type" "ATTACH";
+# match "intclass" "0x07";
+# match "intsubclass" "0x01";
+# match "intprotocol" "(0x01|0x02|0x03)";
+# action "chown root:wheel /dev/$cdev";
+#};
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index 3a9d0e0..45c2d7c 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -47,6 +47,8 @@
set-e
..
..
+ sleep
+ ..
test
..
..
@@ -68,6 +70,8 @@
lib
..
usr.bin
+ diff
+ ..
..
..
lib
@@ -143,6 +147,8 @@
usr.bin
apply
..
+ basename
+ ..
bmake
archives
fmt_44bsd
@@ -243,10 +249,20 @@
..
calendar
..
+ cmp
+ ..
comm
..
+ cut
+ ..
+ dirname
+ ..
file2c
..
+ grep
+ ..
+ gzip
+ ..
join
..
jot
@@ -287,6 +303,8 @@
..
newsyslog
..
+ nmtree
+ ..
pw
..
sa
@@ -294,3 +312,5 @@
..
..
..
+
+# vim: set expandtab ts=4 sw=4:
diff --git a/gnu/usr.bin/Makefile b/gnu/usr.bin/Makefile
index 7b1482d..a320191 100644
--- a/gnu/usr.bin/Makefile
+++ b/gnu/usr.bin/Makefile
@@ -18,7 +18,9 @@ SUBDIR= ${_binutils} \
${_texinfo}
.if ${MK_CXX} != "no"
+.if ${MK_GCC} != "no"
_gperf= gperf
+.endif
.if ${MK_GROFF} != "no"
_groff= groff
.endif
diff --git a/gnu/usr.bin/diff/Makefile b/gnu/usr.bin/diff/Makefile
index c5c66dc..6b29df5 100644
--- a/gnu/usr.bin/diff/Makefile
+++ b/gnu/usr.bin/diff/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <src.opts.mk>
+
DIFFSRC=${.CURDIR}/../../../contrib/diff/src
.PATH: ${DIFFSRC} \
${.CURDIR}/../../../contrib/diff/lib \
@@ -27,4 +29,8 @@ SUBDIR+=doc
DPADD= ${LIBGNUREGEX}
LDADD= -lgnuregex
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/diff/tests/Makefile b/gnu/usr.bin/diff/tests/Makefile
new file mode 100644
index 0000000..aa1629d
--- /dev/null
+++ b/gnu/usr.bin/diff/tests/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../../contrib/netbsd-tests/usr.bin/diff
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/gnu/usr.bin/diff
+ATF_TESTS_SH= diff_test
+ATF_TESTS_SH_SED_diff_test= -e 's/t_diff/`basename $$0`/g'
+ATF_TESTS_SH_SRC_diff_test= t_diff.sh
+
+FILESDIR= ${TESTSDIR}
+FILES+= d_mallocv1.in
+FILES+= d_mallocv2.in
+
+.include <bsd.test.mk>
diff --git a/include/rpcsvc/nis.x b/include/rpcsvc/nis.x
index 7a12c85..ee822d0 100644
--- a/include/rpcsvc/nis.x
+++ b/include/rpcsvc/nis.x
@@ -400,10 +400,7 @@ program NIS_PROG {
%#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights)
%#define WORLD_DEFAULT (NIS_READ_ACC)
%#define GROUP_DEFAULT (NIS_READ_ACC << 8)
-%#define OWNER_DEFAULT ((NIS_READ_ACC +\
- NIS_MODIFY_ACC +\
- NIS_CREATE_ACC +\
- NIS_DESTROY_ACC) << 16)
+%#define OWNER_DEFAULT ((NIS_READ_ACC + NIS_MODIFY_ACC + NIS_CREATE_ACC + NIS_DESTROY_ACC) << 16)
%#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT)
%
%/* Result manipulation defines ... */
@@ -432,10 +429,8 @@ program NIS_PROG {
% * these definitions they take an nis_object *, and an int and return
% * a u_char * for Value, and an int for length.
% */
-%#define ENTRY_VAL(obj, col) \
- (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val
-%#define ENTRY_LEN(obj, col) \
- (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len
+%#define ENTRY_VAL(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val
+%#define ENTRY_LEN(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len
%
%#ifdef __cplusplus
%}
diff --git a/include/strings.h b/include/strings.h
index 4fb9311..2210df0 100644
--- a/include/strings.h
+++ b/include/strings.h
@@ -43,6 +43,9 @@ int bcmp(const void *, const void *, size_t) __pure; /* LEGACY */
void bcopy(const void *, void *, size_t); /* LEGACY */
void bzero(void *, size_t); /* LEGACY */
#endif
+#if __BSD_VISIBLE
+void explicit_bzero(void *, size_t);
+#endif
#if __XSI_VISIBLE
int ffs(int) __pure2;
#endif
diff --git a/lib/libc/gen/dl_iterate_phdr.3 b/lib/libc/gen/dl_iterate_phdr.3
index 5b8afc6..6e952dc 100644
--- a/lib/libc/gen/dl_iterate_phdr.3
+++ b/lib/libc/gen/dl_iterate_phdr.3
@@ -15,7 +15,7 @@
.\"
.\" $OpenBSD: dl_iterate_phdr.3,v 1.3 2007/05/31 19:19:48 jmc Exp $
.\" $FreeBSD$
-.Dd February 15, 2012
+.Dd October 9, 2014
.Dt DL_ITERATE_PHDR 3
.Os
.Sh NAME
@@ -68,7 +68,7 @@ have the following meaning:
The base address at which the object is mapped into the address
space of the calling process.
.It Fa dlpi_name
-The name of the ELF object.
+The pathname of the ELF object.
.It Fa dlpi_phdr
A pointer to the object's program headers.
.It Fa dlpi_phnum
diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3
index 27054460..2b50f0e 100644
--- a/lib/libc/stdtime/strptime.3
+++ b/lib/libc/stdtime/strptime.3
@@ -79,7 +79,8 @@ and
.Fa \&%D ,
are now interpreted as beginning at 1969 per POSIX requirements.
Years 69-00 are interpreted in the 20th century (1969-2000), years
-01-68 in the 21st century (2001-2068). The
+01-68 in the 21st century (2001-2068).
+The
.Fa \&%U
and
.Fa %W
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index 8576bdb..2be6358 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -103,9 +103,6 @@ _strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
ptr = fmt;
while (*ptr != 0) {
- if (*buf == 0)
- break;
-
c = *ptr++;
if (c != '%') {
@@ -123,7 +120,6 @@ _strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
label:
c = *ptr++;
switch (c) {
- case 0:
case '%':
if (*buf++ != '%')
return (NULL);
@@ -552,7 +548,8 @@ label:
strncpy(zonestr, buf, cp - buf);
zonestr[cp - buf] = '\0';
tzset();
- if (0 == strcmp(zonestr, "GMT")) {
+ if (0 == strcmp(zonestr, "GMT") ||
+ 0 == strcmp(zonestr, "UTC")) {
*GMTp = 1;
} else if (0 == strcmp(zonestr, tzname[0])) {
tm->tm_isdst = 0;
@@ -599,6 +596,9 @@ label:
while (isspace_l((unsigned char)*buf, locale))
buf++;
break;
+
+ default:
+ return (NULL);
}
}
@@ -674,6 +674,7 @@ strptime_l(const char * __restrict buf, const char * __restrict fmt,
ret = _strptime(buf, fmt, tm, &gmt, loc);
if (ret && gmt) {
time_t t = timegm(tm);
+
localtime_r(&t, tm);
}
diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc
index 731f4fc..385837c 100644
--- a/lib/libc/string/Makefile.inc
+++ b/lib/libc/string/Makefile.inc
@@ -6,7 +6,8 @@
CFLAGS+= -I${LIBC_SRCTOP}/locale
# machine-independent string sources
-MISRCS+=bcmp.c bcopy.c bzero.c ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \
+MISRCS+=bcmp.c bcopy.c bzero.c explicit_bzero.c \
+ ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \
memccpy.c memchr.c memrchr.c memcmp.c \
memcpy.c memmem.c memmove.c memset.c \
stpcpy.c stpncpy.c strcasecmp.c \
@@ -35,6 +36,7 @@ MAN+= bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \
strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 wcscoll.3 wcstok.3 \
wcswidth.3 wcsxfrm.3 wmemchr.3
+MLINKS+=bzero.3 explicit_bzero.3
MLINKS+=ffs.3 ffsl.3 \
ffs.3 ffsll.3 \
ffs.3 fls.3 \
diff --git a/lib/libc/string/Symbol.map b/lib/libc/string/Symbol.map
index 8e80165..5961092 100644
--- a/lib/libc/string/Symbol.map
+++ b/lib/libc/string/Symbol.map
@@ -100,6 +100,10 @@ FBSD_1.3 {
wcwidth_l;
};
+FBSD_1.4 {
+ explicit_bzero;
+};
+
FBSDprivate_1.0 {
__strtok_r;
};
diff --git a/lib/libc/string/bzero.3 b/lib/libc/string/bzero.3
index 029644a..5af1bcf 100644
--- a/lib/libc/string/bzero.3
+++ b/lib/libc/string/bzero.3
@@ -31,11 +31,12 @@
.\" @(#)bzero.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd October 6, 2014
.Dt BZERO 3
.Os
.Sh NAME
-.Nm bzero
+.Nm bzero ,
+.Nm explicit_bzero
.Nd write zeroes to a byte string
.Sh LIBRARY
.Lb libc
@@ -43,6 +44,8 @@
.In strings.h
.Ft void
.Fn bzero "void *b" "size_t len"
+.Ft void
+.Fn explicit_bzero "void *b" "size_t len"
.Sh DESCRIPTION
The
.Fn bzero
@@ -56,6 +59,12 @@ If
is zero,
.Fn bzero
does nothing.
+.Pp
+The
+.Fn explicit_bzero
+variant behaves the same, but will not be removed by a compiler's dead store
+optimization pass, making it useful for clearing sensitive memory such as a
+password.
.Sh SEE ALSO
.Xr memset 3 ,
.Xr swab 3
@@ -72,3 +81,10 @@ before it was moved to
for
.St -p1003.1-2001
compliance.
+.Pp
+The
+.Fn explicit_bzero
+function first appeared in
+.Ox 5.5
+and
+.Fx 11.0 .
diff --git a/lib/libc/string/explicit_bzero.c b/lib/libc/string/explicit_bzero.c
new file mode 100644
index 0000000..a7811b0
--- /dev/null
+++ b/lib/libc/string/explicit_bzero.c
@@ -0,0 +1,22 @@
+/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
+/*
+ * Public domain.
+ * Written by Matthew Dempsky.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+__attribute__((weak)) void
+__explicit_bzero_hook(void *buf, size_t len)
+{
+}
+
+void
+explicit_bzero(void *buf, size_t len)
+{
+ memset(buf, 0, len);
+ __explicit_bzero_hook(buf, len);
+}
diff --git a/lib/libc/sys/accept.2 b/lib/libc/sys/accept.2
index 0363158..7e60ccc 100644
--- a/lib/libc/sys/accept.2
+++ b/lib/libc/sys/accept.2
@@ -28,7 +28,7 @@
.\" @(#)accept.2 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd October 1, 2013
+.Dd October 9, 2014
.Dt ACCEPT 2
.Os
.Sh NAME
@@ -201,7 +201,7 @@ The
.Fa addr
argument is not in a writable part of the
user address space.
-.It Bq Er EWOULDBLOCK
+.It Bo Er EWOULDBLOCK Bc or Bq Er EAGAIN
The socket is marked non-blocking and no connections
are present to be accepted.
.It Bq Er ECONNABORTED
diff --git a/lib/libcrypt/crypt.c b/lib/libcrypt/crypt.c
index c3ca4c2..623809e 100644
--- a/lib/libcrypt/crypt.c
+++ b/lib/libcrypt/crypt.c
@@ -37,24 +37,26 @@ __FBSDID("$FreeBSD$");
#include "crypt.h"
/*
- * List of supported crypt(3) formats. The first element in the list will
- * be the default.
+ * List of supported crypt(3) formats.
+ *
+ * The default algorithm is the last entry in the list (second-to-last
+ * array element since the last is a sentinel). The reason for placing
+ * the default last rather than first is that DES needs to be at the
+ * bottom for the algorithm guessing logic in crypt(3) to work correctly,
+ * and it needs to be the default for backward compatibility.
*/
static const struct crypt_format {
const char *const name;
char *(*const func)(const char *, const char *);
const char *const magic;
} crypt_formats[] = {
- /* default format */
- { "sha512", crypt_sha512, "$6$" },
-
- /* other supported formats */
{ "md5", crypt_md5, "$1$" },
#ifdef HAS_BLOWFISH
{ "blf", crypt_blowfish, "$2" },
#endif
{ "nth", crypt_nthash, "$3$" },
{ "sha256", crypt_sha256, "$5$" },
+ { "sha512", crypt_sha512, "$6$" },
#ifdef HAS_DES
{ "des", crypt_des, "_" },
#endif
@@ -63,7 +65,8 @@ static const struct crypt_format {
{ NULL, NULL, NULL }
};
-static const struct crypt_format *crypt_format = &crypt_formats[0];
+static const struct crypt_format *crypt_format =
+ &crypt_formats[(sizeof crypt_formats / sizeof *crypt_formats) - 2];
#define DES_SALT_ALPHABET \
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
diff --git a/lib/libnv/nvlist.c b/lib/libnv/nvlist.c
index c7c3cb9..b495441 100644
--- a/lib/libnv/nvlist.c
+++ b/lib/libnv/nvlist.c
@@ -698,7 +698,7 @@ nvlist_check_header(struct nvlist_header *nvlhdrp)
const unsigned char *
nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
- int *flagsp, size_t *leftp)
+ bool *isbep, size_t *leftp)
{
struct nvlist_header nvlhdr;
@@ -725,7 +725,8 @@ nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK);
ptr += sizeof(nvlhdr);
- *flagsp = (int)nvlhdr.nvlh_flags;
+ if (isbep != NULL)
+ *isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
*leftp -= sizeof(nvlhdr);
return (ptr);
@@ -741,7 +742,7 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
nvlist_t *nvl, *retnvl, *tmpnvl;
nvpair_t *nvp;
size_t left;
- int flags;
+ bool isbe;
left = size;
ptr = buf;
@@ -751,44 +752,43 @@ nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds)
if (nvl == NULL)
goto failed;
- ptr = nvlist_unpack_header(nvl, ptr, nfds, &flags, &left);
+ ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
if (ptr == NULL)
goto failed;
while (left > 0) {
- ptr = nvpair_unpack(flags, ptr, &left, &nvp);
+ ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
if (ptr == NULL)
goto failed;
switch (nvpair_type(nvp)) {
case NV_TYPE_NULL:
- ptr = nvpair_unpack_null(flags, nvp, ptr, &left);
+ ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
break;
case NV_TYPE_BOOL:
- ptr = nvpair_unpack_bool(flags, nvp, ptr, &left);
+ ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
break;
case NV_TYPE_NUMBER:
- ptr = nvpair_unpack_number(flags, nvp, ptr, &left);
+ ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
break;
case NV_TYPE_STRING:
- ptr = nvpair_unpack_string(flags, nvp, ptr, &left);
+ ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
break;
case NV_TYPE_NVLIST:
- ptr = nvpair_unpack_nvlist(&flags, nvp, ptr, &left,
- nfds, &tmpnvl);
+ ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
+ &tmpnvl);
nvlist_set_parent(tmpnvl, nvp);
break;
case NV_TYPE_DESCRIPTOR:
- ptr = nvpair_unpack_descriptor(flags, nvp, ptr, &left,
+ ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
fds, nfds);
break;
case NV_TYPE_BINARY:
- ptr = nvpair_unpack_binary(flags, nvp, ptr, &left);
+ ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
break;
case NV_TYPE_NVLIST_UP:
if (nvl->nvl_parent == NULL)
goto failed;
nvl = nvpair_nvlist(nvl->nvl_parent);
- flags = nvl->nvl_flags;
continue;
default:
PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
diff --git a/lib/libnv/nvlist_impl.h b/lib/libnv/nvlist_impl.h
index 28894c0..ef32dea 100644
--- a/lib/libnv/nvlist_impl.h
+++ b/lib/libnv/nvlist_impl.h
@@ -42,6 +42,6 @@ nvlist_t *nvlist_xunpack(const void *buf, size_t size, const int *fds,
nvpair_t *nvlist_get_nvpair_parent(const nvlist_t *nvl);
const unsigned char *nvlist_unpack_header(nvlist_t *nvl,
- const unsigned char *ptr, size_t nfds, int *flagsp, size_t *leftp);
+ const unsigned char *ptr, size_t nfds, bool *isbep, size_t *leftp);
#endif /* !_NVLIST_IMPL_H_ */
diff --git a/lib/libnv/nvpair.c b/lib/libnv/nvpair.c
index 8ff8538..4f0bd72 100644
--- a/lib/libnv/nvpair.c
+++ b/lib/libnv/nvpair.c
@@ -389,7 +389,7 @@ nvpair_init_datasize(nvpair_t *nvp)
}
const unsigned char *
-nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
+nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp)
{
struct nvpair_header nvphdr;
@@ -411,12 +411,12 @@ nvpair_unpack_header(int flags, nvpair_t *nvp, const unsigned char *ptr,
}
#if BYTE_ORDER == BIG_ENDIAN
- if ((flags & NV_FLAG_BIG_ENDIAN) == 0) {
+ if (!isbe) {
nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
}
#else
- if ((flags & NV_FLAG_BIG_ENDIAN) != 0) {
+ if (isbe) {
nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
}
@@ -451,7 +451,7 @@ failed:
}
const unsigned char *
-nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
+nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp __unused)
{
@@ -466,7 +466,7 @@ nvpair_unpack_null(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
}
const unsigned char *
-nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
+nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp)
{
uint8_t value;
@@ -497,7 +497,7 @@ nvpair_unpack_bool(int flags __unused, nvpair_t *nvp, const unsigned char *ptr,
}
const unsigned char *
-nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
+nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp)
{
@@ -512,7 +512,7 @@ nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
return (NULL);
}
- if ((flags & NV_FLAG_BIG_ENDIAN) != 0)
+ if (isbe)
nvp->nvp_data = be64dec(ptr);
else
nvp->nvp_data = le64dec(ptr);
@@ -523,7 +523,7 @@ nvpair_unpack_number(int flags, nvpair_t *nvp, const unsigned char *ptr,
}
const unsigned char *
-nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
+nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp)
{
@@ -551,8 +551,8 @@ nvpair_unpack_string(int flags __unused, nvpair_t *nvp,
}
const unsigned char *
-nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp, const unsigned char *ptr,
- size_t *leftp, size_t nfds, nvlist_t **child)
+nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
+ const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
{
nvlist_t *value;
@@ -567,7 +567,7 @@ nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp, const unsigned char *ptr,
if (value == NULL)
return (NULL);
- ptr = nvlist_unpack_header(value, ptr, nfds, flagsp, leftp);
+ ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
if (ptr == NULL)
return (NULL);
@@ -578,7 +578,7 @@ nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp, const unsigned char *ptr,
}
const unsigned char *
-nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
+nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
size_t *leftp, const int *fds, size_t nfds)
{
int64_t idx;
@@ -594,7 +594,7 @@ nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
return (NULL);
}
- if ((flags & NV_FLAG_BIG_ENDIAN) != 0)
+ if (isbe)
idx = be64dec(ptr);
else
idx = le64dec(ptr);
@@ -618,7 +618,7 @@ nvpair_unpack_descriptor(int flags, nvpair_t *nvp, const unsigned char *ptr,
}
const unsigned char *
-nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
+nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp)
{
void *value;
@@ -644,7 +644,7 @@ nvpair_unpack_binary(int flags __unused, nvpair_t *nvp,
}
const unsigned char *
-nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
+nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
nvpair_t **nvpp)
{
nvpair_t *nvp, *tmp;
@@ -654,7 +654,7 @@ nvpair_unpack(int flags, const unsigned char *ptr, size_t *leftp,
return (NULL);
nvp->nvp_name = (char *)(nvp + 1);
- ptr = nvpair_unpack_header(flags, nvp, ptr, leftp);
+ ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
if (ptr == NULL)
goto failed;
tmp = realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
diff --git a/lib/libnv/nvpair_impl.h b/lib/libnv/nvpair_impl.h
index 70dbbc0..a72000b 100644
--- a/lib/libnv/nvpair_impl.h
+++ b/lib/libnv/nvpair_impl.h
@@ -48,7 +48,7 @@ void nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl);
void nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl);
size_t nvpair_header_size(void);
size_t nvpair_size(const nvpair_t *nvp);
-const unsigned char *nvpair_unpack(int flags, const unsigned char *ptr,
+const unsigned char *nvpair_unpack(bool isbe, const unsigned char *ptr,
size_t *leftp, nvpair_t **nvpp);
void nvpair_free_structure(nvpair_t *nvp);
void nvpair_init_datasize(nvpair_t *nvp);
@@ -72,21 +72,21 @@ unsigned char *nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr,
unsigned char *nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp);
/* Unpack data functions. */
-const unsigned char *nvpair_unpack_header(int flags, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_header(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp);
-const unsigned char *nvpair_unpack_null(int flags, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_null(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp);
-const unsigned char *nvpair_unpack_bool(int flags, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_bool(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp);
-const unsigned char *nvpair_unpack_number(int flags, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_number(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp);
-const unsigned char *nvpair_unpack_string(int flags, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_string(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp);
-const unsigned char *nvpair_unpack_nvlist(int *flagsp, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_nvlist(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp, size_t nvlist, nvlist_t **child);
-const unsigned char *nvpair_unpack_descriptor(int flags, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp, const int *fds, size_t nfds);
-const unsigned char *nvpair_unpack_binary(int flags, nvpair_t *nvp,
+const unsigned char *nvpair_unpack_binary(bool isbe, nvpair_t *nvp,
const unsigned char *ptr, size_t *leftp);
#endif /* !_NVPAIR_IMPL_H_ */
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
index 8cae1f1..11d7f73 100644
--- a/lib/libpcap/Makefile
+++ b/lib/libpcap/Makefile
@@ -7,6 +7,7 @@ SHLIBDIR?= /lib
LIB= pcap
SRCS= grammar.y tokdefs.h version.h pcap-bpf.c \
+ pcap-netmap.c \
pcap.c pcap-common.c inet.c fad-getad.c gencode.c optimize.c nametoaddr.c \
etherent.c savefile.c bpf_filter.c bpf_image.c bpf_dump.c \
scanner.l sf-pcap.c sf-pcap-ng.c version.c
diff --git a/lib/libpcap/config.h b/lib/libpcap/config.h
index 79cb3d2..60cb448 100644
--- a/lib/libpcap/config.h
+++ b/lib/libpcap/config.h
@@ -271,6 +271,9 @@
/* target host supports USB sniffing */
/* #undef PCAP_SUPPORT_USB */
+/* target host supports netmap */
+#define PCAP_SUPPORT_NETMAP 1
+
/* include ACN support */
/* #undef SITA */
diff --git a/lib/libpcap/pcap-netmap.c b/lib/libpcap/pcap-netmap.c
new file mode 100644
index 0000000..309cf63
--- /dev/null
+++ b/lib/libpcap/pcap-netmap.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2014 Luigi Rizzo. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <poll.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+#include "pcap-int.h"
+
+/*
+ * $FreeBSD$
+ *
+ * This code is meant to build also on other versions of libpcap.
+ *
+ * older libpcap miss p->priv, use p->md.device instead (and allocate).
+ * Also opt.timeout was in md.timeout before.
+ * Use #define PCAP_IF_UP to discriminate
+ */
+#ifdef PCAP_IF_UP
+#define NM_PRIV(p) ((struct pcap_netmap *)(p->priv))
+#define the_timeout opt.timeout
+#else
+#define HAVE_NO_PRIV
+#define NM_PRIV(p) ((struct pcap_netmap *)(p->md.device))
+#define SET_PRIV(p, x) p->md.device = (void *)x
+#define the_timeout md.timeout
+#endif
+
+#if defined (linux)
+/* On FreeBSD we use IFF_PPROMISC which is in ifr_flagshigh.
+ * remap to IFF_PROMISC on linux
+ */
+#define IFF_PPROMISC IFF_PROMISC
+#endif /* linux */
+
+struct pcap_netmap {
+ struct nm_desc *d; /* pointer returned by nm_open() */
+ pcap_handler cb; /* callback and argument */
+ u_char *cb_arg;
+ int must_clear_promisc; /* flag */
+ uint64_t rx_pkts; /* # of pkts received before the filter */
+};
+
+
+static int
+pcap_netmap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+
+ ps->ps_recv = pn->rx_pkts;
+ ps->ps_drop = 0;
+ ps->ps_ifdrop = 0;
+ return 0;
+}
+
+
+static void
+pcap_netmap_filter(u_char *arg, struct pcap_pkthdr *h, const u_char *buf)
+{
+ pcap_t *p = (pcap_t *)arg;
+ struct pcap_netmap *pn = NM_PRIV(p);
+ const struct bpf_insn *pc = p->fcode.bf_insns;
+
+ ++pn->rx_pkts;
+ if (pc == NULL || bpf_filter(pc, buf, h->len, h->caplen))
+ pn->cb(pn->cb_arg, h, buf);
+}
+
+
+static int
+pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user)
+{
+ int ret;
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = pn->d;
+ struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 };
+
+ pn->cb = cb;
+ pn->cb_arg = user;
+
+ for (;;) {
+ if (p->break_loop) {
+ p->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ /* nm_dispatch won't run forever */
+
+ ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p);
+ if (ret != 0)
+ break;
+ errno = 0;
+ ret = poll(&pfd, 1, p->the_timeout);
+ }
+ return ret;
+}
+
+
+/* XXX need to check the NIOCTXSYNC/poll */
+static int
+pcap_netmap_inject(pcap_t *p, const void *buf, size_t size)
+{
+ struct nm_desc *d = NM_PRIV(p)->d;
+
+ return nm_inject(d, buf, size);
+}
+
+
+static int
+pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = pn->d;
+ struct ifreq ifr;
+ int error, fd = d->fd;
+
+#ifdef linux
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ fprintf(stderr, "Error: cannot get device control socket.\n");
+ return -1;
+ }
+#endif /* linux */
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
+ switch (what) {
+ case SIOCSIFFLAGS:
+ ifr.ifr_flags = *if_flags;
+#ifdef __FreeBSD__
+ ifr.ifr_flagshigh = *if_flags >> 16;
+#endif /* __FreeBSD__ */
+ break;
+ }
+ error = ioctl(fd, what, &ifr);
+ if (!error) {
+ switch (what) {
+ case SIOCGIFFLAGS:
+ *if_flags = ifr.ifr_flags;
+#ifdef __FreeBSD__
+ *if_flags |= (ifr.ifr_flagshigh << 16);
+#endif /* __FreeBSD__ */
+ }
+ }
+#ifdef linux
+ close(fd);
+#endif /* linux */
+ return error ? -1 : 0;
+}
+
+
+static void
+pcap_netmap_close(pcap_t *p)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = pn->d;
+ uint32_t if_flags = 0;
+
+ if (pn->must_clear_promisc) {
+ pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+ if (if_flags & IFF_PPROMISC) {
+ if_flags &= ~IFF_PPROMISC;
+ pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+ }
+ }
+ nm_close(d);
+#ifdef HAVE_NO_PRIV
+ free(pn);
+ SET_PRIV(p, NULL); // unnecessary
+#endif
+ pcap_cleanup_live_common(p);
+}
+
+
+static int
+pcap_netmap_activate(pcap_t *p)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = nm_open(p->opt.source, NULL, 0, NULL);
+ uint32_t if_flags = 0;
+
+ if (d == NULL) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "netmap open: cannot access %s: %s\n",
+ p->opt.source, pcap_strerror(errno));
+#ifdef HAVE_NO_PRIV
+ free(pn);
+ SET_PRIV(p, NULL); // unnecessary
+#endif
+ pcap_cleanup_live_common(p);
+ return (PCAP_ERROR);
+ }
+ if (0)
+ fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
+ __FUNCTION__, p->opt.source, d, d->fd,
+ d->first_rx_ring, d->last_rx_ring);
+ pn->d = d;
+ p->fd = d->fd;
+ if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) {
+ pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+ if (!(if_flags & IFF_PPROMISC)) {
+ pn->must_clear_promisc = 1;
+ if_flags |= IFF_PPROMISC;
+ pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+ }
+ }
+ p->linktype = DLT_EN10MB;
+ p->selectable_fd = p->fd;
+ p->read_op = pcap_netmap_dispatch;
+ p->inject_op = pcap_netmap_inject,
+ p->setfilter_op = install_bpf_program;
+ p->setdirection_op = NULL;
+ p->set_datalink_op = NULL;
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_netmap_stats;
+ p->cleanup_op = pcap_netmap_close;
+
+ return (0);
+}
+
+
+pcap_t *
+pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *p;
+
+ *is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
+ if (! *is_ours)
+ return NULL;
+#ifdef HAVE_NO_PRIV
+ {
+ void *pn = calloc(1, sizeof(struct pcap_netmap));
+ if (pn == NULL)
+ return NULL;
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL) {
+ free(pn);
+ return NULL;
+ }
+ SET_PRIV(p, pn);
+ }
+#else
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_netmap));
+ if (p == NULL)
+ return (NULL);
+#endif
+ p->activate_op = pcap_netmap_activate;
+ return (p);
+}
diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile
index d665dc4..8a0f4b2 100644
--- a/lib/libproc/Makefile
+++ b/lib/libproc/Makefile
@@ -25,7 +25,18 @@ LDADD+= -lsupc++
DPADD+= ${LIBSTDCPLUSPLUS}
.endif
-SHLIB_MAJOR= 2
+.if ${MK_CDDL} != "no"
+LDADD+= -lctf
+DPADD+= ${LIBCTF}
+IGNORE_PRAGMA= YES
+CFLAGS+= -I${.CURDIR}/../../cddl/contrib/opensolaris/lib/libctf/common \
+ -I${.CURDIR}/../../sys/cddl/contrib/opensolaris/uts/common \
+ -I${.CURDIR}/../../sys/cddl/compat/opensolaris
+.else
+CFLAGS+= -DNO_CTF
+.endif
+
+SHLIB_MAJOR= 3
MAN=
diff --git a/lib/libproc/libproc.h b/lib/libproc/libproc.h
index be77e4b..5d81c2b 100644
--- a/lib/libproc/libproc.h
+++ b/lib/libproc/libproc.h
@@ -37,6 +37,7 @@
#include <rtld_db.h>
#include <limits.h>
+struct ctf_file;
struct proc_handle;
typedef void (*proc_child_func)(void *);
@@ -67,6 +68,11 @@ typedef struct prmap {
#define MA_NOCOREDUMP 0x20
} prmap_t;
+typedef struct prsyminfo {
+ u_int prs_lmid; /* Map id. */
+ u_int prs_id; /* Symbol id. */
+} prsyminfo_t;
+
typedef int proc_map_f(void *, const prmap_t *, const char *);
typedef int proc_sym_f(void *, const GElf_Sym *, const char *);
@@ -125,7 +131,9 @@ int proc_create(const char *, char * const *, proc_child_func *, void *,
struct proc_handle **);
int proc_detach(struct proc_handle *, int);
int proc_getflags(struct proc_handle *);
-int proc_name2sym(struct proc_handle *, const char *, const char *, GElf_Sym *);
+int proc_name2sym(struct proc_handle *, const char *, const char *,
+ GElf_Sym *, prsyminfo_t *);
+struct ctf_file *proc_name2ctf(struct proc_handle *, const char *);
int proc_setflags(struct proc_handle *, int);
int proc_state(struct proc_handle *);
pid_t proc_getpid(struct proc_handle *);
@@ -133,8 +141,7 @@ int proc_wstatus(struct proc_handle *);
int proc_getwstat(struct proc_handle *);
char * proc_signame(int, char *, size_t);
int proc_read(struct proc_handle *, void *, size_t, size_t);
-const lwpstatus_t *
- proc_getlwpstatus(struct proc_handle *);
+const lwpstatus_t *proc_getlwpstatus(struct proc_handle *);
void proc_free(struct proc_handle *);
rd_agent_t *proc_rdagent(struct proc_handle *);
void proc_updatesyms(struct proc_handle *);
diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c
index f5301e6..766ff73 100644
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -32,6 +32,10 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#ifndef NO_CTF
+#include <sys/ctf.h>
+#include <sys/ctf_api.h>
+#endif
#include <sys/user.h>
#include <assert.h>
@@ -42,10 +46,17 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#ifndef NO_CTF
+#include <libctf.h>
+#endif
#include <libutil.h>
#include "_libproc.h"
+#ifdef NO_CTF
+typedef struct ctf_file ctf_file_t;
+#endif
+
#ifndef NO_CXA_DEMANGLE
extern char *__cxa_demangle(const char *, char *, size_t *, int *);
#endif /* NO_CXA_DEMANGLE */
@@ -389,7 +400,7 @@ proc_name2map(struct proc_handle *p, const char *name)
*/
static int
lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
- GElf_Sym *symcopy)
+ GElf_Sym *symcopy, prsyminfo_t *si)
{
GElf_Sym sym;
Elf_Data *data;
@@ -404,6 +415,8 @@ lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
s = elf_strptr(e, stridx, sym.st_name);
if (s != NULL && strcmp(s, symbol) == 0) {
memcpy(symcopy, &sym, sizeof(*symcopy));
+ if (si != NULL)
+ si->prs_id = i;
return (0);
}
}
@@ -412,7 +425,7 @@ lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
int
proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
- GElf_Sym *symcopy)
+ GElf_Sym *symcopy, prsyminfo_t *si)
{
Elf *e;
Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
@@ -462,11 +475,11 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
* First look up the symbol in the dynsymtab, and fall back to the
* symtab if the lookup fails.
*/
- error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy);
+ error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy, si);
if (error == 0)
goto out;
- error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy);
+ error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy, si);
if (error == 0)
goto out;
@@ -484,6 +497,24 @@ err0:
return (error);
}
+ctf_file_t *
+proc_name2ctf(struct proc_handle *p, const char *name)
+{
+#ifndef NO_CTF
+ prmap_t *map;
+ int error;
+
+ if ((map = proc_name2map(p, name)) == NULL)
+ return (NULL);
+
+ return (ctf_open(map->pr_mapname, &error));
+#else
+ (void)p;
+ (void)name;
+ return (NULL);
+#endif
+}
+
int
proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
int mask, proc_sym_f *func, void *cd)
diff --git a/lib/libproc/tests/proc_test.c b/lib/libproc/tests/proc_test.c
index 60f1f04..0242b5b 100644
--- a/lib/libproc/tests/proc_test.c
+++ b/lib/libproc/tests/proc_test.c
@@ -227,6 +227,7 @@ ATF_TC_HEAD(map_alias_name2sym, tc)
ATF_TC_BODY(map_alias_name2sym, tc)
{
GElf_Sym sym1, sym2;
+ prsyminfo_t si1, si2;
struct proc_handle *phdl;
int error;
@@ -239,14 +240,15 @@ ATF_TC_BODY(map_alias_name2sym, tc)
* Make sure that "target_prog:main" and "a.out:main" return the same
* symbol.
*/
- error = proc_name2sym(phdl, target_prog_file, "main", &sym1);
+ error = proc_name2sym(phdl, target_prog_file, "main", &sym1, &si1);
ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
target_prog_file);
- error = proc_name2sym(phdl, aout_object, "main", &sym2);
+ error = proc_name2sym(phdl, aout_object, "main", &sym2, &si2);
ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
aout_object);
ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0);
+ ATF_CHECK_EQ(si1.prs_id, si2.prs_id);
ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
@@ -271,11 +273,11 @@ ATF_TC_BODY(symbol_lookup, tc)
phdl = start_prog(tc, false);
- error = proc_name2sym(phdl, target_prog_file, "main", &main_sym);
+ error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL);
ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'");
error = proc_name2sym(phdl, ldelf_object, "r_debug_state",
- &r_debug_state_sym);
+ &r_debug_state_sym, NULL);
ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'");
set_bkpt(phdl, r_debug_state_sym.st_value, &saved);
diff --git a/lib/librtld_db/rtld_db.c b/lib/librtld_db/rtld_db.c
index 2d1f6e6..cd4377e 100644
--- a/lib/librtld_db/rtld_db.c
+++ b/lib/librtld_db/rtld_db.c
@@ -237,14 +237,14 @@ rd_reset(rd_agent_t *rdap)
GElf_Sym sym;
if (proc_name2sym(rdap->rda_php, "ld-elf.so.1", "r_debug_state",
- &sym) < 0)
+ &sym, NULL) < 0)
return (RD_ERR);
DPRINTF("found r_debug_state at 0x%lx\n", (unsigned long)sym.st_value);
rdap->rda_preinit_addr = sym.st_value;
rdap->rda_dlactivity_addr = sym.st_value;
if (proc_name2sym(rdap->rda_php, "ld-elf.so.1", "_r_debug_postinit",
- &sym) < 0)
+ &sym, NULL) < 0)
return (RD_ERR);
DPRINTF("found _r_debug_postinit at 0x%lx\n",
(unsigned long)sym.st_value);
diff --git a/lib/msun/ld128/e_lgammal_r.c b/lib/msun/ld128/e_lgammal_r.c
index 13f8f75..53d3af1 100644
--- a/lib/msun/ld128/e_lgammal_r.c
+++ b/lib/msun/ld128/e_lgammal_r.c
@@ -206,13 +206,13 @@ sin_pil(long double x)
n--;
}
n &= 7;
- y = y - z + n * 0.25L;
+ y = y - z + n * 0.25;
switch (n) {
case 0: y = __kernel_sinl(pi*y,zero,0); break;
case 1:
case 2: y = __kernel_cosl(pi*(0.5-y),zero); break;
- case 3:
+ case 3:
case 4: y = __kernel_sinl(pi*(one-y),zero,0); break;
case 5:
case 6: y = -__kernel_cosl(pi*(y-1.5),zero); break;
@@ -221,41 +221,33 @@ sin_pil(long double x)
return -y;
}
-
long double
lgammal_r(long double x, int *signgamp)
{
long double nadj,p,p1,p2,p3,q,r,t,w,y,z;
uint64_t llx,lx;
int i;
- uint16_t hx;
+ uint16_t hx,ix;
- EXTRACT_LDBL128_WORDS(hx, lx, llx, x);
-
- if((hx & 0x7fff) == 0x7fff) { /* erfl(nan)=nan */
- i = (hx>>15)<<1;
- return (1-i)+one/x; /* erfl(+-inf)=+-1 */
- }
+ EXTRACT_LDBL128_WORDS(hx,lx,llx,x);
- /* purge off +-inf, NaN, +-0, tiny and negative arguments */
+ /* purge +-Inf and NaNs */
*signgamp = 1;
- if((hx & 0x7fff) == 0x7fff) /* x is +-Inf or NaN */
- return x*x;
- if((hx==0||hx==0x8000)&&lx==0) {
- if (hx&0x8000)
- *signgamp = -1;
- return one/vzero;
- }
+ ix = hx&0x7fff;
+ if(ix==0x7fff) return x*x;
- /* purge off tiny and negative arguments */
- if(fabsl(x)<0x1p-119L) {
- if(hx&0x8000) {
- *signgamp = -1;
- return -logl(-x);
- } else return -logl(x);
+ /* purge +-0 and tiny arguments */
+ *signgamp = 1-2*(hx>>15);
+ if(ix<0x3fff-116) { /* |x|<2**-(p+3), return -log(|x|) */
+ if((ix|lx|llx)==0)
+ return one/vzero;
+ return -logl(fabsl(x));
}
+
+ /* purge negative integers and start evaluation for other x < 0 */
if(hx&0x8000) {
- if(fabsl(x)>=0x1p112)
+ *signgamp = 1;
+ if(ix>=0x3fff+112) /* |x|>=2**(p-1), must be -integer */
return one/vzero;
t = sin_pil(x);
if(t==zero) return one/vzero;
@@ -264,17 +256,19 @@ lgammal_r(long double x, int *signgamp)
x = -x;
}
- if(x == 1 || x ==2) r = 0;
- else if(x<2) {
- if(x<=0.8999996185302734) {
+ /* purge 1 and 2 */
+ if((ix==0x3fff || ix==0x4000) && (lx|llx)==0) r = 0;
+ /* for x < 2.0 */
+ else if(ix<0x4000) {
+ if(x<=8.9999961853027344e-01) {
r = -logl(x);
- if(x>=0.7315998077392578) {y = 1-x; i= 0;}
- else if(x>=0.2316399812698364) {y= x-(tc-1); i=1;}
+ if(x>=7.3159980773925781e-01) {y = 1-x; i= 0;}
+ else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;}
else {y = x; i=2;}
} else {
- r = 0;
- if(x>=1.7316312789916992) {y=2-x;i=0;}
- else if(x>=1.2316322326660156) {y=x-tc;i=1;}
+ r = 0;
+ if(x>=1.7316312789916992e+00) {y=2-x;i=0;}
+ else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;}
else {y=x-1;i=2;}
}
switch(i) {
@@ -285,23 +279,24 @@ lgammal_r(long double x, int *signgamp)
p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*(a13+z*(a15+
z*(a17+z*(a19+z*(a21+z*a23)))))))))));
p = y*p1+p2;
- r += (p-y/2); break;
+ r += p-y/2; break;
case 1:
p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+
y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+
y*(t17+y*(t18+y*(t19+y*(t20+y*(t21+y*(t22+y*(t23+
y*(t24+y*(t25+y*(t26+y*(t27+y*(t28+y*(t29+y*(t30+
y*(t31+y*t32))))))))))))))))))))))))))))));
- r += (tf + p); break;
+ r += tf + p; break;
case 2:
p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*(u6+y*(u7+
y*(u8+y*(u9+y*u10))))))))));
p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*(v6+y*(v7+
y*(v8+y*(v9+y*(v10+y*v11))))))))));
- r += (-y/2 + p1/p2);
+ r += p1/p2-y/2;
}
}
- else if(x<8) {
+ /* x < 8.0 */
+ else if(ix<0x4002) {
i = x;
y = x-i;
p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*(s6+y*(s7+y*(s8+
@@ -318,7 +313,8 @@ lgammal_r(long double x, int *signgamp)
case 3: z *= (y+2); /* FALLTHRU */
r += logl(z); break;
}
- } else if (x < 0x1p119L) {
+ /* 8.0 <= x < 2**(p+3) */
+ } else if (ix<0x3fff+116) {
t = logl(x);
z = one/x;
y = z*z;
@@ -326,6 +322,7 @@ lgammal_r(long double x, int *signgamp)
y*(w9+y*(w10+y*(w11+y*(w12+y*(w13+y*(w14+y*(w15+y*(w16+
y*(w17+y*w18)))))))))))))))));
r = (x-half)*(t-one)+w;
+ /* 2**(p+3) <= x <= inf */
} else
r = x*(logl(x)-1);
if(hx&0x8000) r = nadj - r;
diff --git a/lib/msun/ld80/e_lgammal_r.c b/lib/msun/ld80/e_lgammal_r.c
index 621b04e..1e65769 100644
--- a/lib/msun/ld80/e_lgammal_r.c
+++ b/lib/msun/ld80/e_lgammal_r.c
@@ -14,12 +14,11 @@
__FBSDID("$FreeBSD$");
/*
- * See s_lgamma_r.c for complete comments.
+ * See e_lgamma_r.c for complete comments.
*
* Converted to long double by Steven G. Kargl.
*/
-#include <float.h>
#ifdef __i386__
#include <ieeefp.h>
#endif
@@ -219,8 +218,8 @@ sin_pil(long double x)
y = -x;
- vz = y+0x1p63L;
- z = vz-0x1p63L;
+ vz = y+0x1p63;
+ z = vz-0x1p63;
if (z == y)
return zero;
@@ -243,7 +242,7 @@ sin_pil(long double x)
case 5:
case 6: y = -__kernel_cosl(pi*(y-1.5),zero); break;
default: y = __kernel_sinl(pi*(y-2.0),zero,0); break;
- }
+ }
return -y;
}
@@ -253,31 +252,29 @@ lgammal_r(long double x, int *signgamp)
long double nadj,p,p1,p2,p3,q,r,t,w,y,z;
uint64_t lx;
int i;
- uint16_t hx;
+ uint16_t hx,ix;
EXTRACT_LDBL80_WORDS(hx,lx,x);
- /* purge off +-inf, NaN, +-0 */
+ /* purge +-Inf and NaNs */
*signgamp = 1;
- if((hx & 0x7fff) == 0x7fff) /* x is +-Inf or NaN */
- return x*x;
- if((hx==0||hx==0x8000)&&lx==0) {
- if (hx&0x8000)
- *signgamp = -1;
- return one/vzero;
- }
+ ix = hx&0x7fff;
+ if(ix==0x7fff) return x*x;
ENTERI();
- /* purge off tiny and negative arguments */
- if(fabsl(x)<0x1p-70L) { /* |x|<2**-70, return -log(|x|) */
- if(hx&0x8000) {
- *signgamp = -1;
- RETURNI(-logl(-x));
- } else RETURNI(-logl(x));
+ /* purge +-0 and tiny arguments */
+ *signgamp = 1-2*(hx>>15);
+ if(ix<0x3fff-67) { /* |x|<2**-(p+3), return -log(|x|) */
+ if((ix|lx)==0)
+ RETURNI(one/vzero);
+ RETURNI(-logl(fabsl(x)));
}
+
+ /* purge negative integers and start evaluation for other x < 0 */
if(hx&0x8000) {
- if(fabsl(x)>=0x1p63) /* |x|>=2**(p-1), must be -integer */
+ *signgamp = 1;
+ if(ix>=0x3fff+63) /* |x|>=2**(p-1), must be -integer */
RETURNI(one/vzero);
t = sin_pil(x);
if(t==zero) RETURNI(one/vzero); /* -integer */
@@ -286,19 +283,30 @@ lgammal_r(long double x, int *signgamp)
x = -x;
}
- /* purge off 1 and 2 */
- if(x == 1 || x == 2) r = 0;
+ /* purge 1 and 2 */
+ if((ix==0x3fff || ix==0x4000) && lx==0x8000000000000000ULL) r = 0;
/* for x < 2.0 */
- else if(x<2) {
- if(x<=0.8999996185302734) { /* lgamma(x) = lgamma(x+1)-log(x) */
- r = - logl(x);
- if(x>=0.7315998077392578) {y = 1-x; i= 0;}
- else if(x>=0.2316399812698364) {y= x-(tc-1); i=1;}
- else {y = x; i=2;}
+ else if(ix<0x4000) {
+ /*
+ * XXX Supposedly, one can use the following information to replace the
+ * XXX FP rational expressions. A similar approach is appropriate
+ * XXX for ld128, but one (may need?) needs to consider llx, too.
+ *
+ * 8.9999961853027344e-01 3ffe e666600000000000
+ * 7.3159980773925781e-01 3ffe bb4a200000000000
+ * 2.3163998126983643e-01 3ffc ed33080000000000
+ * 1.7316312789916992e+00 3fff dda6180000000000
+ * 1.2316322326660156e+00 3fff 9da6200000000000
+ */
+ if(x<8.9999961853027344e-01) {
+ r = -logl(x);
+ if(x>=7.3159980773925781e-01) {y = 1-x; i= 0;}
+ else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;}
+ else {y = x; i=2;}
} else {
r = 0;
- if(x>=1.7316312789916992) {y=2-x;i=0;}
- else if(x>=1.2316322326660156) {y=x-tc;i=1;}
+ if(x>=1.7316312789916992e+00) {y=2-x;i=0;}
+ else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;}
else {y=x-1;i=2;}
}
switch(i) {
@@ -307,19 +315,20 @@ lgammal_r(long double x, int *signgamp)
p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*(a10+z*a12)))));
p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*a13))))));
p = y*p1+p2;
- r += (p-y/2); break;
+ r += p-y/2; break;
case 1:
p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+
y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+
y*(t17+y*t18))))))))))))))));
- r += (tf + p); break;
+ r += tf + p; break;
case 2:
p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*u6))))));
p2 = 1+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*v6)))));
- r += (-y/2 + p1/p2);
+ r += p1/p2-y/2;
}
}
- else if(x<8) {
+ /* x < 8.0 */
+ else if(ix<0x4002) {
i = x;
y = x-i;
p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
@@ -334,15 +343,15 @@ lgammal_r(long double x, int *signgamp)
case 3: z *= (y+2); /* FALLTHRU */
r += logl(z); break;
}
- /* 8.0 <= x < 2**70 */
- } else if (x < 0x1p70L) {
+ /* 8.0 <= x < 2**(p+3) */
+ } else if (ix<0x3fff+67) {
t = logl(x);
z = one/x;
y = z*z;
w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*(w6+y*(w7+y*w8)))))));
r = (x-half)*(t-one)+w;
+ /* 2**(p+3) <= x <= inf */
} else
- /* 2**70 <= x <= inf */
r = x*(logl(x)-1);
if(hx&0x8000) r = nadj - r;
RETURNI(r);
diff --git a/lib/msun/src/e_lgamma_r.c b/lib/msun/src/e_lgamma_r.c
index a0bd310..be70767 100644
--- a/lib/msun/src/e_lgamma_r.c
+++ b/lib/msun/src/e_lgamma_r.c
@@ -201,28 +201,28 @@ sin_pi(double x)
double
__ieee754_lgamma_r(double x, int *signgamp)
{
- double t,y,z,nadj,p,p1,p2,p3,q,r,w;
+ double nadj,p,p1,p2,p3,q,r,t,w,y,z;
int32_t hx;
int i,ix,lx;
EXTRACT_WORDS(hx,lx,x);
- /* purge off +-inf, NaN, +-0, tiny and negative arguments */
+ /* purge +-Inf and NaNs */
*signgamp = 1;
ix = hx&0x7fffffff;
if(ix>=0x7ff00000) return x*x;
- if((ix|lx)==0) {
- if(hx<0)
- *signgamp = -1;
- return one/vzero;
- }
- if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */
- if(hx<0) {
- *signgamp = -1;
- return -__ieee754_log(-x);
- } else return -__ieee754_log(x);
+
+ /* purge +-0 and tiny arguments */
+ *signgamp = 1-2*((uint32_t)hx>>31);
+ if(ix<0x3c700000) { /* |x|<2**-56, return -log(|x|) */
+ if((ix|lx)==0)
+ return one/vzero;
+ return -__ieee754_log(fabs(x));
}
+
+ /* purge negative integers and start evaluation for other x < 0 */
if(hx<0) {
+ *signgamp = 1;
if(ix>=0x43300000) /* |x|>=2**52, must be -integer */
return one/vzero;
t = sin_pi(x);
@@ -232,7 +232,7 @@ __ieee754_lgamma_r(double x, int *signgamp)
x = -x;
}
- /* purge off 1 and 2 */
+ /* purge 1 and 2 */
if((((ix-0x3ff00000)|lx)==0)||(((ix-0x40000000)|lx)==0)) r = 0;
/* for x < 2.0 */
else if(ix<0x40000000) {
@@ -253,7 +253,7 @@ __ieee754_lgamma_r(double x, int *signgamp)
p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
p = y*p1+p2;
- r += (p-y/2); break;
+ r += p-y/2; break;
case 1:
z = y*y;
w = z*y;
@@ -261,19 +261,20 @@ __ieee754_lgamma_r(double x, int *signgamp)
p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
p = z*p1-(tt-w*(p2+y*p3));
- r += (tf + p); break;
+ r += tf + p; break;
case 2:
p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
- r += (-0.5*y + p1/p2);
+ r += p1/p2-y/2;
}
}
- else if(ix<0x40200000) { /* x < 8.0 */
- i = (int)x;
- y = x-(double)i;
+ /* x < 8.0 */
+ else if(ix<0x40200000) {
+ i = x;
+ y = x-i;
p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
- r = half*y+p/q;
+ r = y/2+p/q;
z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
switch(i) {
case 7: z *= (y+6); /* FALLTHRU */
@@ -283,15 +284,15 @@ __ieee754_lgamma_r(double x, int *signgamp)
case 3: z *= (y+2); /* FALLTHRU */
r += __ieee754_log(z); break;
}
- /* 8.0 <= x < 2**58 */
- } else if (ix < 0x43900000) {
+ /* 8.0 <= x < 2**56 */
+ } else if (ix < 0x43700000) {
t = __ieee754_log(x);
z = one/x;
y = z*z;
w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
r = (x-half)*(t-one)+w;
} else
- /* 2**58 <= x <= inf */
+ /* 2**56 <= x <= inf */
r = x*(__ieee754_log(x)-one);
if(hx<0) r = nadj - r;
return r;
diff --git a/lib/msun/src/e_lgammaf_r.c b/lib/msun/src/e_lgammaf_r.c
index 9d23053..9084e18 100644
--- a/lib/msun/src/e_lgammaf_r.c
+++ b/lib/msun/src/e_lgammaf_r.c
@@ -122,29 +122,29 @@ sin_pif(float x)
float
__ieee754_lgammaf_r(float x, int *signgamp)
{
- float t,y,z,nadj,p,p1,p2,p3,q,r,w;
+ float nadj,p,p1,p2,p3,q,r,t,w,y,z;
int32_t hx;
int i,ix;
GET_FLOAT_WORD(hx,x);
- /* purge off +-inf, NaN, +-0, tiny and negative arguments */
+ /* purge +-Inf and NaNs */
*signgamp = 1;
ix = hx&0x7fffffff;
if(ix>=0x7f800000) return x*x;
- if(ix==0) {
- if(hx<0)
- *signgamp = -1;
- return one/vzero;
- }
- if(ix<0x35000000) { /* |x|<2**-21, return -log(|x|) */
- if(hx<0) {
- *signgamp = -1;
- return -__ieee754_logf(-x);
- } else return -__ieee754_logf(x);
+
+ /* purge +-0 and tiny arguments */
+ *signgamp = 1-2*((uint32_t)hx>>31);
+ if(ix<0x32000000) { /* |x|<2**-27, return -log(|x|) */
+ if(ix==0)
+ return one/vzero;
+ return -__ieee754_logf(fabsf(x));
}
+
+ /* purge negative integers and start evaluation for other x < 0 */
if(hx<0) {
- if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */
+ *signgamp = 1;
+ if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */
return one/vzero;
t = sin_pif(x);
if(t==zero) return one/vzero; /* -integer */
@@ -153,7 +153,7 @@ __ieee754_lgammaf_r(float x, int *signgamp)
x = -x;
}
- /* purge off 1 and 2 */
+ /* purge 1 and 2 */
if (ix==0x3f800000||ix==0x40000000) r = 0;
/* for x < 2.0 */
else if(ix<0x40000000) {
@@ -174,17 +174,18 @@ __ieee754_lgammaf_r(float x, int *signgamp)
p1 = a0+z*(a2+z*a4);
p2 = z*(a1+z*(a3+z*a5));
p = y*p1+p2;
- r += (p-y/2); break;
+ r += p-y/2; break;
case 1:
p = t0+y*t1+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*t7)))));
- r += (tf + p); break;
+ r += tf + p; break;
case 2:
p1 = y*(u0+y*(u1+y*u2));
p2 = one+y*(v1+y*(v2+y*v3));
- r += (p1/p2-y/2);
+ r += p1/p2-y/2;
}
}
- else if(ix<0x41000000) { /* x < 8.0 */
+ /* x < 8.0 */
+ else if(ix<0x41000000) {
i = x;
y = x-i;
p = y*(s0+y*(s1+y*(s2+y*s3)));
@@ -199,15 +200,15 @@ __ieee754_lgammaf_r(float x, int *signgamp)
case 3: z *= (y+2); /* FALLTHRU */
r += __ieee754_logf(z); break;
}
- /* 8.0 <= x < 2**24 */
- } else if (ix < 0x4b800000) {
+ /* 8.0 <= x < 2**27 */
+ } else if (ix < 0x4d000000) {
t = __ieee754_logf(x);
z = one/x;
y = z*z;
w = w0+z*(w1+y*w2);
r = (x-half)*(t-one)+w;
} else
- /* 2**24 <= x <= inf */
+ /* 2**27 <= x <= inf */
r = x*(__ieee754_logf(x)-one);
if(hx<0) r = nadj - r;
return r;
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index b1337c0..cc7afda 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -3377,8 +3377,7 @@ rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info)
{
phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase;
- phdr_info->dlpi_name = STAILQ_FIRST(&obj->names) ?
- STAILQ_FIRST(&obj->names)->name : obj->path;
+ phdr_info->dlpi_name = obj->path;
phdr_info->dlpi_phdr = obj->phdr;
phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
phdr_info->dlpi_tls_modid = obj->tlsindex;
diff --git a/release/doc/en_US.ISO8859-1/hardware/article.xml b/release/doc/en_US.ISO8859-1/hardware/article.xml
index 444e3ca..09cb3be 100644
--- a/release/doc/en_US.ISO8859-1/hardware/article.xml
+++ b/release/doc/en_US.ISO8859-1/hardware/article.xml
@@ -908,6 +908,8 @@
&hwlist.udav;
+ &hwlist.urndis;
+
&hwlist.vge;
&hwlist.vr;
diff --git a/sbin/dumpon/dumpon.8 b/sbin/dumpon/dumpon.8
index 6be8090..c2601b2 100644
--- a/sbin/dumpon/dumpon.8
+++ b/sbin/dumpon/dumpon.8
@@ -28,7 +28,7 @@
.\" From: @(#)swapon.8 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd April 29, 2013
+.Dd October 8, 2014
.Dt DUMPON 8
.Os
.Sh NAME
@@ -124,9 +124,18 @@ performs a
on
.Pa /dev/null
and thus instructs the kernel not to save crash dumps.
+.Pp
+Since
+.Nm
+cannot be used during kernel initialization, the
+.Va dumpdev
+variable of
+.Xr loader 8
+must be used to enable dumps for system panics which occur
+during kernel initialization.
.Sh FILES
-.Bl -tag -width "/dev/{ad,da}?s?b" -compact
-.It Pa /dev/{ad,da}?s?b
+.Bl -tag -width "/dev/{ada,da}?s?b" -compact
+.It Pa /dev/{ada,da}?s?b
standard swap areas
.It Pa /etc/rc.conf
boot-time system configuration
@@ -136,6 +145,7 @@ boot-time system configuration
.Xr rc.conf 5 ,
.Xr config 8 ,
.Xr init 8 ,
+.Xr loader 8 ,
.Xr rc 8 ,
.Xr savecore 8 ,
.Xr swapon 8 ,
diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c
index 9c478b3..51a6faa 100644
--- a/sbin/ifconfig/iflagg.c
+++ b/sbin/ifconfig/iflagg.c
@@ -17,6 +17,7 @@ static const char rcsid[] =
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_lagg.h>
+#include <net/ieee8023ad_lacp.h>
#include <net/route.h>
#include <ctype.h>
@@ -246,18 +247,9 @@ lagg_status(int s)
putchar('\n');
if (verbose) {
printf("\tlagg options:\n");
- printf("\t\tuse_flowid: %d\n",
- (ro.ro_opts & LAGG_OPT_USE_FLOWID) ? 1 : 0);
+ printb("\t\tflags", ro.ro_opts, LAGG_OPT_BITS);
+ putchar('\n');
printf("\t\tflowid_shift: %d\n", ro.ro_flowid_shift);
- switch (ra.ra_proto) {
- case LAGG_PROTO_LACP:
- printf("\t\tlacp_strict: %d\n",
- (ro.ro_opts & LAGG_OPT_LACP_STRICT) ? 1 : 0);
- printf("\t\tlacp_rxtest: %d\n",
- (ro.ro_opts & LAGG_OPT_LACP_RXTEST) ? 1 : 0);
- printf("\t\tlacp_txtest: %d\n",
- (ro.ro_opts & LAGG_OPT_LACP_TXTEST) ? 1 : 0);
- }
printf("\tlagg statistics:\n");
printf("\t\tactive ports: %d\n", ro.ro_active);
printf("\t\tflapping: %u\n", ro.ro_flapping);
@@ -272,7 +264,8 @@ lagg_status(int s)
printf("\tlaggport: %s ", rpbuf[i].rp_portname);
printb("flags", rpbuf[i].rp_flags, LAGG_PORT_BITS);
if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
- printf(" state=%X", lp->actor_state);
+ printb(" state", lp->actor_state,
+ LACP_STATE_BITS);
putchar('\n');
if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
printf("\t\t%s\n",
diff --git a/sbin/ipfw/Makefile b/sbin/ipfw/Makefile
index de27e3e..9eb4511 100644
--- a/sbin/ipfw/Makefile
+++ b/sbin/ipfw/Makefile
@@ -3,7 +3,7 @@
.include <src.opts.mk>
PROG= ipfw
-SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c
+SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c tables.c
WARNS?= 2
.if ${MK_PF} != "no"
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 5b56b39..53169fb 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 31, 2014
+.Dd Aug 13, 2014
.Dt IPFW 8
.Os
.Sh NAME
@@ -48,17 +48,43 @@ in-kernel NAT.
.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
.Ss LOOKUP TABLES
.Nm
-.Cm table Ar number Cm add Ar addr Ns Oo / Ns Ar masklen Oc Op Ar value
+.Oo Cm set Ar N Oc Cm table Ar name Cm create Ar create-options
.Nm
-.Cm table Ar number Cm delete Ar addr Ns Op / Ns Ar masklen
+.Oo Cm set Ar N Oc Cm table Ar name Cm destroy
.Nm
-.Cm table
-.Brq Ar number | all
-.Cm flush
+.Oo Cm set Ar N Oc Cm table Ar name Cm modify Ar modify-options
+.Nm
+.Oo Cm set Ar N Oc Cm table Ar name Cm swap Ar name
+.Nm
+.Oo Cm set Ar N Oc Cm table Ar name Cm add Ar table-key Op Ar value
+.Nm
+.Oo Cm set Ar N Oc Cm table Ar name Cm add Op Ar table-key Ar value ...
+.Nm
+.Oo Cm set Ar N Oc Cm table Ar name Cm atomic add Op Ar table-key Ar value ...
+.Nm
+.Oo Cm set Ar N Oc Cm table Ar name Cm delete Op Ar table-key ...
.Nm
-.Cm table
-.Brq Ar number | all
+.Oo Cm set Ar N Oc Cm table Ar name Cm lookup Ar addr
+.Nm
+.Oo Cm set Ar N Oc Cm table Ar name Cm lock
+.Nm
+.Oo Cm set Ar N Oc Cm table Ar name Cm unlock
+.Nm
+.Oo Cm set Ar N Oc Cm table
+.Brq Ar name | all
.Cm list
+.Nm
+.Oo Cm set Ar N Oc Cm table
+.Brq Ar name | all
+.Cm info
+.Nm
+.Oo Cm set Ar N Oc Cm table
+.Brq Ar name | all
+.Cm detail
+.Nm
+.Oo Cm set Ar N Oc Cm table
+.Brq Ar name | all
+.Cm flush
.Ss DUMMYNET CONFIGURATION (TRAFFIC SHAPER AND PACKET SCHEDULER)
.Nm
.Brq Cm pipe | queue | sched
@@ -87,6 +113,13 @@ in-kernel NAT.
.Oc
.Oc
.Ar pathname
+.Ss INTERNAL DIAGNOSTICS
+.Nm
+.Cm internal iflist
+.Nm
+.Cm internal talist
+.Nm
+.Cm internal vlist
.Sh DESCRIPTION
The
.Nm
@@ -822,10 +855,11 @@ It is possible to use the
.Cm tablearg
keyword with a skipto for a
.Em computed
-skipto, but care should be used, as no destination caching
-is possible in this case so the rules are always walked to find it,
-starting from the
-.Cm skipto .
+skipto. Skipto may work either in O(log(N)) or in O(1) depending
+on amount of memory and/or sysctl variables.
+See the
+.Sx SYSCTL VARIABLES
+section for more details.
.It Cm call Ar number | tablearg
The current rule number is saved in the internal stack and
ruleset processing continues with the first rule numbered
@@ -1152,7 +1186,7 @@ with multiple addresses) is provided for convenience only and
its use is discouraged.
.It Ar addr : Oo Cm not Oc Bro
.Cm any | me | me6 |
-.Cm table Ns Pq Ar number Ns Op , Ns Ar value
+.Cm table Ns Pq Ar name Ns Op , Ns Ar value
.Ar | addr-list | addr-set
.Brc
.Bl -tag -width indent
@@ -1164,8 +1198,8 @@ matches any IP address configured on an interface in the system.
matches any IPv6 address configured on an interface in the system.
The address list is evaluated at the time the packet is
analysed.
-.It Cm table Ns Pq Ar number Ns Op , Ns Ar value
-Matches any IPv4 address for which an entry exists in the lookup table
+.It Cm table Ns Pq Ar name Ns Op , Ns Ar value
+Matches any IPv4 or IPv6 address for which an entry exists in the lookup table
.Ar number .
If an optional 32-bit unsigned
.Ar value
@@ -1359,6 +1393,19 @@ and IPsec encapsulated security payload headers
.It Cm fib Ar fibnum
Matches a packet that has been tagged to use
the given FIB (routing table) number.
+.It Cm flow Ar table Ns Pq Ar name Ns Op , Ns Ar value
+Search for the flow entry in lookup table
+.Ar name .
+If not found, the match fails.
+Otherwise, the match succeeds and
+.Cm tablearg
+is set to the value extracted from the table.
+.Pp
+This option can be useful to quickly dispatch traffic based on
+certain packet fields.
+See the
+.Sx LOOKUP TABLES
+section below for more information on lookup tables.
.It Cm flow-id Ar labels
Matches IPv6 packets containing any of the flow labels given in
.Ar labels .
@@ -1550,9 +1597,9 @@ of source and destination addresses and ports can be
specified.
Currently,
only IPv4 flows are supported.
-.It Cm lookup Bro Cm dst-ip | dst-port | src-ip | src-port | uid | jail Brc Ar N
+.It Cm lookup Bro Cm dst-ip | dst-port | src-ip | src-port | uid | jail Brc Ar name
Search an entry in lookup table
-.Ar N
+.Ar name
that matches the field specified as argument.
If not found, the match fails.
Otherwise, the match succeeds and
@@ -1616,13 +1663,19 @@ and they are always printed as hexadecimal (unless the
option is used, in which case symbolic resolution will be attempted).
.It Cm proto Ar protocol
Matches packets with the corresponding IP protocol.
-.It Cm recv | xmit | via Brq Ar ifX | Ar if Ns Cm * | Ar table Ns Pq Ar number Ns Op , Ns Ar value | Ar ipno | Ar any
+.It Cm recv | xmit | via Brq Ar ifX | Ar if Ns Cm * | Ar table Ns Po Ar name Ns Oo , Ns Ar value Oc Pc | Ar ipno | Ar any
Matches packets received, transmitted or going through,
respectively, the interface specified by exact name
.Po Ar ifX Pc ,
by device name
.Po Ar if* Pc ,
by IP address, or through some interface.
+Table
+.Ar name
+may be used to match interface by its kernel ifindex.
+See the
+.Sx LOOKUP TABLES
+section below for more information on lookup tables.
.Pp
The
.Cm via
@@ -1817,15 +1870,35 @@ connected networks instead of all source addresses.
.Sh LOOKUP TABLES
Lookup tables are useful to handle large sparse sets of
addresses or other search keys (e.g., ports, jail IDs, interface names).
-In the rest of this section we will use the term ``address''.
-There may be up to 65535 different lookup tables, numbered 0 to 65534.
+In the rest of this section we will use the term ``key''.
+Table name needs to match the following spec:
+.Ar table-name .
+Tables with the same name can be created in different
+.Ar sets .
+However, rule links to the tables in
+.Ar set 0
+by default.
+This behavior can be controlled by
+.Va net.inet.ip.fw.tables_sets
+variable.
+See the
+.Sx SETS OF RULES
+section for more information.
+There may be up to 65535 different lookup tables.
.Pp
+The following table types are supported:
+.Bl -tag -width indent
+.It Ar table-type : Ar addr | iface | number | flow
+.It Ar table-key : Ar addr Ns Oo / Ns Ar masklen Oc | iface-name | number | flow-spec
+.It Ar flow-spec : Ar flow-field Ns Op , Ns Ar flow-spec
+.It Ar flow-field : src-ip | proto | src-port | dst-ip | dst-port
+.It Cm addr
+matches IPv4 or IPv6 address.
Each entry is represented by an
.Ar addr Ns Op / Ns Ar masklen
and will match all addresses with base
.Ar addr
-(specified as an IPv4/IPv6 address, a hostname or an unsigned integer)
-and mask width of
+(specified as an IPv4/IPv6 address, or a hostname) and mask width of
.Ar masklen
bits.
If
@@ -1833,29 +1906,140 @@ If
is not specified, it defaults to 32 for IPv4 and 128 for IPv6.
When looking up an IP address in a table, the most specific
entry will match.
-Associated with each entry is a 32-bit unsigned
-.Ar value ,
-which can optionally be checked by a rule matching code.
-When adding an entry, if
-.Ar value
-is not specified, it defaults to 0.
-.Pp
-An entry can be added to a table
-.Pq Cm add ,
-or removed from a table
-.Pq Cm delete .
-A table can be examined
-.Pq Cm list
-or flushed
-.Pq Cm flush .
-.Pp
-Internally, each table is stored in a Radix tree, the same way as
-the routing table (see
-.Xr route 4 ) .
+.It Cm iface
+matches interface names.
+Each entry is represented by string treated as interface name.
+Wildcards are not supported.
+.It Cm number
+maches protocol ports, uids/gids or jail IDs.
+Each entry is represented by 32-bit unsigned integer.
+Ranges are not supported.
+.It Cm flow
+Matches packet fields specified by
+.Ar flow
+type suboptions with table entries.
+.El
+.Pp
+Tables require explicit creation via
+.Cm create
+before use.
+.Pp
+The following creation options are supported:
+.Bl -tag -width indent
+.It Ar create-options : Ar create-option | create-options
+.It Ar create-option : Cm type Ar table-type | Cm valtype Ar value-mask | Cm algo Ar algo-desc |
+.Cm limit Ar number | Cm locked
+.It Cm type
+Table key type.
+.It Cm valtype
+Table value mask.
+.It Cm algo
+Table algorithm to use (see below).
+.It Cm limit
+Maximum number of items that may be inserted into table.
+.It Cm locked
+Restrict any table modifications.
+.El
+.Pp
+Some of these options may be modified later via
+.Cm modify
+keyword.
+The following options can be changed:
+.Bl -tag -width indent
+.It Ar modify-options : Ar modify-option | modify-options
+.It Ar modify-option : Cm limit Ar number
+.It Cm limit
+Alter maximum number of items that may be inserted into table.
+.El
+.Pp
+Additionally, table can be locked or unlocked using
+.Cm lock
+or
+.Cm unlock
+commands.
+.Pp
+Tables of the same
+.Ar type
+can be swapped with each other using
+.Cm swap Ar name
+command.
+Swap may fail if tables limits are set and data exchange
+would result in limits hit.
+Operation is performed atomically.
+.Pp
+One or more entries can be added to a table at once using
+.Cm add
+command.
+Addition of all items are performed atomically.
+By default, error in addition of one entry does not influence
+addition of other entries. However, non-zero error code is returned
+in that case.
+Special
+.Cm atomic
+keyword may be specified before
+.Cm add
+to indicate all-or-none add request.
.Pp
-Lookup tables currently support only ports, jail IDs, IPv4/IPv6 addresses
-and interface names.
-Wildcards is not supported for interface names.
+One or more entries can be removed from a table at once using
+.Cm delete
+command.
+By default, error in removal of one entry does not influence
+removing of other entries. However, non-zero error code is returned
+in that case.
+.Pp
+It may be possible to check what entry will be found on particular
+.Ar table-key
+using
+.Cm lookup
+.Ae table-key
+command.
+This functionality is optional and may be unsupported in some algorithms.
+.Pp
+The following operations can be performed on
+.Ar one
+or
+.Cm all
+tables:
+.Bl -tag -width indent
+.It Cm list
+List all entries.
+.It Cm flush
+Removes all entries.
+.It Cm info
+Shows generic table information.
+.It Cm detail
+Shows generic table information and algo-specific data.
+.El
+.Pp
+The following lookup algorithms are supported:
+.Bl -tag -width indent
+.It Ar algo-desc : algo-name | "algo-name algo-data"
+.It Ar algo-name: Ar addr:radix | addr:hash | iface:arrray | number:array | flow:hash
+.It Cm addr:radix
+Separate Radix trees for IPv4 and IPv6, the same way as the routing table (see
+.Xr route 4 ) .
+Default choice for
+.Ar addr
+type.
+.It Cm addr:hash
+Separate auto-growing hashes for IPv4 and IPv6.
+Accepts entries with the same mask length specified initially via
+.Cm "addr:hash masks=/v4,/v6"
+algorithm creation options.
+Assume /32 and /128 masks by default.
+Search removes host bits (according to mask) from supplied address and checks
+resulting key in appropriate hash.
+Mostly optimized for /64 and byte-ranged IPv6 masks.
+.It Cm iface:arrray
+Array storing sorted indexes for entries which are presented in the system.
+Optimized for very fast lookup.
+.It Cm number:array
+Array storing sorted u32 numbers.
+.It Cm flow:hash
+Auto-growing hash storing flow entries.
+Search calculates hash on required packet fields and searches for matching
+entries in selected bucket.
+.El
.Pp
The
.Cm tablearg
@@ -1864,6 +2048,39 @@ the argument for a rule action, action parameter or rule option.
This can significantly reduce number of rules in some configurations.
If two tables are used in a rule, the result of the second (destination)
is used.
+.Pp
+Each record may hold one or more values according to
+.Ar value-mask .
+This mask is set on table creation via
+.Cm valtype
+option.
+The following value types are supported:
+.Bl -tag -width indent
+.It Ar value-mask : Ar value-type Ns Op , Ns Ar value-mask
+.It Ar value-type : Ar skipto | pipe | fib | nat | dscp | tag | divert |
+.Ar netgraph | limit | ipv4
+.It Cm skipto
+rule number to jump to.
+.It Cm pipe
+Pipe number to use.
+.It Cm fib
+fib number to match/set.
+.It Cm nat
+nat number to jump to.
+.It Cm dscp
+dscp value to match/set.
+.It Cm tag
+tag number to match/set.
+.It Cm divert
+port number to divert traffic to.
+.It Cm netgraph
+hook number to move packet to.
+.It Cm limit
+maximum number of connections.
+.It Cm ipv4
+IPv4 nexthop to fwd packets to.
+.El
+.Pp
The
.Cm tablearg
argument can be used with the following actions:
@@ -1873,32 +2090,34 @@ action parameters:
rule options:
.Cm limit, tagged.
.Pp
-When used with
-.Cm fwd
-it is possible to supply table entries with values
-that are in the form of IP addresses or hostnames.
-See the
-.Sx EXAMPLES
-Section for example usage of tables and the tablearg keyword.
-.Pp
When used with the
.Cm skipto
action, the user should be aware that the code will walk the ruleset
-up to a rule equal to, or past, the given number,
-and should therefore try keep the
-ruleset compact between the skipto and the target rules.
+up to a rule equal to, or past, the given number.
+.Pp
+See the
+.Sx EXAMPLES
+Section for example usage of tables and the tablearg keyword.
.Sh SETS OF RULES
-Each rule belongs to one of 32 different
+Each rule or table belongs to one of 32 different
.Em sets
, numbered 0 to 31.
Set 31 is reserved for the default rule.
.Pp
-By default, rules are put in set 0, unless you use the
+By default, rules or tables are put in set 0, unless you use the
.Cm set N
-attribute when entering a new rule.
+attribute when adding a new rule or table.
Sets can be individually and atomically enabled or disabled,
so this mechanism permits an easy way to store multiple configurations
of the firewall and quickly (and atomically) switch between them.
+.Pp
+By default, tables from set 0 are referenced when adding rule with
+table opcodes regardless of rule set.
+This behavior can be changed by setting
+.Va net.inet.ip.fw.tables_set
+variable to 1.
+Rule's set will then be used for table references.
+.Pp
The command to enable/disable sets is
.Bd -ragged -offset indent
.Nm
@@ -2968,6 +3187,22 @@ Controls whether bridged packets are passed to
.Nm .
Default is no.
.El
+.Sh INTERNAL DIAGNOSTICS
+There are some commands that may be useful to understand current state
+of certain subsystems inside kernel module.
+These commands provide debugging output which may change without notice.
+.Pp
+Currently the following commands are available as
+.Cm internal
+sub-options:
+.Bl -tag -width indent
+.It Cm iflist
+Lists all interface which are currently tracked by
+.Nm
+with their in-kernel status.
+.It Cm talist
+List all table lookup algorithms currently available.
+.El
.Sh EXAMPLES
There are far too many possible uses of
.Nm
@@ -3220,30 +3455,43 @@ Then we classify traffic using a single rule:
.Dl "ipfw pipe 1 config bw 1000Kbyte/s"
.Dl "ipfw pipe 4 config bw 4000Kbyte/s"
.Dl "..."
-.Dl "ipfw table 1 add 192.168.2.0/24 1"
-.Dl "ipfw table 1 add 192.168.0.0/27 4"
-.Dl "ipfw table 1 add 192.168.0.2 1"
+.Dl "ipfw table T1 create type addr"
+.Dl "ipfw table T1 add 192.168.2.0/24 1"
+.Dl "ipfw table T1 add 192.168.0.0/27 4"
+.Dl "ipfw table T1 add 192.168.0.2 1"
.Dl "..."
-.Dl "ipfw add pipe tablearg ip from table(1) to any"
+.Dl "ipfw add pipe tablearg ip from 'table(T1)' to any"
.Pp
Using the
.Cm fwd
action, the table entries may include hostnames and IP addresses.
.Pp
-.Dl "ipfw table 1 add 192.168.2.0/24 10.23.2.1"
-.Dl "ipfw table 1 add 192.168.0.0/27 router1.dmz"
+.Dl "ipfw table T2 create type addr ftype ip"
+.Dl "ipfw table T2 add 192.168.2.0/24 10.23.2.1"
+.Dl "ipfw table T21 add 192.168.0.0/27 router1.dmz"
.Dl "..."
.Dl "ipfw add 100 fwd tablearg ip from any to table(1)"
.Pp
In the following example per-interface firewall is created:
.Pp
-.Dl "ipfw table 10 add vlan20 12000"
-.Dl "ipfw table 10 add vlan30 13000"
-.Dl "ipfw table 20 add vlan20 22000"
-.Dl "ipfw table 20 add vlan30 23000"
+.Dl "ipfw table IN create type iface valtype skipto,fib"
+.Dl "ipfw table IN add vlan20 12000,12"
+.Dl "ipfw table IN add vlan30 13000,13"
+.Dl "ipfw table OUT create type iface valtype skipto"
+.Dl "ipfw table OUT add vlan20 22000"
+.Dl "ipfw table OUT add vlan30 23000"
+.Dl ".."
+.Dl "ipfw add 100 ipfw setfib tablearg ip from any to any recv 'table(IN)' in"
+.Dl "ipfw add 200 ipfw skipto tablearg ip from any to any recv 'table(IN)' in"
+.Dl "ipfw add 300 ipfw skipto tablearg ip from any to any xmit 'table(OUT)' out"
+.Pp
+The following example illustrate usage of flow tables:
+.Pp
+.Dl "ipfw table fl create type flow:flow:src-ip,proto,dst-ip,dst-port"
+.Dl "ipfw table fl add 2a02:6b8:77::88,tcp,2a02:6b8:77::99,80 11"
+.Dl "ipfw table fl add 10.0.0.1,udp,10.0.0.2,53 12"
.Dl ".."
-.Dl "ipfw add 100 ipfw skipto tablearg ip from any to any recv 'table(10)' in"
-.Dl "ipfw add 200 ipfw skipto tablearg ip from any to any xmit 'table(10)' out"
+.Dl "ipfw add 100 allow ip from any to any flow 'table(fl,11)' recv ix0"
.Ss SETS OF RULES
To add a set of rules atomically, e.g.\& set 18:
.Pp
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 30fe604..19c1d40 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -66,22 +66,13 @@ struct format_opts {
uint32_t first; /* first rule to request */
uint32_t last; /* last rule to request */
uint32_t dcnt; /* number of dynamic states */
+ ipfw_obj_ctlv *tstate; /* table state data */
};
-#define IP_FW_TARG IP_FW_TABLEARG
-#define ip_fw_bcounter ip_fw
-#define ip_fw_rule ip_fw
-struct tidx;
int resvd_set_number = RESVD_SET;
int ipfw_socket = -1;
-uint32_t ipfw_tables_max = 0; /* Number of tables supported by kernel */
-
-#ifndef s6_addr32
-#define s6_addr32 __u6_addr.__u6_addr32
-#endif
-
#define CHECK_LENGTH(v, len) do { \
if ((v) < (len)) \
errx(EX_DATAERR, "Rule too long"); \
@@ -362,6 +353,7 @@ static struct _s_x rule_options[] = {
{ "src-ipv6", TOK_SRCIP6},
{ "src-ip6", TOK_SRCIP6},
{ "lookup", TOK_LOOKUP},
+ { "flow", TOK_FLOW},
{ "//", TOK_COMMENT },
{ "not", TOK_NOT }, /* pseudo option */
@@ -376,6 +368,11 @@ static struct _s_x rule_options[] = {
};
void bprint_uint_arg(struct buf_pr *bp, const char *str, uint32_t arg);
+static int ipfw_get_config(struct cmdline_opts *co, struct format_opts *fo,
+ ipfw_cfg_lheader **pcfg, size_t *psize);
+static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
+ ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av);
+static void ipfw_list_tifaces(void);
/*
* Simple string buffer API.
@@ -514,6 +511,26 @@ safe_realloc(void *ptr, size_t size)
}
/*
+ * Compare things like interface or table names.
+ */
+int
+stringnum_cmp(const char *a, const char *b)
+{
+ int la, lb;
+
+ la = strlen(a);
+ lb = strlen(b);
+
+ if (la > lb)
+ return (1);
+ else if (la < lb)
+ return (-01);
+
+ return (strcmp(a, b));
+}
+
+
+/*
* conditionally runs the command.
* Selected options or negative -> getsockopt
*/
@@ -546,20 +563,18 @@ do_cmd(int optname, void *optval, uintptr_t optlen)
}
/*
- * do_setcmd3 - pass ipfw control cmd to kernel
+ * do_set3 - pass ipfw control cmd to kernel
* @optname: option name
* @optval: pointer to option data
* @optlen: option length
*
- * Function encapsulates option value in IP_FW3 socket option
- * and calls setsockopt().
- * Function returns 0 on success or -1 otherwise.
+ * Assumes op3 header is already embedded.
+ * Calls setsockopt() with IP_FW3 as kernel-visible opcode.
+ * Returns 0 on success or errno otherwise.
*/
-static int
-do_setcmd3(int optname, void *optval, socklen_t optlen)
+int
+do_set3(int optname, ip_fw3_opheader *op3, uintptr_t optlen)
{
- socklen_t len;
- ip_fw3_opheader *op3;
if (co.test_only)
return (0);
@@ -569,14 +584,40 @@ do_setcmd3(int optname, void *optval, socklen_t optlen)
if (ipfw_socket < 0)
err(EX_UNAVAILABLE, "socket");
- len = sizeof(ip_fw3_opheader) + optlen;
- op3 = alloca(len);
- /* Zero reserved fields */
- memset(op3, 0, sizeof(ip_fw3_opheader));
- memcpy(op3 + 1, optval, optlen);
op3->opcode = optname;
- return setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len);
+ return (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, optlen));
+}
+
+/*
+ * do_get3 - pass ipfw control cmd to kernel
+ * @optname: option name
+ * @optval: pointer to option data
+ * @optlen: pointer to option length
+ *
+ * Assumes op3 header is already embedded.
+ * Calls getsockopt() with IP_FW3 as kernel-visible opcode.
+ * Returns 0 on success or errno otherwise.
+ */
+int
+do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen)
+{
+ int error;
+
+ if (co.test_only)
+ return (0);
+
+ if (ipfw_socket == -1)
+ ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ if (ipfw_socket < 0)
+ err(EX_UNAVAILABLE, "socket");
+
+ op3->opcode = optname;
+
+ error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3,
+ (socklen_t *)optlen);
+
+ return (error);
}
/**
@@ -596,6 +637,37 @@ match_token(struct _s_x *table, char *string)
}
/**
+ * match_token takes a table and a string, returns the value associated
+ * with the string for the best match.
+ *
+ * Returns:
+ * value from @table for matched records
+ * -1 for non-matched records
+ * -2 if more than one records match @string.
+ */
+int
+match_token_relaxed(struct _s_x *table, char *string)
+{
+ struct _s_x *pt, *m;
+ int i, c;
+
+ i = strlen(string);
+ c = 0;
+
+ for (pt = table ; i != 0 && pt->s != NULL ; pt++) {
+ if (strncmp(pt->s, string, i) != 0)
+ continue;
+ m = pt;
+ c++;
+ }
+
+ if (c == 1)
+ return (m->x);
+
+ return (c > 0 ? -2: -1);
+}
+
+/**
* match_value takes a table and a value, returns the string associated
* with the value (NULL in case of failure).
*/
@@ -608,16 +680,36 @@ match_value(struct _s_x *p, int value)
return NULL;
}
+size_t
+concat_tokens(char *buf, size_t bufsize, struct _s_x *table, char *delimiter)
+{
+ struct _s_x *pt;
+ int l;
+ size_t sz;
+
+ for (sz = 0, pt = table ; pt->s != NULL; pt++) {
+ l = snprintf(buf + sz, bufsize - sz, "%s%s",
+ (sz == 0) ? "" : delimiter, pt->s);
+ sz += l;
+ bufsize += l;
+ if (sz > bufsize)
+ return (bufsize);
+ }
+
+ return (sz);
+}
+
/*
* helper function to process a set of flags and set bits in the
* appropriate masks.
*/
-void
-fill_flags(struct _s_x *flags, char *p, uint8_t *set, uint8_t *clear)
+int
+fill_flags(struct _s_x *flags, char *p, char **e, uint32_t *set,
+ uint32_t *clear)
{
char *q; /* points to the separator */
int val;
- uint8_t *which; /* mask we are working on */
+ uint32_t *which; /* mask we are working on */
while (p && *p) {
if (*p == '!') {
@@ -629,11 +721,35 @@ fill_flags(struct _s_x *flags, char *p, uint8_t *set, uint8_t *clear)
if (q)
*q++ = '\0';
val = match_token(flags, p);
- if (val <= 0)
- errx(EX_DATAERR, "invalid flag %s", p);
- *which |= (uint8_t)val;
+ if (val <= 0) {
+ if (e != NULL)
+ *e = p;
+ return (-1);
+ }
+ *which |= (uint32_t)val;
p = q;
}
+ return (0);
+}
+
+void
+print_flags_buffer(char *buf, size_t sz, struct _s_x *list, uint32_t set)
+{
+ char const *comma = "";
+ int i, l;
+
+ for (i = 0; list[i].x != 0; i++) {
+ if ((set & list[i].x) == 0)
+ continue;
+
+ set &= ~list[i].x;
+ l = snprintf(buf, sz, "%s%s", comma, list[i].s);
+ if (l >= sz)
+ return;
+ comma = ",";
+ buf += l;
+ sz -=l;
+ }
}
/*
@@ -1018,6 +1134,7 @@ print_flags(struct buf_pr *bp, char const *name, ipfw_insn *cmd,
}
}
+
/*
* Print the ip address contained in a command.
*/
@@ -1029,6 +1146,7 @@ print_ip(struct buf_pr *bp, struct format_opts *fo, ipfw_insn_ip *cmd,
struct in_addr *ia;
uint32_t len = F_LEN((ipfw_insn *)cmd);
uint32_t *a = ((ipfw_insn_u32 *)cmd)->d;
+ char *t;
if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) {
uint32_t d = a[1];
@@ -1036,8 +1154,9 @@ print_ip(struct buf_pr *bp, struct format_opts *fo, ipfw_insn_ip *cmd,
if (d < sizeof(lookup_key)/sizeof(lookup_key[0]))
arg = match_value(rule_options, lookup_key[d]);
- bprintf(bp, "%s lookup %s %d", cmd->o.len & F_NOT ? " not": "",
- arg, cmd->o.arg1);
+ t = table_search_ctlv(fo->tstate, ((ipfw_insn *)cmd)->arg1);
+ bprintf(bp, "%s lookup %s %s", cmd->o.len & F_NOT ? " not": "",
+ arg, t);
return;
}
bprintf(bp, "%s%s ", cmd->o.len & F_NOT ? " not": "", s);
@@ -1048,7 +1167,8 @@ print_ip(struct buf_pr *bp, struct format_opts *fo, ipfw_insn_ip *cmd,
}
if (cmd->o.opcode == O_IP_SRC_LOOKUP ||
cmd->o.opcode == O_IP_DST_LOOKUP) {
- bprintf(bp, "table(%u", ((ipfw_insn *)cmd)->arg1);
+ t = table_search_ctlv(fo->tstate, ((ipfw_insn *)cmd)->arg1);
+ bprintf(bp, "table(%s", t);
if (len == F_INSN_SIZE(ipfw_insn_u32))
bprintf(bp, ",%u", *a);
bprintf(bp, ")");
@@ -1262,12 +1382,9 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */
ipfw_insn_altq *altqptr = NULL; /* set if we find an O_ALTQ */
int or_block = 0; /* we are in an or block */
- uint32_t set_disable;
uint32_t uval;
- bcopy(&rule->next_rule, &set_disable, sizeof(set_disable));
-
- if (set_disable & (1 << rule->set)) {
+ if ((fo->set_mask & (1 << rule->set)) == 0) {
/* disabled mask */
if (!co->show_sets)
return;
@@ -1504,7 +1621,7 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
break;
}
}
- if (rule->_pad & 1) { /* empty rules before options */
+ if (rule->flags & IPFW_RULE_NOOPT) { /* empty rules before options */
if (!co->do_compact) {
show_prerequisites(bp, &flags, HAVE_PROTO, 0);
bprintf(bp, " from any to any");
@@ -1707,7 +1824,7 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
case O_RECV:
case O_VIA:
{
- char const *s;
+ char const *s, *t;
ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd;
if (cmd->opcode == O_XMIT)
@@ -1719,10 +1836,26 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
if (cmdif->name[0] == '\0')
bprintf(bp, " %s %s", s,
inet_ntoa(cmdif->p.ip));
- else if (cmdif->name[0] == '\1') /* interface table */
- bprintf(bp, " %s table(%d)", s, cmdif->p.glob);
- else
+ else if (cmdif->name[0] == '\1') {
+ /* interface table */
+ t = table_search_ctlv(fo->tstate,
+ cmdif->p.kidx);
+ bprintf(bp, " %s table(%s)", s, t);
+ } else
bprintf(bp, " %s %s", s, cmdif->name);
+
+ break;
+ }
+ case O_IP_FLOW_LOOKUP:
+ {
+ char *t;
+
+ t = table_search_ctlv(fo->tstate, cmd->arg1);
+ bprintf(bp, " flow table(%s", t);
+ if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32))
+ bprintf(bp, ",%u",
+ ((ipfw_insn_u32 *)cmd)->d[0]);
+ bprintf(bp, ")");
break;
}
case O_IPID:
@@ -1974,6 +2107,19 @@ show_dyn_state(struct cmdline_opts *co, struct format_opts *fo,
bprintf(bp, " UNKNOWN <-> UNKNOWN\n");
}
+static int
+do_range_cmd(int cmd, ipfw_range_tlv *rt)
+{
+ ipfw_range_header rh;
+
+ memset(&rh, 0, sizeof(rh));
+ memcpy(&rh.range, rt, sizeof(*rt));
+ rh.range.head.length = sizeof(*rt);
+ rh.range.head.type = IPFW_TLV_RANGE;
+
+ return (do_set3(cmd, &rh.opheader, sizeof(rh)));
+}
+
/*
* This one handles all set-related commands
* ipfw set { show | enable | disable }
@@ -1984,77 +2130,75 @@ show_dyn_state(struct cmdline_opts *co, struct format_opts *fo,
void
ipfw_sets_handler(char *av[])
{
- uint32_t set_disable, masks[2];
- int i, nbytes;
- uint16_t rulenum;
- uint8_t cmd, new_set;
+ uint32_t masks[2];
+ int i;
+ uint8_t cmd, new_set, rulenum;
+ ipfw_range_tlv rt;
+ char *msg;
+ size_t size;
av++;
+ memset(&rt, 0, sizeof(rt));
if (av[0] == NULL)
errx(EX_USAGE, "set needs command");
if (_substrcmp(*av, "show") == 0) {
- void *data = NULL;
- char const *msg;
- int nalloc;
-
- nalloc = nbytes = sizeof(struct ip_fw);
- while (nbytes >= nalloc) {
- if (data)
- free(data);
- nalloc = nalloc * 2 + 200;
- nbytes = nalloc;
- data = safe_calloc(1, nbytes);
- if (do_cmd(IP_FW_GET, data, (uintptr_t)&nbytes) < 0)
- err(EX_OSERR, "getsockopt(IP_FW_GET)");
- }
+ struct format_opts fo;
+ ipfw_cfg_lheader *cfg;
- bcopy(&((struct ip_fw *)data)->next_rule,
- &set_disable, sizeof(set_disable));
+ memset(&fo, 0, sizeof(fo));
+ if (ipfw_get_config(&co, &fo, &cfg, &size) != 0)
+ err(EX_OSERR, "requesting config failed");
- for (i = 0, msg = "disable" ; i < RESVD_SET; i++)
- if ((set_disable & (1<<i))) {
+ for (i = 0, msg = "disable"; i < RESVD_SET; i++)
+ if ((cfg->set_mask & (1<<i)) == 0) {
printf("%s %d", msg, i);
msg = "";
}
- msg = (set_disable) ? " enable" : "enable";
+ msg = (cfg->set_mask != (uint32_t)-1) ? " enable" : "enable";
for (i = 0; i < RESVD_SET; i++)
- if (!(set_disable & (1<<i))) {
+ if ((cfg->set_mask & (1<<i)) != 0) {
printf("%s %d", msg, i);
msg = "";
}
printf("\n");
+ free(cfg);
} else if (_substrcmp(*av, "swap") == 0) {
av++;
if ( av[0] == NULL || av[1] == NULL )
errx(EX_USAGE, "set swap needs 2 set numbers\n");
- rulenum = atoi(av[0]);
- new_set = atoi(av[1]);
- if (!isdigit(*(av[0])) || rulenum > RESVD_SET)
+ rt.set = atoi(av[0]);
+ rt.new_set = atoi(av[1]);
+ if (!isdigit(*(av[0])) || rt.set > RESVD_SET)
errx(EX_DATAERR, "invalid set number %s\n", av[0]);
- if (!isdigit(*(av[1])) || new_set > RESVD_SET)
+ if (!isdigit(*(av[1])) || rt.new_set > RESVD_SET)
errx(EX_DATAERR, "invalid set number %s\n", av[1]);
- masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
- i = do_cmd(IP_FW_DEL, masks, sizeof(uint32_t));
+ i = do_range_cmd(IP_FW_SET_SWAP, &rt);
} else if (_substrcmp(*av, "move") == 0) {
av++;
if (av[0] && _substrcmp(*av, "rule") == 0) {
- cmd = 2;
+ rt.flags = IPFW_RCFLAG_RANGE; /* move rules to new set */
+ cmd = IP_FW_XMOVE;
av++;
} else
- cmd = 3;
+ cmd = IP_FW_SET_MOVE; /* Move set to new one */
if (av[0] == NULL || av[1] == NULL || av[2] == NULL ||
av[3] != NULL || _substrcmp(av[1], "to") != 0)
errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
rulenum = atoi(av[0]);
- new_set = atoi(av[2]);
- if (!isdigit(*(av[0])) || (cmd == 3 && rulenum > RESVD_SET) ||
- (cmd == 2 && rulenum == IPFW_DEFAULT_RULE) )
+ rt.new_set = atoi(av[2]);
+ if (cmd == IP_FW_XMOVE) {
+ rt.start_rule = rulenum;
+ rt.end_rule = rulenum;
+ } else
+ rt.set = rulenum;
+ rt.new_set = atoi(av[2]);
+ if (!isdigit(*(av[0])) || (cmd == 3 && rt.set > RESVD_SET) ||
+ (cmd == 2 && rt.start_rule == IPFW_DEFAULT_RULE) )
errx(EX_DATAERR, "invalid source number %s\n", av[0]);
if (!isdigit(*(av[2])) || new_set > RESVD_SET)
errx(EX_DATAERR, "invalid dest. set %s\n", av[1]);
- masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
- i = do_cmd(IP_FW_DEL, masks, sizeof(uint32_t));
+ i = do_range_cmd(cmd, &rt);
} else if (_substrcmp(*av, "disable") == 0 ||
_substrcmp(*av, "enable") == 0 ) {
int which = _substrcmp(*av, "enable") == 0 ? 1 : 0;
@@ -2082,9 +2226,11 @@ ipfw_sets_handler(char *av[])
errx(EX_DATAERR,
"cannot enable and disable the same set\n");
- i = do_cmd(IP_FW_DEL, masks, sizeof(masks));
+ rt.set = masks[0];
+ rt.new_set = masks[1];
+ i = do_range_cmd(IP_FW_SET_ENABLE, &rt);
if (i)
- warn("set enable/disable: setsockopt(IP_FW_DEL)");
+ warn("set enable/disable: setsockopt(IP_FW_SET_ENABLE)");
} else
errx(EX_USAGE, "invalid set command %s\n", *av);
}
@@ -2122,30 +2268,204 @@ ipfw_sysctl_handler(char *av[], int which)
}
}
+typedef void state_cb(struct cmdline_opts *co, struct format_opts *fo,
+ void *arg, void *state);
+
+static void
+prepare_format_dyn(struct cmdline_opts *co, struct format_opts *fo,
+ void *arg, void *_state)
+{
+ ipfw_dyn_rule *d;
+ int width;
+ uint8_t set;
+
+ d = (ipfw_dyn_rule *)_state;
+ /* Count _ALL_ states */
+ fo->dcnt++;
+
+ if (fo->show_counters == 0)
+ return;
+
+ if (co->use_set) {
+ /* skip states from another set */
+ bcopy((char *)&d->rule + sizeof(uint16_t), &set,
+ sizeof(uint8_t));
+ if (set != co->use_set - 1)
+ return;
+ }
+
+ width = pr_u64(NULL, &d->pcnt, 0);
+ if (width > fo->pcwidth)
+ fo->pcwidth = width;
+
+ width = pr_u64(NULL, &d->bcnt, 0);
+ if (width > fo->bcwidth)
+ fo->bcwidth = width;
+}
+
+static int
+foreach_state(struct cmdline_opts *co, struct format_opts *fo,
+ caddr_t base, size_t sz, state_cb dyn_bc, void *dyn_arg)
+{
+ int ttype;
+ state_cb *fptr;
+ void *farg;
+ ipfw_obj_tlv *tlv;
+ ipfw_obj_ctlv *ctlv;
+
+ fptr = NULL;
+ ttype = 0;
+
+ while (sz > 0) {
+ ctlv = (ipfw_obj_ctlv *)base;
+ switch (ctlv->head.type) {
+ case IPFW_TLV_DYNSTATE_LIST:
+ base += sizeof(*ctlv);
+ sz -= sizeof(*ctlv);
+ ttype = IPFW_TLV_DYN_ENT;
+ fptr = dyn_bc;
+ farg = dyn_arg;
+ break;
+ default:
+ return (sz);
+ }
+
+ while (sz > 0) {
+ tlv = (ipfw_obj_tlv *)base;
+ if (tlv->type != ttype)
+ break;
+
+ fptr(co, fo, farg, tlv + 1);
+ sz -= tlv->length;
+ base += tlv->length;
+ }
+ }
+
+ return (sz);
+}
+
+static void
+prepare_format_opts(struct cmdline_opts *co, struct format_opts *fo,
+ ipfw_obj_tlv *rtlv, int rcnt, caddr_t dynbase, size_t dynsz)
+{
+ int bcwidth, pcwidth, width;
+ int n;
+ struct ip_fw_bcounter *cntr;
+ struct ip_fw_rule *r;
+
+ bcwidth = 0;
+ pcwidth = 0;
+ if (fo->show_counters != 0) {
+ for (n = 0; n < rcnt; n++,
+ rtlv = (ipfw_obj_tlv *)((caddr_t)rtlv + rtlv->length)) {
+ cntr = (struct ip_fw_bcounter *)(rtlv + 1);
+ r = (struct ip_fw_rule *)((caddr_t)cntr + cntr->size);
+ /* skip rules from another set */
+ if (co->use_set && r->set != co->use_set - 1)
+ continue;
+
+ /* packet counter */
+ width = pr_u64(NULL, &cntr->pcnt, 0);
+ if (width > pcwidth)
+ pcwidth = width;
+
+ /* byte counter */
+ width = pr_u64(NULL, &cntr->bcnt, 0);
+ if (width > bcwidth)
+ bcwidth = width;
+ }
+ }
+ fo->bcwidth = bcwidth;
+ fo->pcwidth = pcwidth;
+
+ fo->dcnt = 0;
+ if (co->do_dynamic && dynsz > 0)
+ foreach_state(co, fo, dynbase, dynsz, prepare_format_dyn, NULL);
+}
+
+static int
+list_static_range(struct cmdline_opts *co, struct format_opts *fo,
+ struct buf_pr *bp, ipfw_obj_tlv *rtlv, int rcnt)
+{
+ int n, seen;
+ struct ip_fw_rule *r;
+ struct ip_fw_bcounter *cntr;
+ int c = 0;
+
+ for (n = seen = 0; n < rcnt; n++,
+ rtlv = (ipfw_obj_tlv *)((caddr_t)rtlv + rtlv->length)) {
+
+ if (fo->show_counters != 0) {
+ cntr = (struct ip_fw_bcounter *)(rtlv + 1);
+ r = (struct ip_fw_rule *)((caddr_t)cntr + cntr->size);
+ } else {
+ cntr = NULL;
+ r = (struct ip_fw_rule *)(rtlv + 1);
+ }
+ if (r->rulenum > fo->last)
+ break;
+ if (co->use_set && r->set != co->use_set - 1)
+ continue;
+ if (r->rulenum >= fo->first && r->rulenum <= fo->last) {
+ show_static_rule(co, fo, bp, r, cntr);
+ printf("%s", bp->buf);
+ c += rtlv->length;
+ bp_flush(bp);
+ seen++;
+ }
+ }
+
+ return (seen);
+}
+
+static void
+list_dyn_state(struct cmdline_opts *co, struct format_opts *fo,
+ void *_arg, void *_state)
+{
+ uint16_t rulenum;
+ uint8_t set;
+ ipfw_dyn_rule *d;
+ struct buf_pr *bp;
+
+ d = (ipfw_dyn_rule *)_state;
+ bp = (struct buf_pr *)_arg;
+
+ bcopy(&d->rule, &rulenum, sizeof(rulenum));
+ if (rulenum > fo->last)
+ return;
+ if (co->use_set) {
+ bcopy((char *)&d->rule + sizeof(uint16_t),
+ &set, sizeof(uint8_t));
+ if (set != co->use_set - 1)
+ return;
+ }
+ if (rulenum >= fo->first) {
+ show_dyn_state(co, fo, bp, d);
+ printf("%s\n", bp->buf);
+ bp_flush(bp);
+ }
+}
+
+static int
+list_dyn_range(struct cmdline_opts *co, struct format_opts *fo,
+ struct buf_pr *bp, caddr_t base, size_t sz)
+{
+
+ sz = foreach_state(co, fo, base, sz, list_dyn_state, bp);
+ return (sz);
+}
+
void
ipfw_list(int ac, char *av[], int show_counters)
{
- struct ip_fw *r;
- ipfw_dyn_rule *dynrules, *d;
-
-#define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r)))
- char *lim;
- void *data = NULL;
- int bcwidth, n, nbytes, nstat, ndyn, pcwidth, width;
- int exitval = EX_OK;
+ ipfw_cfg_lheader *cfg;
+ struct format_opts sfo;
+ size_t sz;
+ int error;
int lac;
char **lav;
- u_long rnum, last;
+ uint32_t rnum;
char *endptr;
- struct format_opts fo;
- struct buf_pr bp;
- int seen = 0;
- uint8_t set;
-
- const int ocmd = co.do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
- int nalloc = 1024; /* start somewhere... */
-
- last = 0;
if (co.test_only) {
fprintf(stderr, "Testing only, list disabled\n");
@@ -2158,176 +2478,215 @@ ipfw_list(int ac, char *av[], int show_counters)
ac--;
av++;
+ memset(&sfo, 0, sizeof(sfo));
- /* get rules or pipes from kernel, resizing array as necessary */
- nbytes = nalloc;
+ /* Determine rule range to request */
+ if (ac > 0) {
+ for (lac = ac, lav = av; lac != 0; lac--) {
+ rnum = strtoul(*lav++, &endptr, 10);
+ if (sfo.first == 0 || rnum < sfo.first)
+ sfo.first = rnum;
- while (nbytes >= nalloc) {
- nalloc = nalloc * 2 + 200;
- nbytes = nalloc;
- data = safe_realloc(data, nbytes);
- if (do_cmd(ocmd, data, (uintptr_t)&nbytes) < 0)
- err(EX_OSERR, "getsockopt(IP_%s_GET)",
- co.do_pipe ? "DUMMYNET" : "FW");
+ if (*endptr == '-')
+ rnum = strtoul(endptr + 1, &endptr, 10);
+ if (sfo.last == 0 || rnum > sfo.last)
+ sfo.last = rnum;
+ }
}
- /*
- * Count static rules. They have variable size so we
- * need to scan the list to count them.
- */
- for (nstat = 1, r = data, lim = (char *)data + nbytes;
- r->rulenum < IPFW_DEFAULT_RULE && (char *)r < lim;
- ++nstat, r = NEXT(r) )
- ; /* nothing */
+ /* get configuraion from kernel */
+ cfg = NULL;
+ sfo.show_counters = show_counters;
+ sfo.flags = IPFW_CFG_GET_STATIC;
+ if (co.do_dynamic != 0)
+ sfo.flags |= IPFW_CFG_GET_STATES;
+ if (sfo.show_counters != 0)
+ sfo.flags |= IPFW_CFG_GET_COUNTERS;
+ if (ipfw_get_config(&co, &sfo, &cfg, &sz) != 0)
+ err(EX_OSERR, "retrieving config failed");
+
+ error = ipfw_show_config(&co, &sfo, cfg, sz, ac, av);
+
+ free(cfg);
+
+ if (error != EX_OK)
+ exit(error);
+}
+
+static int
+ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
+ ipfw_cfg_lheader *cfg, size_t sz, int ac, char *av[])
+{
+ caddr_t dynbase;
+ size_t dynsz;
+ int rcnt;
+ int exitval = EX_OK;
+ int lac;
+ char **lav;
+ char *endptr;
+ size_t read;
+ struct buf_pr bp;
+ ipfw_obj_ctlv *ctlv, *tstate;
+ ipfw_obj_tlv *rbase;
/*
- * Count dynamic rules. This is easier as they have
- * fixed size.
+ * Handle tablenames TLV first, if any
*/
- r = NEXT(r);
- dynrules = (ipfw_dyn_rule *)r ;
- n = (char *)r - (char *)data;
- ndyn = (nbytes - n) / sizeof *dynrules;
-
- /* if showing stats, figure out column widths ahead of time */
- bcwidth = pcwidth = 0;
- if (show_counters) {
- for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) {
- /* skip rules from another set */
- if (co.use_set && r->set != co.use_set - 1)
- continue;
-
- /* packet counter */
- width = pr_u64(&bp, &r->pcnt, 0);
- if (width > pcwidth)
- pcwidth = width;
+ tstate = NULL;
+ rbase = NULL;
+ dynbase = NULL;
+ dynsz = 0;
+ read = sizeof(*cfg);
+
+ fo->set_mask = cfg->set_mask;
+
+ ctlv = (ipfw_obj_ctlv *)(cfg + 1);
+
+ if (cfg->flags & IPFW_CFG_GET_STATIC) {
+ /* We've requested static rules */
+ if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
+ fo->tstate = ctlv;
+ read += ctlv->head.length;
+ ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
+ ctlv->head.length);
+ }
- /* byte counter */
- width = pr_u64(&bp, &r->bcnt, 0);
- if (width > bcwidth)
- bcwidth = width;
+ if (ctlv->head.type == IPFW_TLV_RULE_LIST) {
+ rbase = (ipfw_obj_tlv *)(ctlv + 1);
+ rcnt = ctlv->count;
+ read += ctlv->head.length;
+ ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
+ ctlv->head.length);
}
}
- if (co.do_dynamic && ndyn) {
- for (n = 0, d = dynrules; n < ndyn; n++, d++) {
- if (co.use_set) {
- /* skip rules from another set */
- bcopy((char *)&d->rule + sizeof(uint16_t),
- &set, sizeof(uint8_t));
- if (set != co.use_set - 1)
- continue;
- }
- width = pr_u64(&bp, &d->pcnt, 0);
- if (width > pcwidth)
- pcwidth = width;
- width = pr_u64(&bp, &d->bcnt, 0);
- if (width > bcwidth)
- bcwidth = width;
- }
+ if ((cfg->flags & IPFW_CFG_GET_STATES) && (read != sz)) {
+ /* We may have some dynamic states */
+ dynsz = sz - read;
+ /* Skip empty header */
+ if (dynsz != sizeof(ipfw_obj_ctlv))
+ dynbase = (caddr_t)ctlv;
+ else
+ dynsz = 0;
}
- memset(&fo, 0, sizeof(fo));
- fo.pcwidth = pcwidth;
- fo.bcwidth = bcwidth;
+ prepare_format_opts(co, fo, rbase, rcnt, dynbase, dynsz);
bp_alloc(&bp, 4096);
+
/* if no rule numbers were specified, list all rules */
if (ac == 0) {
- for (n = 0, r = data; n < nstat; n++, r = NEXT(r)) {
- if (co.use_set && r->set != co.use_set - 1)
- continue;
- show_static_rule(&co, &fo, &bp, r, r);
- printf("%s", bp.buf);
- bp_flush(&bp);
- }
+ fo->first = 0;
+ fo->last = IPFW_DEFAULT_RULE;
+ list_static_range(co, fo, &bp, rbase, rcnt);
- if (co.do_dynamic && ndyn) {
- printf("## Dynamic rules (%d):\n", ndyn);
- for (n = 0, d = dynrules; n < ndyn; n++, d++) {
- if (co.use_set) {
- bcopy((char *)&d->rule + sizeof(uint16_t),
- &set, sizeof(uint8_t));
- if (set != co.use_set - 1)
- continue;
- }
- show_dyn_state(&co, &fo, &bp, d);
- printf("%s\n", bp.buf);
- bp_flush(&bp);
- }
+ if (co->do_dynamic && dynsz > 0) {
+ printf("## Dynamic rules (%d %lu):\n", fo->dcnt, dynsz);
+ list_dyn_range(co, fo, &bp, dynbase, dynsz);
}
- goto done;
+
+ bp_free(&bp);
+ return (EX_OK);
}
/* display specific rules requested on command line */
-
for (lac = ac, lav = av; lac != 0; lac--) {
/* convert command line rule # */
- last = rnum = strtoul(*lav++, &endptr, 10);
+ fo->last = fo->first = strtoul(*lav++, &endptr, 10);
if (*endptr == '-')
- last = strtoul(endptr+1, &endptr, 10);
+ fo->last = strtoul(endptr + 1, &endptr, 10);
if (*endptr) {
exitval = EX_USAGE;
warnx("invalid rule number: %s", *(lav - 1));
continue;
}
- for (n = seen = 0, r = data; n < nstat; n++, r = NEXT(r) ) {
- if (r->rulenum > last)
- break;
- if (co.use_set && r->set != co.use_set - 1)
- continue;
- if (r->rulenum >= rnum && r->rulenum <= last) {
- show_static_rule(&co, &fo, &bp, r, r);
- printf("%s", bp.buf);
- bp_flush(&bp);
- seen = 1;
- }
- }
- if (!seen) {
+
+ if (list_static_range(co, fo, &bp, rbase, rcnt) == 0) {
/* give precedence to other error(s) */
if (exitval == EX_OK)
exitval = EX_UNAVAILABLE;
- warnx("rule %lu does not exist", rnum);
+ if (fo->first == fo->last)
+ warnx("rule %u does not exist", fo->first);
+ else
+ warnx("no rules in range %u-%u",
+ fo->first, fo->last);
}
}
- if (co.do_dynamic && ndyn) {
+ if (co->do_dynamic && dynsz > 0) {
printf("## Dynamic rules:\n");
for (lac = ac, lav = av; lac != 0; lac--) {
- last = rnum = strtoul(*lav++, &endptr, 10);
+ fo->last = fo->first = strtoul(*lav++, &endptr, 10);
if (*endptr == '-')
- last = strtoul(endptr+1, &endptr, 10);
+ fo->last = strtoul(endptr+1, &endptr, 10);
if (*endptr)
/* already warned */
continue;
- for (n = 0, d = dynrules; n < ndyn; n++, d++) {
- uint16_t rulenum;
-
- bcopy(&d->rule, &rulenum, sizeof(rulenum));
- if (rulenum > rnum)
- break;
- if (co.use_set) {
- bcopy((char *)&d->rule + sizeof(uint16_t),
- &set, sizeof(uint8_t));
- if (set != co.use_set - 1)
- continue;
- }
- if (r->rulenum >= rnum && r->rulenum <= last) {
- show_dyn_state(&co, &fo, &bp, d);
- printf("%s\n", bp.buf);
- bp_flush(&bp);
- }
- }
+ list_dyn_range(co, fo, &bp, dynbase, dynsz);
}
}
- ac = 0;
+ bp_free(&bp);
+ return (exitval);
+}
-done:
- free(data);
- if (exitval != EX_OK)
- exit(exitval);
-#undef NEXT
+/*
+ * Retrieves current ipfw configuration of given type
+ * and stores its pointer to @pcfg.
+ *
+ * Caller is responsible for freeing @pcfg.
+ *
+ * Returns 0 on success.
+ */
+
+static int
+ipfw_get_config(struct cmdline_opts *co, struct format_opts *fo,
+ ipfw_cfg_lheader **pcfg, size_t *psize)
+{
+ ipfw_cfg_lheader *cfg;
+ size_t sz;
+ int i;
+
+
+ if (co->test_only != 0) {
+ fprintf(stderr, "Testing only, list disabled\n");
+ return (0);
+ }
+
+ /* Start with some data size */
+ sz = 4096;
+ cfg = NULL;
+
+ for (i = 0; i < 16; i++) {
+ if (cfg != NULL)
+ free(cfg);
+ if ((cfg = calloc(1, sz)) == NULL)
+ return (ENOMEM);
+
+ cfg->flags = fo->flags;
+ cfg->start_rule = fo->first;
+ cfg->end_rule = fo->last;
+
+ if (do_get3(IP_FW_XGET, &cfg->opheader, &sz) != 0) {
+ if (errno != ENOMEM) {
+ free(cfg);
+ return (errno);
+ }
+
+ /* Buffer size is not enough. Try to increase */
+ sz = sz * 2;
+ if (sz < cfg->size)
+ sz = cfg->size;
+ continue;
+ }
+
+ *pcfg = cfg;
+ *psize = sz;
+ return (0);
+ }
+
+ free(cfg);
+ return (ENOMEM);
}
static int
@@ -2343,6 +2702,79 @@ lookup_host (char *host, struct in_addr *ipaddr)
return(0);
}
+struct tidx {
+ ipfw_obj_ntlv *idx;
+ uint32_t count;
+ uint32_t size;
+ uint16_t counter;
+ uint8_t set;
+};
+
+static uint16_t
+pack_table(struct tidx *tstate, char *name)
+{
+ int i;
+ ipfw_obj_ntlv *ntlv;
+
+ if (table_check_name(name) != 0)
+ return (0);
+
+ for (i = 0; i < tstate->count; i++) {
+ if (strcmp(tstate->idx[i].name, name) != 0)
+ continue;
+ if (tstate->idx[i].set != tstate->set)
+ continue;
+
+ return (tstate->idx[i].idx);
+ }
+
+ if (tstate->count + 1 > tstate->size) {
+ tstate->size += 4;
+ tstate->idx = realloc(tstate->idx, tstate->size *
+ sizeof(ipfw_obj_ntlv));
+ if (tstate->idx == NULL)
+ return (0);
+ }
+
+ ntlv = &tstate->idx[i];
+ memset(ntlv, 0, sizeof(ipfw_obj_ntlv));
+ strlcpy(ntlv->name, name, sizeof(ntlv->name));
+ ntlv->head.type = IPFW_TLV_TBL_NAME;
+ ntlv->head.length = sizeof(ipfw_obj_ntlv);
+ ntlv->set = tstate->set;
+ ntlv->idx = ++tstate->counter;
+ tstate->count++;
+
+ return (ntlv->idx);
+}
+
+static void
+fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate)
+{
+ uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
+ uint16_t uidx;
+ char *p;
+
+ if ((p = strchr(av + 6, ')')) == NULL)
+ errx(EX_DATAERR, "forgotten parenthesis: '%s'", av);
+ *p = '\0';
+ p = strchr(av + 6, ',');
+ if (p)
+ *p++ = '\0';
+
+ if ((uidx = pack_table(tstate, av + 6)) == 0)
+ errx(EX_DATAERR, "Invalid table name: %s", av + 6);
+
+ cmd->opcode = opcode;
+ cmd->arg1 = uidx;
+ if (p) {
+ cmd->len |= F_INSN_SIZE(ipfw_insn_u32);
+ d[0] = strtoul(p, NULL, 0);
+ } else
+ cmd->len |= F_INSN_SIZE(ipfw_insn);
+}
+
+
/*
* fills the addr and mask fields in the instruction as appropriate from av.
* Update length as appropriate.
@@ -2359,7 +2791,6 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen, struct tidx *tstate)
{
int len = 0;
uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
- uint32_t tables_max;
cmd->o.len &= ~F_LEN_MASK; /* zero len */
@@ -2372,21 +2803,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen, struct tidx *tstate)
}
if (strncmp(av, "table(", 6) == 0) {
- char *p = strchr(av + 6, ',');
-
- if (p)
- *p++ = '\0';
- cmd->o.opcode = O_IP_DST_LOOKUP;
- cmd->o.arg1 = strtoul(av + 6, NULL, 0);
- tables_max = ipfw_get_tables_max();
- if (cmd->o.arg1 > tables_max)
- errx(EX_USAGE, "The table number exceeds the maximum "
- "allowed value (%u)", tables_max - 1);
- if (p) {
- cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
- d[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;
}
@@ -2567,17 +2984,16 @@ n2mask(struct in6_addr *mask, int n)
return;
}
-/*
- * helper function to process a set of flags and set bits in the
- * appropriate masks.
- */
static void
fill_flags_cmd(ipfw_insn *cmd, enum ipfw_opcodes opcode,
struct _s_x *flags, char *p)
{
- uint8_t set = 0, clear = 0;
+ char *e;
+ uint32_t set = 0, clear = 0;
+
+ if (fill_flags(flags, p, &e, &set, &clear) != 0)
+ errx(EX_DATAERR, "invalid flag %s", e);
- fill_flags(flags, p, &set, &clear);
cmd->opcode = opcode;
cmd->len = (cmd->len & (F_NOT | F_OR)) | 1;
cmd->arg1 = (set & 0xff) | ( (clear & 0xff) << 8);
@@ -2591,9 +3007,11 @@ ipfw_delete(char *av[])
int i;
int exitval = EX_OK;
int do_set = 0;
+ ipfw_range_tlv rt;
av++;
NEED1("missing rule specification");
+ memset(&rt, 0, sizeof(rt));
if ( *av && _substrcmp(*av, "set") == 0) {
/* Do not allow using the following syntax:
* ipfw set N delete set M
@@ -2616,15 +3034,25 @@ ipfw_delete(char *av[])
} else if (co.do_pipe) {
exitval = ipfw_delete_pipe(co.do_pipe, i);
} else {
- if (co.use_set)
- rulenum = (i & 0xffff) | (5 << 24) |
- ((co.use_set - 1) << 16);
- else
- rulenum = (i & 0xffff) | (do_set << 24);
- i = do_cmd(IP_FW_DEL, &rulenum, sizeof rulenum);
- if (i) {
+ if (do_set != 0) {
+ rt.set = i & 31;
+ rt.flags = IPFW_RCFLAG_SET;
+ } else {
+ rt.start_rule = i & 0xffff;
+ rt.end_rule = i & 0xffff;
+ if (rt.start_rule == 0 && rt.end_rule == 0)
+ rt.flags |= IPFW_RCFLAG_ALL;
+ else
+ rt.flags |= IPFW_RCFLAG_RANGE;
+ if (co.use_set != 0) {
+ rt.set = co.use_set - 1;
+ rt.flags |= IPFW_RCFLAG_SET;
+ }
+ }
+ i = do_range_cmd(IP_FW_XDEL, &rt);
+ if (i != 0) {
exitval = EX_UNAVAILABLE;
- warn("rule %u: setsockopt(IP_FW_DEL)",
+ warn("rule %u: setsockopt(IP_FW_XDEL)",
rulenum);
}
}
@@ -2644,6 +3072,9 @@ ipfw_delete(char *av[])
static void
fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate)
{
+ char *p;
+ uint16_t uidx;
+
cmd->name[0] = '\0';
cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
@@ -2653,11 +3084,17 @@ fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate)
if (strcmp(arg, "any") == 0)
cmd->o.len = 0; /* effectively ignore this command */
else if (strncmp(arg, "table(", 6) == 0) {
- char *p = strchr(arg + 6, ',');
+ if ((p = strchr(arg + 6, ')')) == NULL)
+ errx(EX_DATAERR, "forgotten parenthesis: '%s'", arg);
+ *p = '\0';
+ p = strchr(arg + 6, ',');
if (p)
*p++ = '\0';
+ if ((uidx = pack_table(tstate, arg + 6)) == 0)
+ errx(EX_DATAERR, "Invalid table name: %s", arg + 6);
+
cmd->name[0] = '\1'; /* Special value indicating table */
- cmd->p.glob = strtoul(arg + 6, NULL, 0);
+ cmd->p.kidx = uidx;
} else if (!isdigit(*arg)) {
strlcpy(cmd->name, arg, sizeof(cmd->name));
cmd->p.glob = strpbrk(arg, "*?[") != NULL ? 1 : 0;
@@ -2904,13 +3341,34 @@ add_dstip(ipfw_insn *cmd, char *av, int cblen, struct tidx *tstate)
return cmd;
}
+static struct _s_x f_reserved_keywords[] = {
+ { "altq", TOK_OR },
+ { "//", TOK_OR },
+ { "diverted", TOK_OR },
+ { "dst-port", TOK_OR },
+ { "src-port", TOK_OR },
+ { "established", TOK_OR },
+ { "keep-state", TOK_OR },
+ { "frag", TOK_OR },
+ { "icmptypes", TOK_OR },
+ { "in", TOK_OR },
+ { "out", TOK_OR },
+ { "ip6", TOK_OR },
+ { "any", TOK_OR },
+ { "to", TOK_OR },
+ { "via", TOK_OR },
+ { "{", TOK_OR },
+ { NULL, 0 } /* terminator */
+};
+
static ipfw_insn *
add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode, int cblen)
{
- /* XXX "any" is trapped before. Perhaps "to" */
- if (_substrcmp(av, "any") == 0) {
- return NULL;
- } else if (fill_newports((ipfw_insn_u16 *)cmd, av, proto, cblen)) {
+
+ if (match_token(f_reserved_keywords, av) != -1)
+ return (NULL);
+
+ if (fill_newports((ipfw_insn_u16 *)cmd, av, proto, cblen)) {
/* XXX todo: check that we have a protocol with ports */
cmd->opcode = opcode;
return cmd;
@@ -2993,7 +3451,7 @@ add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen, struct tidx *tstate)
*
*/
void
-ipfw_add(char *av[])
+compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
{
/*
* rules are added into the 'rulebuf' and then copied in
@@ -3001,8 +3459,7 @@ ipfw_add(char *av[])
* Some things that need to go out of order (prob, action etc.)
* go into actbuf[].
*/
- static uint32_t rulebuf[255], actbuf[255], cmdbuf[255];
- void *tstate = NULL;
+ static uint32_t actbuf[255], cmdbuf[255];
int rblen, ablen, cblen;
ipfw_insn *src, *dst, *cmd, *action, *prev=NULL;
@@ -3028,14 +3485,14 @@ ipfw_add(char *av[])
bzero(actbuf, sizeof(actbuf)); /* actions go here */
bzero(cmdbuf, sizeof(cmdbuf));
- bzero(rulebuf, sizeof(rulebuf));
+ bzero(rbuf, *rbufsize);
- rule = (struct ip_fw *)rulebuf;
+ rule = (struct ip_fw_rule *)rbuf;
cmd = (ipfw_insn *)cmdbuf;
action = (ipfw_insn *)actbuf;
- rblen = sizeof(rulebuf) / sizeof(rulebuf[0]);
- rblen -= offsetof(struct ip_fw, cmd) / sizeof(rulebuf[0]);
+ rblen = *rbufsize / sizeof(uint32_t);
+ rblen -= sizeof(struct ip_fw_rule) / sizeof(uint32_t);
ablen = sizeof(actbuf) / sizeof(actbuf[0]);
cblen = sizeof(cmdbuf) / sizeof(cmdbuf[0]);
cblen -= F_INSN_SIZE(ipfw_insn_u32) + 1;
@@ -3057,6 +3514,7 @@ ipfw_add(char *av[])
if (set < 0 || set > RESVD_SET)
errx(EX_DATAERR, "illegal set %s", av[1]);
rule->set = set;
+ tstate->set = set;
av += 2;
}
@@ -3162,7 +3620,7 @@ chkarg:
errx(EX_USAGE, "missing argument for %s", *(av - 1));
if (isdigit(**av)) {
action->arg1 = strtoul(*av, NULL, 10);
- if (action->arg1 <= 0 || action->arg1 >= IP_FW_TARG)
+ if (action->arg1 <= 0 || action->arg1 >= IP_FW_TABLEARG)
errx(EX_DATAERR, "illegal argument for %s",
*(av - 1));
} else if (_substrcmp(*av, "tablearg") == 0) {
@@ -3298,6 +3756,8 @@ chkarg:
errx(EX_DATAERR, "fibs not suported.\n");
if (action->arg1 >= numfibs) /* Temporary */
errx(EX_DATAERR, "fib too large.\n");
+ /* Add high-order bit to fib to make room for tablearg*/
+ action->arg1 |= 0x8000;
}
av++;
break;
@@ -3317,6 +3777,9 @@ chkarg:
action->arg1 = code;
} else
action->arg1 = strtoul(*av, NULL, 10);
+ /* Add high-order bit to DSCP to make room for tablearg */
+ if (action->arg1 != IP_FW_TARG)
+ action->arg1 |= 0x8000;
av++;
break;
}
@@ -3588,7 +4051,7 @@ read_options:
* nothing specified so far, store in the rule to ease
* printout later.
*/
- rule->_pad = 1;
+ rule->flags |= IPFW_RULE_NOOPT;
}
prev = NULL;
while ( av[0] != NULL ) {
@@ -4038,7 +4501,6 @@ read_options:
case TOK_LOOKUP: {
ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd;
- char *p;
int j;
if (!av[0] || !av[1])
@@ -4054,12 +4516,22 @@ read_options:
errx(EX_USAGE, "format: cannot lookup on %s", *av);
__PAST_END(c->d, 1) = j; // i converted to option
av++;
- cmd->arg1 = strtoul(*av, &p, 0);
- if (p && *p)
- errx(EX_USAGE, "format: lookup argument tablenum");
+
+ if ((j = pack_table(tstate, *av)) == 0)
+ errx(EX_DATAERR, "Invalid table name: %s", *av);
+
+ cmd->arg1 = j;
av++;
}
break;
+ case TOK_FLOW:
+ NEED1("missing table name");
+ if (strncmp(*av, "table(", 6) != 0)
+ errx(EX_DATAERR,
+ "enclose table name into \"table()\"");
+ fill_table(cmd, *av, O_IP_FLOW_LOOKUP, tstate);
+ av++;
+ break;
default:
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
@@ -4161,19 +4633,113 @@ done:
}
rule->cmd_len = (uint32_t *)dst - (uint32_t *)(rule->cmd);
- i = (char *)dst - (char *)rule;
- if (do_cmd(IP_FW_ADD, rule, (uintptr_t)&i) == -1)
- err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
+ *rbufsize = (char *)dst - (char *)rule;
+}
+
+/*
+ * Adds one or more rules to ipfw chain.
+ * Data layout:
+ * Request:
+ * [
+ * ip_fw3_opheader
+ * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional *1)
+ * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) [ ip_fw_rule ip_fw_insn ] x N ] (*2) (*3)
+ * ]
+ * Reply:
+ * [
+ * ip_fw3_opheader
+ * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional)
+ * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) [ ip_fw_rule ip_fw_insn ] x N ]
+ * ]
+ *
+ * Rules in reply are modified to store their actual ruleset number.
+ *
+ * (*1) TLVs inside IPFW_TLV_TBL_LIST needs to be sorted ascending
+ * accoring to their idx field and there has to be no duplicates.
+ * (*2) Numbered rules inside IPFW_TLV_RULE_LIST needs to be sorted ascending.
+ * (*3) Each ip_fw structure needs to be aligned to u64 boundary.
+ */
+void
+ipfw_add(char *av[])
+{
+ uint32_t rulebuf[1024];
+ int rbufsize, default_off, tlen, rlen;
+ size_t sz;
+ struct tidx ts;
+ struct ip_fw_rule *rule;
+ caddr_t tbuf;
+ ip_fw3_opheader *op3;
+ ipfw_obj_ctlv *ctlv, *tstate;
+
+ rbufsize = sizeof(rulebuf);
+ memset(&ts, 0, sizeof(ts));
+
+ /* Optimize case with no tables */
+ default_off = sizeof(ipfw_obj_ctlv) + sizeof(ip_fw3_opheader);
+ op3 = (ip_fw3_opheader *)rulebuf;
+ ctlv = (ipfw_obj_ctlv *)(op3 + 1);
+ rule = (struct ip_fw_rule *)(ctlv + 1);
+ rbufsize -= default_off;
+
+ compile_rule(av, (uint32_t *)rule, &rbufsize, &ts);
+ /* Align rule size to u64 boundary */
+ rlen = roundup2(rbufsize, sizeof(uint64_t));
+
+ tbuf = NULL;
+ sz = 0;
+ tstate = NULL;
+ if (ts.count != 0) {
+ /* Some tables. We have to alloc more data */
+ tlen = ts.count * sizeof(ipfw_obj_ntlv);
+ sz = default_off + sizeof(ipfw_obj_ctlv) + tlen + rlen;
+
+ if ((tbuf = calloc(1, sz)) == NULL)
+ err(EX_UNAVAILABLE, "malloc() failed for IP_FW_ADD");
+ op3 = (ip_fw3_opheader *)tbuf;
+ /* Tables first */
+ ctlv = (ipfw_obj_ctlv *)(op3 + 1);
+ ctlv->head.type = IPFW_TLV_TBLNAME_LIST;
+ ctlv->head.length = sizeof(ipfw_obj_ctlv) + tlen;
+ ctlv->count = ts.count;
+ ctlv->objsize = sizeof(ipfw_obj_ntlv);
+ memcpy(ctlv + 1, ts.idx, tlen);
+ table_sort_ctlv(ctlv);
+ tstate = ctlv;
+ /* Rule next */
+ ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length);
+ ctlv->head.type = IPFW_TLV_RULE_LIST;
+ ctlv->head.length = sizeof(ipfw_obj_ctlv) + rlen;
+ ctlv->count = 1;
+ memcpy(ctlv + 1, rule, rbufsize);
+ } else {
+ /* Simply add header */
+ sz = rlen + default_off;
+ memset(ctlv, 0, sizeof(*ctlv));
+ ctlv->head.type = IPFW_TLV_RULE_LIST;
+ ctlv->head.length = sizeof(ipfw_obj_ctlv) + rlen;
+ ctlv->count = 1;
+ }
+
+ if (do_get3(IP_FW_XADD, op3, &sz) != 0)
+ err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_XADD");
+
if (!co.do_quiet) {
struct format_opts sfo;
struct buf_pr bp;
memset(&sfo, 0, sizeof(sfo));
+ sfo.tstate = tstate;
sfo.set_mask = (uint32_t)(-1);
bp_alloc(&bp, 4096);
- show_static_rule(&co, &sfo, &bp, rule, rule);
+ show_static_rule(&co, &sfo, &bp, rule, NULL);
printf("%s", bp.buf);
bp_free(&bp);
}
+
+ if (tbuf != NULL)
+ free(tbuf);
+
+ if (ts.idx != NULL)
+ free(ts.idx);
}
/*
@@ -4185,21 +4751,24 @@ done:
void
ipfw_zero(int ac, char *av[], int optname)
{
- uint32_t arg, saved_arg;
+ ipfw_range_tlv rt;
+ uint32_t arg;
int failed = EX_OK;
char const *errstr;
char const *name = optname ? "RESETLOG" : "ZERO";
- optname = optname ? IP_FW_RESETLOG : IP_FW_ZERO;
+ optname = optname ? IP_FW_XRESETLOG : IP_FW_XZERO;
+ memset(&rt, 0, sizeof(rt));
av++; ac--;
- if (!ac) {
+ if (ac == 0) {
/* clear all entries */
- if (do_cmd(optname, NULL, 0) < 0)
- err(EX_UNAVAILABLE, "setsockopt(IP_FW_%s)", name);
+ rt.flags = IPFW_RCFLAG_ALL;
+ if (do_range_cmd(optname, &rt) < 0)
+ err(EX_UNAVAILABLE, "setsockopt(IP_FW_X%s)", name);
if (!co.do_quiet)
- printf("%s.\n", optname == IP_FW_ZERO ?
+ printf("%s.\n", optname == IP_FW_XZERO ?
"Accounting cleared":"Logging counts reset");
return;
@@ -4212,18 +4781,20 @@ ipfw_zero(int ac, char *av[], int optname)
if (errstr)
errx(EX_DATAERR,
"invalid rule number %s\n", *av);
- saved_arg = arg;
- if (co.use_set)
- arg |= (1 << 24) | ((co.use_set - 1) << 16);
- av++;
- ac--;
- if (do_cmd(optname, &arg, sizeof(arg))) {
- warn("rule %u: setsockopt(IP_FW_%s)",
- saved_arg, name);
+ rt.start_rule = arg;
+ rt.end_rule = arg;
+ rt.flags |= IPFW_RCFLAG_RANGE;
+ if (co.use_set != 0) {
+ rt.set = co.use_set - 1;
+ rt.flags |= IPFW_RCFLAG_SET;
+ }
+ if (do_range_cmd(optname, &rt) != 0) {
+ warn("rule %u: setsockopt(IP_FW_X%s)",
+ arg, name);
failed = EX_UNAVAILABLE;
} else if (!co.do_quiet)
- printf("Entry %d %s.\n", saved_arg,
- optname == IP_FW_ZERO ?
+ printf("Entry %d %s.\n", arg,
+ optname == IP_FW_XZERO ?
"cleared" : "logging count reset");
} else {
errx(EX_USAGE, "invalid rule number ``%s''", *av);
@@ -4236,7 +4807,7 @@ ipfw_zero(int ac, char *av[], int optname)
void
ipfw_flush(int force)
{
- int cmd = co.do_pipe ? IP_DUMMYNET_FLUSH : IP_FW_FLUSH;
+ ipfw_range_tlv rt;
if (!force && !co.do_quiet) { /* need to ask user */
int c;
@@ -4258,316 +4829,121 @@ ipfw_flush(int force)
return;
}
/* `ipfw set N flush` - is the same that `ipfw delete set N` */
- if (co.use_set) {
- uint32_t arg = ((co.use_set - 1) & 0xffff) | (1 << 24);
- if (do_cmd(IP_FW_DEL, &arg, sizeof(arg)) < 0)
- err(EX_UNAVAILABLE, "setsockopt(IP_FW_DEL)");
- } else if (do_cmd(cmd, NULL, 0) < 0)
- err(EX_UNAVAILABLE, "setsockopt(IP_%s_FLUSH)",
- co.do_pipe ? "DUMMYNET" : "FW");
+ memset(&rt, 0, sizeof(rt));
+ if (co.use_set != 0) {
+ rt.set = co.use_set - 1;
+ rt.flags = IPFW_RCFLAG_SET;
+ } else
+ rt.flags = IPFW_RCFLAG_ALL;
+ if (do_range_cmd(IP_FW_XDEL, &rt) != 0)
+ err(EX_UNAVAILABLE, "setsockopt(IP_FW_XDEL)");
if (!co.do_quiet)
printf("Flushed all %s.\n", co.do_pipe ? "pipes" : "rules");
}
+static struct _s_x intcmds[] = {
+ { "talist", TOK_TALIST },
+ { "iflist", TOK_IFLIST },
+ { "vlist", TOK_VLIST },
+ { NULL, 0 }
+};
-static void table_list(uint16_t num, int need_header);
-static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
-
-/*
- * Retrieve maximum number of tables supported by ipfw(4) module.
- */
-uint32_t
-ipfw_get_tables_max()
-{
- size_t len;
- uint32_t tables_max;
-
- if (ipfw_tables_max != 0)
- return (ipfw_tables_max);
-
- len = sizeof(tables_max);
- if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
- NULL, 0) == -1) {
- if (co.test_only)
- tables_max = 128; /* Old conservative default */
- else
- errx(1, "Can't determine maximum number of ipfw tables."
- " Perhaps you forgot to load ipfw module?");
- }
-
- ipfw_tables_max = tables_max;
-
- return (ipfw_tables_max);
-}
-
-/*
- * This one handles all table-related commands
- * ipfw table N add addr[/masklen] [value]
- * ipfw table N delete addr[/masklen]
- * ipfw table {N | all} flush
- * ipfw table {N | all} list
- */
void
-ipfw_table_handler(int ac, char *av[])
+ipfw_internal_handler(int ac, char *av[])
{
- ipfw_table_xentry xent;
- int do_add;
- int is_all;
- uint32_t a;
- uint32_t tables_max;
+ int tcmd;
- tables_max = ipfw_get_tables_max();
+ ac--; av++;
+ NEED1("internal cmd required");
- memset(&xent, 0, sizeof(xent));
+ if ((tcmd = match_token(intcmds, *av)) == -1)
+ errx(EX_USAGE, "invalid internal sub-cmd: %s", *av);
- ac--; av++;
- if (ac && isdigit(**av)) {
- xent.tbl = atoi(*av);
- is_all = 0;
- ac--; av++;
- } else if (ac && _substrcmp(*av, "all") == 0) {
- xent.tbl = 0;
- is_all = 1;
- ac--; av++;
- } else
- errx(EX_USAGE, "table number or 'all' keyword required");
- if (xent.tbl >= tables_max)
- errx(EX_USAGE, "The table number exceeds the maximum allowed "
- "value (%d)", tables_max - 1);
- NEED1("table needs command");
- if (is_all && _substrcmp(*av, "list") != 0
- && _substrcmp(*av, "flush") != 0)
- errx(EX_USAGE, "table number required");
-
- if (_substrcmp(*av, "add") == 0 ||
- _substrcmp(*av, "delete") == 0) {
- do_add = **av == 'a';
- ac--; av++;
- if (!ac)
- errx(EX_USAGE, "address required");
-
- table_fill_xentry(*av, &xent);
-
- ac--; av++;
- if (do_add && ac) {
- unsigned int tval;
- /* isdigit is a bit of a hack here.. */
- if (strchr(*av, (int)'.') == NULL && isdigit(**av)) {
- xent.value = strtoul(*av, NULL, 0);
- } else {
- if (lookup_host(*av, (struct in_addr *)&tval) == 0) {
- /* The value must be stored in host order *
- * so that the values < 65k can be distinguished */
- xent.value = ntohl(tval);
- } else {
- errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
- }
- }
- } else
- xent.value = 0;
- if (do_setcmd3(do_add ? IP_FW_TABLE_XADD : IP_FW_TABLE_XDEL,
- &xent, xent.len) < 0) {
- /* If running silent, don't bomb out on these errors. */
- if (!(co.do_quiet && (errno == (do_add ? EEXIST : ESRCH))))
- err(EX_OSERR, "setsockopt(IP_FW_TABLE_%s)",
- do_add ? "XADD" : "XDEL");
- /* In silent mode, react to a failed add by deleting */
- if (do_add) {
- do_setcmd3(IP_FW_TABLE_XDEL, &xent, xent.len);
- if (do_setcmd3(IP_FW_TABLE_XADD, &xent, xent.len) < 0)
- err(EX_OSERR,
- "setsockopt(IP_FW_TABLE_XADD)");
- }
- }
- } else if (_substrcmp(*av, "flush") == 0) {
- a = is_all ? tables_max : (uint32_t)(xent.tbl + 1);
- do {
- if (do_cmd(IP_FW_TABLE_FLUSH, &xent.tbl,
- sizeof(xent.tbl)) < 0)
- err(EX_OSERR, "setsockopt(IP_FW_TABLE_FLUSH)");
- } while (++xent.tbl < a);
- } else if (_substrcmp(*av, "list") == 0) {
- a = is_all ? tables_max : (uint32_t)(xent.tbl + 1);
- do {
- table_list(xent.tbl, is_all);
- } while (++xent.tbl < a);
- } else
- errx(EX_USAGE, "invalid table command %s", *av);
+ switch (tcmd) {
+ case TOK_IFLIST:
+ ipfw_list_tifaces();
+ break;
+ case TOK_TALIST:
+ ipfw_list_ta(ac, av);
+ break;
+ case TOK_VLIST:
+ ipfw_list_values(ac, av);
+ break;
+ }
}
-static void
-table_fill_xentry(char *arg, ipfw_table_xentry *xent)
+static int
+ipfw_get_tracked_ifaces(ipfw_obj_lheader **polh)
{
- int addrlen, mask, masklen, type;
- struct in6_addr *paddr;
- uint32_t *pkey;
- char *p;
- uint32_t key;
-
- mask = 0;
- type = 0;
- addrlen = 0;
- masklen = 0;
-
- /*
- * Let's try to guess type by agrument.
- * Possible types:
- * 1) IPv4[/mask]
- * 2) IPv6[/mask]
- * 3) interface name
- * 4) port, uid/gid or other u32 key (base 10 format)
- * 5) hostname
- */
- paddr = &xent->k.addr6;
- if (ishexnumber(*arg) != 0 || *arg == ':') {
- /* Remove / if exists */
- if ((p = strchr(arg, '/')) != NULL) {
- *p = '\0';
- mask = atoi(p + 1);
- }
-
- if (inet_pton(AF_INET, arg, paddr) == 1) {
- if (p != NULL && mask > 32)
- errx(EX_DATAERR, "bad IPv4 mask width: %s",
- p + 1);
+ ipfw_obj_lheader req, *olh;
+ size_t sz;
- type = IPFW_TABLE_CIDR;
- masklen = p ? mask : 32;
- addrlen = sizeof(struct in_addr);
- } else if (inet_pton(AF_INET6, arg, paddr) == 1) {
- if (IN6_IS_ADDR_V4COMPAT(paddr))
- errx(EX_DATAERR,
- "Use IPv4 instead of v4-compatible");
- if (p != NULL && mask > 128)
- errx(EX_DATAERR, "bad IPv6 mask width: %s",
- p + 1);
-
- type = IPFW_TABLE_CIDR;
- masklen = p ? mask : 128;
- addrlen = sizeof(struct in6_addr);
- } else {
- /* Port or any other key */
- /* Skip non-base 10 entries like 'fa1' */
- key = strtol(arg, &p, 10);
- if (*p == '\0') {
- pkey = (uint32_t *)paddr;
- *pkey = htonl(key);
- type = IPFW_TABLE_CIDR;
- masklen = 32;
- addrlen = sizeof(uint32_t);
- } else if ((p != arg) && (*p == '.')) {
- /*
- * Warn on IPv4 address strings
- * which are "valid" for inet_aton() but not
- * in inet_pton().
- *
- * Typical examples: '10.5' or '10.0.0.05'
- */
- errx(EX_DATAERR,
- "Invalid IPv4 address: %s", arg);
- }
- }
- }
+ memset(&req, 0, sizeof(req));
+ sz = sizeof(req);
- if (type == 0 && strchr(arg, '.') == NULL) {
- /* Assume interface name. Copy significant data only */
- mask = MIN(strlen(arg), IF_NAMESIZE - 1);
- memcpy(xent->k.iface, arg, mask);
- /* Set mask to exact match */
- masklen = 8 * IF_NAMESIZE;
- type = IPFW_TABLE_INTERFACE;
- addrlen = IF_NAMESIZE;
+ if (do_get3(IP_FW_XIFLIST, &req.opheader, &sz) != 0) {
+ if (errno != ENOMEM)
+ return (errno);
}
- if (type == 0) {
- if (lookup_host(arg, (struct in_addr *)paddr) != 0)
- errx(EX_NOHOST, "hostname ``%s'' unknown", arg);
+ sz = req.size;
+ if ((olh = calloc(1, sz)) == NULL)
+ return (ENOMEM);
- masklen = 32;
- type = IPFW_TABLE_CIDR;
- addrlen = sizeof(struct in_addr);
+ olh->size = sz;
+ if (do_get3(IP_FW_XIFLIST, &olh->opheader, &sz) != 0) {
+ free(olh);
+ return (errno);
}
- xent->type = type;
- xent->masklen = masklen;
- xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
+ *polh = olh;
+ return (0);
}
-static void
-table_list(uint16_t num, int need_header)
+static int
+ifinfo_cmp(const void *a, const void *b)
{
- ipfw_xtable *tbl;
- ipfw_table_xentry *xent;
- socklen_t l;
- uint32_t *a, sz, tval;
- char tbuf[128];
- struct in6_addr *addr6;
- ip_fw3_opheader *op3;
+ ipfw_iface_info *ia, *ib;
- /* Prepend value with IP_FW3 header */
- l = sizeof(ip_fw3_opheader) + sizeof(uint32_t);
- op3 = alloca(l);
- /* Zero reserved fields */
- memset(op3, 0, sizeof(ip_fw3_opheader));
- a = (uint32_t *)(op3 + 1);
- *a = num;
- op3->opcode = IP_FW_TABLE_XGETSIZE;
- if (do_cmd(IP_FW3, op3, (uintptr_t)&l) < 0)
- err(EX_OSERR, "getsockopt(IP_FW_TABLE_XGETSIZE)");
-
- /* If a is zero we have nothing to do, the table is empty. */
- if (*a == 0)
- return;
+ ia = (ipfw_iface_info *)a;
+ ib = (ipfw_iface_info *)b;
- l = *a;
- tbl = safe_calloc(1, l);
- tbl->opheader.opcode = IP_FW_TABLE_XLIST;
- tbl->tbl = num;
- if (do_cmd(IP_FW3, tbl, (uintptr_t)&l) < 0)
- err(EX_OSERR, "getsockopt(IP_FW_TABLE_XLIST)");
- if (tbl->cnt && need_header)
- printf("---table(%d)---\n", tbl->tbl);
- sz = tbl->size - sizeof(ipfw_xtable);
- xent = &tbl->xent[0];
- while (sz > 0) {
- switch (tbl->type) {
- case IPFW_TABLE_CIDR:
- /* IPv4 or IPv6 prefixes */
- tval = xent->value;
- addr6 = &xent->k.addr6;
+ return (stringnum_cmp(ia->ifname, ib->ifname));
+}
+
+/*
+ * Retrieves table list from kernel,
+ * optionally sorts it and calls requested function for each table.
+ * Returns 0 on success.
+ */
+static void
+ipfw_list_tifaces()
+{
+ ipfw_obj_lheader *olh;
+ ipfw_iface_info *info;
+ int i, error;
+ if ((error = ipfw_get_tracked_ifaces(&olh)) != 0)
+ err(EX_OSERR, "Unable to request ipfw tracked interface list");
- if ((xent->flags & IPFW_TCF_INET) != 0) {
- /* IPv4 address */
- inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf));
- } else {
- /* IPv6 address */
- inet_ntop(AF_INET6, addr6, tbuf, sizeof(tbuf));
- }
- if (co.do_value_as_ip) {
- tval = htonl(tval);
- printf("%s/%u %s\n", tbuf, xent->masklen,
- inet_ntoa(*(struct in_addr *)&tval));
- } else
- printf("%s/%u %u\n", tbuf, xent->masklen, tval);
- break;
- case IPFW_TABLE_INTERFACE:
- /* Interface names */
- tval = xent->value;
- if (co.do_value_as_ip) {
- tval = htonl(tval);
- printf("%s %s\n", xent->k.iface,
- inet_ntoa(*(struct in_addr *)&tval));
- } else
- printf("%s %u\n", xent->k.iface, tval);
- }
+ qsort(olh + 1, olh->count, olh->objsize, ifinfo_cmp);
- if (sz < xent->len)
- break;
- sz -= xent->len;
- xent = (ipfw_table_xentry *)((char *)xent + xent->len);
+ info = (ipfw_iface_info *)(olh + 1);
+ for (i = 0; i < olh->count; i++) {
+ if (info->flags & IPFW_IFFLAG_RESOLVED)
+ printf("%s ifindex: %d refcount: %u changes: %u\n",
+ info->ifname, info->ifindex, info->refcnt,
+ info->gencnt);
+ else
+ printf("%s ifindex: unresolved refcount: %u changes: %u\n",
+ info->ifname, info->refcnt, info->gencnt);
+ info = (ipfw_iface_info *)((caddr_t)info + olh->objsize);
}
- free(tbl);
+ free(olh);
}
+
+
+
+
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 7a4e7a3..80970ef 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -207,7 +207,28 @@ enum tokens {
TOK_LOOKUP,
TOK_SOCKARG,
TOK_SETDSCP,
+ TOK_FLOW,
+ TOK_IFLIST,
+ /* Table tokens */
+ TOK_CREATE,
+ TOK_DESTROY,
+ TOK_LIST,
+ TOK_INFO,
+ TOK_DETAIL,
+ TOK_MODIFY,
+ TOK_FLUSH,
+ TOK_SWAP,
+ TOK_ADD,
+ TOK_DEL,
+ TOK_VALTYPE,
+ TOK_ALGO,
+ TOK_TALIST,
+ TOK_ATOMIC,
+ TOK_LOCK,
+ TOK_UNLOCK,
+ TOK_VLIST,
};
+
/*
* the following macro returns an error message if we run out of
* arguments.
@@ -236,14 +257,22 @@ void *safe_realloc(void *ptr, size_t size);
/* string comparison functions used for historical compatibility */
int _substrcmp(const char *str1, const char* str2);
int _substrcmp2(const char *str1, const char* str2, const char* str3);
+int stringnum_cmp(const char *a, const char *b);
/* utility functions */
int match_token(struct _s_x *table, char *string);
+int match_token_relaxed(struct _s_x *table, char *string);
char const *match_value(struct _s_x *p, int value);
+size_t concat_tokens(char *buf, size_t bufsize, struct _s_x *table,
+ char *delimiter);
+int fill_flags(struct _s_x *flags, char *p, char **e, uint32_t *set,
+ uint32_t *clear);
+void print_flags_buffer(char *buf, size_t sz, struct _s_x *list, uint32_t set);
+struct _ip_fw3_opheader;
int do_cmd(int optname, void *optval, uintptr_t optlen);
-
-uint32_t ipfw_get_tables_max(void);
+int do_set3(int optname, struct _ip_fw3_opheader *op3, uintptr_t optlen);
+int do_get3(int optname, struct _ip_fw3_opheader *op3, size_t *optlen);
struct in6_addr;
void n2mask(struct in6_addr *mask, int n);
@@ -282,6 +311,7 @@ void ipfw_delete(char *av[]);
void ipfw_flush(int force);
void ipfw_zero(int ac, char *av[], int optname);
void ipfw_list(int ac, char *av[], int show_counters);
+void ipfw_internal_handler(int ac, char *av[]);
#ifdef PF
/* altq.c */
@@ -311,3 +341,12 @@ void fill_flow6(struct _ipfw_insn_u32 *cmd, char *av, int cblen);
void fill_unreach6_code(u_short *codep, char *str);
void fill_icmp6types(struct _ipfw_insn_icmp6 *cmd, char *av, int cblen);
int fill_ext6hdr(struct _ipfw_insn *cmd, char *av);
+
+/* tables.c */
+struct _ipfw_obj_ctlv;
+char *table_search_ctlv(struct _ipfw_obj_ctlv *ctlv, uint16_t idx);
+void table_sort_ctlv(struct _ipfw_obj_ctlv *ctlv);
+int table_check_name(char *tablename);
+void ipfw_list_ta(int ac, char *av[]);
+void ipfw_list_values(int ac, char *av[]);
+
diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c
index 82a299b..f25578f 100644
--- a/sbin/ipfw/main.c
+++ b/sbin/ipfw/main.c
@@ -436,6 +436,10 @@ ipfw_main(int oldac, char **oldav)
ipfw_list(ac, av, do_acct);
else if (_substrcmp(*av, "show") == 0)
ipfw_list(ac, av, 1 /* show counters */);
+ else if (_substrcmp(*av, "table") == 0)
+ ipfw_table_handler(ac, av);
+ else if (_substrcmp(*av, "internal") == 0)
+ ipfw_internal_handler(ac, av);
else
errx(EX_USAGE, "bad command `%s'", *av);
}
diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c
index bff28e1..3bd0259 100644
--- a/sbin/ipfw/nat.c
+++ b/sbin/ipfw/nat.c
@@ -30,14 +30,13 @@
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
-#define IPFW_INTERNAL /* Access to protected structures in ip_fw.h. */
-
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h> /* def. of struct route */
@@ -46,6 +45,14 @@
#include <arpa/inet.h>
#include <alias.h>
+typedef int (nat_cb_t)(struct nat44_cfg_nat *cfg, void *arg);
+static void nat_show_cfg(struct nat44_cfg_nat *n, void *arg);
+static void nat_show_log(struct nat44_cfg_nat *n, void *arg);
+static int nat_show_data(struct nat44_cfg_nat *cfg, void *arg);
+static int natname_cmp(const void *a, const void *b);
+static int nat_foreach(nat_cb_t *f, void *arg, int sort);
+static int nat_get_cmd(char *name, uint16_t cmd, ipfw_obj_header **ooh);
+
static struct _s_x nat_params[] = {
{ "ip", TOK_IP },
{ "if", TOK_IF },
@@ -71,7 +78,7 @@ static struct _s_x nat_params[] = {
* n->if_name copy of interface name "ifn"
*/
static void
-set_addr_dynamic(const char *ifn, struct cfg_nat *n)
+set_addr_dynamic(const char *ifn, struct nat44_cfg_nat *n)
{
size_t needed;
int mib[6];
@@ -288,15 +295,15 @@ StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto,
* and SetupProtoRedirect() from natd.c.
*
* Every setup_* function fills at least one redirect entry
- * (struct cfg_redir) and zero or more server pool entry (struct cfg_spool)
- * in buf.
+ * (struct nat44_cfg_redir) and zero or more server pool entry
+ * (struct nat44_cfg_spool) in buf.
*
* The format of data in buf is:
*
- * cfg_nat cfg_redir cfg_spool ...... cfg_spool
+ * nat44_cfg_nat nat44_cfg_redir nat44_cfg_spool ...... nat44_cfg_spool
*
* ------------------------------------- ------------
- * | | .....X ... | | | | .....
+ * | | .....X ..... | | | | .....
* ------------------------------------- ...... ------------
* ^
* spool_cnt n=0 ...... n=(X-1)
@@ -314,7 +321,7 @@ StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto,
static int
estimate_redir_addr(int *ac, char ***av)
{
- size_t space = sizeof(struct cfg_redir);
+ size_t space = sizeof(struct nat44_cfg_redir);
char *sep = **av;
u_int c = 0;
@@ -327,7 +334,7 @@ estimate_redir_addr(int *ac, char ***av)
if (c > 0)
c++;
- space += c * sizeof(struct cfg_spool);
+ space += c * sizeof(struct nat44_cfg_spool);
return (space);
}
@@ -335,31 +342,31 @@ estimate_redir_addr(int *ac, char ***av)
static int
setup_redir_addr(char *buf, int *ac, char ***av)
{
- struct cfg_redir *r;
+ struct nat44_cfg_redir *r;
char *sep;
size_t space;
- r = (struct cfg_redir *)buf;
+ r = (struct nat44_cfg_redir *)buf;
r->mode = REDIR_ADDR;
- /* Skip cfg_redir at beginning of buf. */
- buf = &buf[sizeof(struct cfg_redir)];
- space = sizeof(struct cfg_redir);
+ /* Skip nat44_cfg_redir at beginning of buf. */
+ buf = &buf[sizeof(struct nat44_cfg_redir)];
+ space = sizeof(struct nat44_cfg_redir);
/* Extract local address. */
if (strchr(**av, ',') != NULL) {
- struct cfg_spool *spool;
+ struct nat44_cfg_spool *spool;
/* Setup LSNAT server pool. */
r->laddr.s_addr = INADDR_NONE;
sep = strtok(**av, ",");
while (sep != NULL) {
- spool = (struct cfg_spool *)buf;
- space += sizeof(struct cfg_spool);
+ spool = (struct nat44_cfg_spool *)buf;
+ space += sizeof(struct nat44_cfg_spool);
StrToAddr(sep, &spool->addr);
spool->port = ~0;
r->spool_cnt++;
- /* Point to the next possible cfg_spool. */
- buf = &buf[sizeof(struct cfg_spool)];
+ /* Point to the next possible nat44_cfg_spool. */
+ buf = &buf[sizeof(struct nat44_cfg_spool)];
sep = strtok(NULL, ",");
}
} else
@@ -376,7 +383,7 @@ setup_redir_addr(char *buf, int *ac, char ***av)
static int
estimate_redir_port(int *ac, char ***av)
{
- size_t space = sizeof(struct cfg_redir);
+ size_t space = sizeof(struct nat44_cfg_redir);
char *sep = **av;
u_int c = 0;
@@ -389,7 +396,7 @@ estimate_redir_port(int *ac, char ***av)
if (c > 0)
c++;
- space += c * sizeof(struct cfg_spool);
+ space += c * sizeof(struct nat44_cfg_spool);
return (space);
}
@@ -397,7 +404,7 @@ estimate_redir_port(int *ac, char ***av)
static int
setup_redir_port(char *buf, int *ac, char ***av)
{
- struct cfg_redir *r;
+ struct nat44_cfg_redir *r;
char *sep, *protoName, *lsnat = NULL;
size_t space;
u_short numLocalPorts;
@@ -405,11 +412,11 @@ setup_redir_port(char *buf, int *ac, char ***av)
numLocalPorts = 0;
- r = (struct cfg_redir *)buf;
+ r = (struct nat44_cfg_redir *)buf;
r->mode = REDIR_PORT;
- /* Skip cfg_redir at beginning of buf. */
- buf = &buf[sizeof(struct cfg_redir)];
- space = sizeof(struct cfg_redir);
+ /* Skip nat44_cfg_redir at beginning of buf. */
+ buf = &buf[sizeof(struct nat44_cfg_redir)];
+ space = sizeof(struct nat44_cfg_redir);
/*
* Extract protocol.
@@ -516,12 +523,12 @@ setup_redir_port(char *buf, int *ac, char ***av)
/* Setup LSNAT server pool. */
if (lsnat != NULL) {
- struct cfg_spool *spool;
+ struct nat44_cfg_spool *spool;
sep = strtok(lsnat, ",");
while (sep != NULL) {
- spool = (struct cfg_spool *)buf;
- space += sizeof(struct cfg_spool);
+ spool = (struct nat44_cfg_spool *)buf;
+ space += sizeof(struct nat44_cfg_spool);
/*
* The sctp nat does not allow the port numbers to
* be mapped to new port numbers. Therefore, no ports
@@ -549,8 +556,8 @@ setup_redir_port(char *buf, int *ac, char ***av)
spool->port = GETLOPORT(portRange);
}
r->spool_cnt++;
- /* Point to the next possible cfg_spool. */
- buf = &buf[sizeof(struct cfg_spool)];
+ /* Point to the next possible nat44_cfg_spool. */
+ buf = &buf[sizeof(struct nat44_cfg_spool)];
sep = strtok(NULL, ",");
}
}
@@ -561,15 +568,15 @@ setup_redir_port(char *buf, int *ac, char ***av)
static int
setup_redir_proto(char *buf, int *ac, char ***av)
{
- struct cfg_redir *r;
+ struct nat44_cfg_redir *r;
struct protoent *protoent;
size_t space;
- r = (struct cfg_redir *)buf;
+ r = (struct nat44_cfg_redir *)buf;
r->mode = REDIR_PROTO;
- /* Skip cfg_redir at beginning of buf. */
- buf = &buf[sizeof(struct cfg_redir)];
- space = sizeof(struct cfg_redir);
+ /* Skip nat44_cfg_redir at beginning of buf. */
+ buf = &buf[sizeof(struct nat44_cfg_redir)];
+ space = sizeof(struct nat44_cfg_redir);
/*
* Extract protocol.
@@ -616,18 +623,28 @@ setup_redir_proto(char *buf, int *ac, char ***av)
}
static void
-print_nat_config(unsigned char *buf)
+nat_show_log(struct nat44_cfg_nat *n, void *arg)
+{
+ char *buf;
+
+ buf = (char *)(n + 1);
+ if (buf[0] != '\0')
+ printf("nat %s: %s\n", n->name, buf);
+}
+
+static void
+nat_show_cfg(struct nat44_cfg_nat *n, void *arg)
{
- struct cfg_nat *n;
int i, cnt, flag, off;
- struct cfg_redir *t;
- struct cfg_spool *s;
+ struct nat44_cfg_redir *t;
+ struct nat44_cfg_spool *s;
+ caddr_t buf;
struct protoent *p;
- n = (struct cfg_nat *)buf;
+ buf = (caddr_t)n;
flag = 1;
- off = sizeof(*n);
- printf("ipfw nat %u config", n->id);
+ off = sizeof(*n);
+ printf("ipfw nat %s config", n->name);
if (strlen(n->if_name) != 0)
printf(" if %s", n->if_name);
else if (n->ip.s_addr != 0)
@@ -661,8 +678,8 @@ print_nat_config(unsigned char *buf)
}
/* Print all the redirect's data configuration. */
for (cnt = 0; cnt < n->redir_cnt; cnt++) {
- t = (struct cfg_redir *)&buf[off];
- off += SOF_REDIR;
+ t = (struct nat44_cfg_redir *)&buf[off];
+ off += sizeof(struct nat44_cfg_redir);
switch (t->mode) {
case REDIR_ADDR:
printf(" redirect_addr");
@@ -670,13 +687,13 @@ print_nat_config(unsigned char *buf)
printf(" %s", inet_ntoa(t->laddr));
else
for (i = 0; i < t->spool_cnt; i++) {
- s = (struct cfg_spool *)&buf[off];
+ s = (struct nat44_cfg_spool *)&buf[off];
if (i)
printf(",");
else
printf(" ");
printf("%s", inet_ntoa(s->addr));
- off += SOF_SPOOL;
+ off += sizeof(struct nat44_cfg_spool);
}
printf(" %s", inet_ntoa(t->paddr));
break;
@@ -690,12 +707,12 @@ print_nat_config(unsigned char *buf)
t->pport_cnt - 1);
} else
for (i=0; i < t->spool_cnt; i++) {
- s = (struct cfg_spool *)&buf[off];
+ s = (struct nat44_cfg_spool *)&buf[off];
if (i)
printf(",");
printf("%s:%u", inet_ntoa(s->addr),
s->port);
- off += SOF_SPOOL;
+ off += sizeof(struct nat44_cfg_spool);
}
printf(" ");
@@ -736,7 +753,8 @@ print_nat_config(unsigned char *buf)
void
ipfw_config_nat(int ac, char **av)
{
- struct cfg_nat *n; /* Nat instance configuration. */
+ ipfw_obj_header *oh;
+ struct nat44_cfg_nat *n; /* Nat instance configuration. */
int i, off, tok, ac1;
char *id, *buf, **av1, *end;
size_t len;
@@ -755,7 +773,7 @@ ipfw_config_nat(int ac, char **av)
if (ac == 0)
errx(EX_DATAERR, "missing option");
- len = sizeof(struct cfg_nat);
+ len = sizeof(*oh) + sizeof(*n);
ac1 = ac;
av1 = av;
while (ac1 > 0) {
@@ -804,7 +822,7 @@ ipfw_config_nat(int ac, char **av)
if (ac1 < 2)
errx(EX_DATAERR, "redirect_proto: "
"not enough arguments");
- len += sizeof(struct cfg_redir);
+ len += sizeof(struct nat44_cfg_redir);
av1 += 2;
ac1 -= 2;
/* Skip optional remoteIP/port */
@@ -825,11 +843,14 @@ ipfw_config_nat(int ac, char **av)
if ((buf = malloc(len)) == NULL)
errx(EX_OSERR, "malloc failed");
- /* Offset in buf: save space for n at the beginning. */
- off = sizeof(*n);
+ /* Offset in buf: save space for header at the beginning. */
+ off = sizeof(*oh) + sizeof(*n);
memset(buf, 0, len);
- n = (struct cfg_nat *)buf;
- n->id = i;
+ oh = (ipfw_obj_header *)buf;
+ n = (struct nat44_cfg_nat *)(oh + 1);
+ oh->ntlv.head.length = sizeof(oh->ntlv);
+ snprintf(oh->ntlv.name, sizeof(oh->ntlv.name), "%d", i);
+ snprintf(n->name, sizeof(n->name), "%d", i);
while (ac > 0) {
tok = match_token(nat_params, *av);
@@ -900,9 +921,9 @@ ipfw_config_nat(int ac, char **av)
}
}
- i = do_cmd(IP_FW_NAT_CFG, buf, off);
- if (i)
- err(1, "setsockopt(%s)", "IP_FW_NAT_CFG");
+ i = do_set3(IP_FW_NAT44_XCONFIG, &oh->opheader, len);
+ if (i != 0)
+ err(1, "setsockopt(%s)", "IP_FW_NAT44_XCONFIG");
if (!co.do_quiet) {
/* After every modification, we show the resultant rule. */
@@ -912,23 +933,147 @@ ipfw_config_nat(int ac, char **av)
}
}
+struct nat_list_arg {
+ uint16_t cmd;
+ int is_all;
+};
+
+static int
+nat_show_data(struct nat44_cfg_nat *cfg, void *arg)
+{
+ struct nat_list_arg *nla;
+ ipfw_obj_header *oh;
+
+ nla = (struct nat_list_arg *)arg;
+
+ switch (nla->cmd) {
+ case IP_FW_NAT44_XGETCONFIG:
+ if (nat_get_cmd(cfg->name, nla->cmd, &oh) != 0) {
+ warnx("Error getting nat instance %s info", cfg->name);
+ break;
+ }
+ nat_show_cfg((struct nat44_cfg_nat *)(oh + 1), NULL);
+ free(oh);
+ break;
+ case IP_FW_NAT44_XGETLOG:
+ if (nat_get_cmd(cfg->name, nla->cmd, &oh) == 0) {
+ nat_show_log((struct nat44_cfg_nat *)(oh + 1), NULL);
+ free(oh);
+ break;
+ }
+ /* Handle error */
+ if (nla->is_all != 0 && errno == ENOENT)
+ break;
+ warn("Error getting nat instance %s info", cfg->name);
+ break;
+ }
+
+ return (0);
+}
+
+/*
+ * Compare nat names.
+ * Honor number comparison.
+ */
+static int
+natname_cmp(const void *a, const void *b)
+{
+ struct nat44_cfg_nat *ia, *ib;
+
+ ia = (struct nat44_cfg_nat *)a;
+ ib = (struct nat44_cfg_nat *)b;
+
+ return (stringnum_cmp(ia->name, ib->name));
+}
+
+/*
+ * Retrieves nat list from kernel,
+ * optionally sorts it and calls requested function for each table.
+ * Returns 0 on success.
+ */
+static int
+nat_foreach(nat_cb_t *f, void *arg, int sort)
+{
+ ipfw_obj_lheader *olh;
+ struct nat44_cfg_nat *cfg;
+ size_t sz;
+ int i, error;
+
+ /* Start with reasonable default */
+ sz = sizeof(*olh) + 16 * sizeof(struct nat44_cfg_nat);
+
+ for (;;) {
+ if ((olh = calloc(1, sz)) == NULL)
+ return (ENOMEM);
+
+ olh->size = sz;
+ if (do_get3(IP_FW_NAT44_LIST_NAT, &olh->opheader, &sz) != 0) {
+ free(olh);
+ if (errno == ENOMEM) {
+ sz = olh->size;
+ continue;
+ }
+ return (errno);
+ }
+
+ if (sort != 0)
+ qsort(olh + 1, olh->count, olh->objsize, natname_cmp);
+
+ cfg = (struct nat44_cfg_nat*)(olh + 1);
+ for (i = 0; i < olh->count; i++) {
+ error = f(cfg, arg); /* Ignore errors for now */
+ cfg = (struct nat44_cfg_nat *)((caddr_t)cfg +
+ olh->objsize);
+ }
+
+ free(olh);
+ break;
+ }
+
+ return (0);
+}
+
+static int
+nat_get_cmd(char *name, uint16_t cmd, ipfw_obj_header **ooh)
+{
+ ipfw_obj_header *oh;
+ struct nat44_cfg_nat *cfg;
+ size_t sz;
+
+ /* Start with reasonable default */
+ sz = sizeof(*oh) + sizeof(*cfg) + 128;
+
+ for (;;) {
+ if ((oh = calloc(1, sz)) == NULL)
+ return (ENOMEM);
+ cfg = (struct nat44_cfg_nat *)(oh + 1);
+ oh->ntlv.head.length = sizeof(oh->ntlv);
+ strlcpy(oh->ntlv.name, name, sizeof(oh->ntlv.name));
+ strlcpy(cfg->name, name, sizeof(cfg->name));
+
+ if (do_get3(cmd, &oh->opheader, &sz) != 0) {
+ sz = cfg->size;
+ free(oh);
+ if (errno == ENOMEM)
+ continue;
+ return (errno);
+ }
+
+ *ooh = oh;
+ break;
+ }
+
+ return (0);
+}
void
ipfw_show_nat(int ac, char **av)
{
- struct cfg_nat *n;
- struct cfg_redir *e;
- int cmd, i, nbytes, do_cfg, do_rule, frule, lrule, nalloc, size;
- int nat_cnt, redir_cnt, r;
- uint8_t *data, *p;
- char *endptr;
-
- do_rule = 0;
- nalloc = 1024;
- size = 0;
- data = NULL;
- frule = 0;
- lrule = IPFW_DEFAULT_RULE; /* max ipfw rule number */
+ ipfw_obj_header *oh;
+ char *name;
+ int cmd;
+ struct nat_list_arg nla;
+
ac--;
av++;
@@ -936,55 +1081,35 @@ ipfw_show_nat(int ac, char **av)
return;
/* Parse parameters. */
- for (cmd = IP_FW_NAT_GET_LOG, do_cfg = 0; ac != 0; ac--, av++) {
+ cmd = 0; /* XXX: Change to IP_FW_NAT44_XGETLOG @ MFC */
+ name = NULL;
+ for ( ; ac != 0; ac--, av++) {
if (!strncmp(av[0], "config", strlen(av[0]))) {
- cmd = IP_FW_NAT_GET_CONFIG, do_cfg = 1;
+ cmd = IP_FW_NAT44_XGETCONFIG;
+ continue;
+ }
+ if (strcmp(av[0], "log") == 0) {
+ cmd = IP_FW_NAT44_XGETLOG;
continue;
}
- /* Convert command line rule #. */
- frule = lrule = strtoul(av[0], &endptr, 10);
- if (*endptr == '-')
- lrule = strtoul(endptr+1, &endptr, 10);
- if (lrule == 0)
- err(EX_USAGE, "invalid rule number: %s", av[0]);
- do_rule = 1;
+ if (name != NULL)
+ err(EX_USAGE,"only one instance name may be specified");
+ name = av[0];
}
- nbytes = nalloc;
- while (nbytes >= nalloc) {
- nalloc = nalloc * 2;
- nbytes = nalloc;
- data = safe_realloc(data, nbytes);
- if (do_cmd(cmd, data, (uintptr_t)&nbytes) < 0)
- err(EX_OSERR, "getsockopt(IP_FW_GET_%s)",
- (cmd == IP_FW_NAT_GET_LOG) ? "LOG" : "CONFIG");
- }
- if (nbytes == 0)
- exit(0);
- if (do_cfg) {
- nat_cnt = *((int *)data);
- for (i = sizeof(nat_cnt); nat_cnt; nat_cnt--) {
- n = (struct cfg_nat *)&data[i];
- if (frule <= n->id && lrule >= n->id)
- print_nat_config(&data[i]);
- i += sizeof(struct cfg_nat);
- for (redir_cnt = 0; redir_cnt < n->redir_cnt; redir_cnt++) {
- e = (struct cfg_redir *)&data[i];
- i += sizeof(struct cfg_redir) + e->spool_cnt *
- sizeof(struct cfg_spool);
- }
- }
+ if (cmd == 0)
+ errx(EX_USAGE, "Please specify action. Available: config,log");
+
+ if (name == NULL) {
+ memset(&nla, 0, sizeof(nla));
+ nla.cmd = cmd;
+ nla.is_all = 1;
+ nat_foreach(nat_show_data, &nla, 1);
} else {
- for (i = 0; 1; i += LIBALIAS_BUF_SIZE + sizeof(int)) {
- p = &data[i];
- if (p == data + nbytes)
- break;
- bcopy(p, &r, sizeof(int));
- if (do_rule) {
- if (!(frule <= r && lrule >= r))
- continue;
- }
- printf("nat %u: %s\n", r, p+sizeof(int));
- }
+ if (nat_get_cmd(name, cmd, &oh) != 0)
+ err(EX_OSERR, "Error getting nat %s instance info", name);
+ nat_show_cfg((struct nat44_cfg_nat *)(oh + 1), NULL);
+ free(oh);
}
}
+
diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c
new file mode 100644
index 0000000..a94e182
--- /dev/null
+++ b/sbin/ipfw/tables.c
@@ -0,0 +1,2012 @@
+/*
+ * Copyright (c) 2014 Yandex LLC
+ * Copyright (c) 2014 Alexander V. Chernikov
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ *
+ * in-kernel ipfw tables support.
+ *
+ * $FreeBSD: projects/ipfw/sbin/ipfw/ipfw2.c 267467 2014-06-14 10:58:39Z melifaro $
+ */
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip_fw.h>
+#include <arpa/inet.h>
+
+#include "ipfw2.h"
+
+static void table_modify_record(ipfw_obj_header *oh, int ac, char *av[],
+ int add, int quiet, int update, int atomic);
+static int table_flush(ipfw_obj_header *oh);
+static int table_destroy(ipfw_obj_header *oh);
+static int table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i);
+static int table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i);
+static int table_do_swap(ipfw_obj_header *oh, char *second);
+static void table_create(ipfw_obj_header *oh, int ac, char *av[]);
+static void table_modify(ipfw_obj_header *oh, int ac, char *av[]);
+static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]);
+static void table_lock(ipfw_obj_header *oh, int lock);
+static int table_swap(ipfw_obj_header *oh, char *second);
+static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i);
+static int table_show_info(ipfw_xtable_info *i, void *arg);
+static void table_fill_ntlv(ipfw_obj_ntlv *ntlv, char *name, uint32_t set,
+ uint16_t uidx);
+
+static int table_flush_one(ipfw_xtable_info *i, void *arg);
+static int table_show_one(ipfw_xtable_info *i, void *arg);
+static int table_do_get_list(ipfw_xtable_info *i, ipfw_obj_header **poh);
+static void table_show_list(ipfw_obj_header *oh, int need_header);
+static void table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent);
+
+static void tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent,
+ char *key, int add, uint8_t *ptype, uint32_t *pvmask, ipfw_xtable_info *xi);
+static void tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent,
+ char *arg, uint8_t type, uint32_t vmask);
+static void table_show_value(char *buf, size_t bufsize, ipfw_table_value *v,
+ uint32_t vmask, int print_ip);
+
+typedef int (table_cb_t)(ipfw_xtable_info *i, void *arg);
+static int tables_foreach(table_cb_t *f, void *arg, int sort);
+
+#ifndef s6_addr32
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+
+static struct _s_x tabletypes[] = {
+ { "addr", IPFW_TABLE_ADDR },
+ { "iface", IPFW_TABLE_INTERFACE },
+ { "number", IPFW_TABLE_NUMBER },
+ { "flow", IPFW_TABLE_FLOW },
+ { NULL, 0 }
+};
+
+static struct _s_x tablevaltypes[] = {
+ { "skipto", IPFW_VTYPE_SKIPTO },
+ { "pipe", IPFW_VTYPE_PIPE },
+ { "fib", IPFW_VTYPE_FIB },
+ { "nat", IPFW_VTYPE_NAT },
+ { "dscp", IPFW_VTYPE_DSCP },
+ { "tag", IPFW_VTYPE_TAG },
+ { "divert", IPFW_VTYPE_DIVERT },
+ { "netgraph", IPFW_VTYPE_NETGRAPH },
+ { "limit", IPFW_VTYPE_LIMIT },
+ { "ipv4", IPFW_VTYPE_NH4 },
+ { "ipv6", IPFW_VTYPE_NH6 },
+ { NULL, 0 }
+};
+
+static struct _s_x tablecmds[] = {
+ { "add", TOK_ADD },
+ { "delete", TOK_DEL },
+ { "create", TOK_CREATE },
+ { "destroy", TOK_DESTROY },
+ { "flush", TOK_FLUSH },
+ { "modify", TOK_MODIFY },
+ { "swap", TOK_SWAP },
+ { "info", TOK_INFO },
+ { "detail", TOK_DETAIL },
+ { "list", TOK_LIST },
+ { "lookup", TOK_LOOKUP },
+ { "atomic", TOK_ATOMIC },
+ { "lock", TOK_LOCK },
+ { "unlock", TOK_UNLOCK },
+ { NULL, 0 }
+};
+
+static int
+lookup_host (char *host, struct in_addr *ipaddr)
+{
+ struct hostent *he;
+
+ if (!inet_aton(host, ipaddr)) {
+ if ((he = gethostbyname(host)) == NULL)
+ return(-1);
+ *ipaddr = *(struct in_addr *)he->h_addr_list[0];
+ }
+ return(0);
+}
+
+static int
+get_token(struct _s_x *table, char *string, char *errbase)
+{
+ int tcmd;
+
+ if ((tcmd = match_token_relaxed(table, string)) < 0)
+ errx(EX_USAGE, "%s %s %s",
+ (tcmd == 0) ? "invalid" : "ambiguous", errbase, string);
+
+ return (tcmd);
+}
+
+/*
+ * This one handles all table-related commands
+ * ipfw table NAME create ...
+ * ipfw table NAME modify ...
+ * ipfw table NAME destroy
+ * ipfw table NAME swap NAME
+ * ipfw table NAME lock
+ * ipfw table NAME unlock
+ * ipfw table NAME add addr[/masklen] [value]
+ * ipfw table NAME add [addr[/masklen] value] [addr[/masklen] value] ..
+ * ipfw table NAME delete addr[/masklen] [addr[/masklen]] ..
+ * ipfw table NAME lookup addr
+ * ipfw table {NAME | all} flush
+ * ipfw table {NAME | all} list
+ * ipfw table {NAME | all} info
+ * ipfw table {NAME | all} detail
+ */
+void
+ipfw_table_handler(int ac, char *av[])
+{
+ int do_add, is_all;
+ int atomic, error, tcmd;
+ ipfw_xtable_info i;
+ ipfw_obj_header oh;
+ char *tablename;
+ uint32_t set;
+ void *arg;
+
+ memset(&oh, 0, sizeof(oh));
+ is_all = 0;
+ if (co.use_set != 0)
+ set = co.use_set - 1;
+ else
+ set = 0;
+
+ ac--; av++;
+ NEED1("table needs name");
+ tablename = *av;
+
+ if (table_check_name(tablename) == 0) {
+ table_fill_ntlv(&oh.ntlv, *av, set, 1);
+ oh.idx = 1;
+ } else {
+ if (strcmp(tablename, "all") == 0)
+ is_all = 1;
+ else
+ errx(EX_USAGE, "table name %s is invalid", tablename);
+ }
+ ac--; av++;
+ NEED1("table needs command");
+
+ tcmd = get_token(tablecmds, *av, "table command");
+ /* Check if atomic operation was requested */
+ atomic = 0;
+ if (tcmd == TOK_ATOMIC) {
+ ac--; av++;
+ NEED1("atomic needs command");
+ tcmd = get_token(tablecmds, *av, "table command");
+ switch (tcmd) {
+ case TOK_ADD:
+ break;
+ default:
+ errx(EX_USAGE, "atomic is not compatible with %s", *av);
+ }
+ atomic = 1;
+ }
+
+ switch (tcmd) {
+ case TOK_LIST:
+ case TOK_INFO:
+ case TOK_DETAIL:
+ case TOK_FLUSH:
+ break;
+ default:
+ if (is_all != 0)
+ errx(EX_USAGE, "table name required");
+ }
+
+ switch (tcmd) {
+ case TOK_ADD:
+ case TOK_DEL:
+ do_add = **av == 'a';
+ ac--; av++;
+ table_modify_record(&oh, ac, av, do_add, co.do_quiet,
+ co.do_quiet, atomic);
+ break;
+ case TOK_CREATE:
+ ac--; av++;
+ table_create(&oh, ac, av);
+ break;
+ case TOK_MODIFY:
+ ac--; av++;
+ table_modify(&oh, ac, av);
+ break;
+ case TOK_DESTROY:
+ if (table_destroy(&oh) != 0)
+ err(EX_OSERR, "failed to destroy table %s", tablename);
+ break;
+ case TOK_FLUSH:
+ if (is_all == 0) {
+ if ((error = table_flush(&oh)) != 0)
+ err(EX_OSERR, "failed to flush table %s info",
+ tablename);
+ } else {
+ error = tables_foreach(table_flush_one, &oh, 1);
+ if (error != 0)
+ err(EX_OSERR, "failed to flush tables list");
+ }
+ break;
+ case TOK_SWAP:
+ ac--; av++;
+ NEED1("second table name required");
+ table_swap(&oh, *av);
+ break;
+ case TOK_LOCK:
+ case TOK_UNLOCK:
+ table_lock(&oh, (tcmd == TOK_LOCK));
+ break;
+ case TOK_DETAIL:
+ case TOK_INFO:
+ arg = (tcmd == TOK_DETAIL) ? (void *)1 : NULL;
+ if (is_all == 0) {
+ if ((error = table_get_info(&oh, &i)) != 0)
+ err(EX_OSERR, "failed to request table info");
+ table_show_info(&i, arg);
+ } else {
+ error = tables_foreach(table_show_info, arg, 1);
+ if (error != 0)
+ err(EX_OSERR, "failed to request tables list");
+ }
+ break;
+ case TOK_LIST:
+ if (is_all == 0) {
+ ipfw_xtable_info i;
+ if ((error = table_get_info(&oh, &i)) != 0)
+ err(EX_OSERR, "failed to request table info");
+ table_show_one(&i, NULL);
+ } else {
+ error = tables_foreach(table_show_one, NULL, 1);
+ if (error != 0)
+ err(EX_OSERR, "failed to request tables list");
+ }
+ break;
+ case TOK_LOOKUP:
+ ac--; av++;
+ table_lookup(&oh, ac, av);
+ break;
+ }
+}
+
+static void
+table_fill_ntlv(ipfw_obj_ntlv *ntlv, char *name, uint32_t set, uint16_t uidx)
+{
+
+ ntlv->head.type = IPFW_TLV_TBL_NAME;
+ ntlv->head.length = sizeof(ipfw_obj_ntlv);
+ ntlv->idx = uidx;
+ ntlv->set = set;
+ strlcpy(ntlv->name, name, sizeof(ntlv->name));
+}
+
+static void
+table_fill_objheader(ipfw_obj_header *oh, ipfw_xtable_info *i)
+{
+
+ oh->idx = 1;
+ table_fill_ntlv(&oh->ntlv, i->tablename, i->set, 1);
+}
+
+static struct _s_x tablenewcmds[] = {
+ { "type", TOK_TYPE },
+ { "valtype", TOK_VALTYPE },
+ { "algo", TOK_ALGO },
+ { "limit", TOK_LIMIT },
+ { "locked", TOK_LOCK },
+ { NULL, 0 }
+};
+
+static struct _s_x flowtypecmds[] = {
+ { "src-ip", IPFW_TFFLAG_SRCIP },
+ { "proto", IPFW_TFFLAG_PROTO },
+ { "src-port", IPFW_TFFLAG_SRCPORT },
+ { "dst-ip", IPFW_TFFLAG_DSTIP },
+ { "dst-port", IPFW_TFFLAG_DSTPORT },
+ { NULL, 0 }
+};
+
+int
+table_parse_type(uint8_t ttype, char *p, uint8_t *tflags)
+{
+ uint32_t fset, fclear;
+ char *e;
+
+ /* Parse type options */
+ switch(ttype) {
+ case IPFW_TABLE_FLOW:
+ fset = fclear = 0;
+ if (fill_flags(flowtypecmds, p, &e, &fset, &fclear) != 0)
+ errx(EX_USAGE,
+ "unable to parse flow option %s", e);
+ *tflags = fset;
+ break;
+ default:
+ return (EX_USAGE);
+ }
+
+ return (0);
+}
+
+void
+table_print_type(char *tbuf, size_t size, uint8_t type, uint8_t tflags)
+{
+ const char *tname;
+ int l;
+
+ if ((tname = match_value(tabletypes, type)) == NULL)
+ tname = "unknown";
+
+ l = snprintf(tbuf, size, "%s", tname);
+ tbuf += l;
+ size -= l;
+
+ switch(type) {
+ case IPFW_TABLE_FLOW:
+ if (tflags != 0) {
+ *tbuf++ = ':';
+ l--;
+ print_flags_buffer(tbuf, size, flowtypecmds, tflags);
+ }
+ break;
+ }
+}
+
+/*
+ * Creates new table
+ *
+ * ipfw table NAME create [ type { addr | iface | number | flow } ]
+ * [ algo algoname ]
+ */
+static void
+table_create(ipfw_obj_header *oh, int ac, char *av[])
+{
+ ipfw_xtable_info xi;
+ int error, tcmd, val;
+ uint32_t fset, fclear;
+ size_t sz;
+ char *e, *p;
+ char tbuf[128];
+
+ sz = sizeof(tbuf);
+ memset(&xi, 0, sizeof(xi));
+
+ while (ac > 0) {
+ tcmd = get_token(tablenewcmds, *av, "option");
+ ac--; av++;
+
+ switch (tcmd) {
+ case TOK_LIMIT:
+ NEED1("limit value required");
+ xi.limit = strtol(*av, NULL, 10);
+ ac--; av++;
+ break;
+ case TOK_TYPE:
+ NEED1("table type required");
+ /* Type may have suboptions after ':' */
+ if ((p = strchr(*av, ':')) != NULL)
+ *p++ = '\0';
+ val = match_token(tabletypes, *av);
+ if (val == -1) {
+ concat_tokens(tbuf, sizeof(tbuf), tabletypes,
+ ", ");
+ errx(EX_USAGE,
+ "Unknown tabletype: %s. Supported: %s",
+ *av, tbuf);
+ }
+ xi.type = val;
+ if (p != NULL) {
+ error = table_parse_type(val, p, &xi.tflags);
+ if (error != 0)
+ errx(EX_USAGE,
+ "Unsupported suboptions: %s", p);
+ }
+ ac--; av++;
+ break;
+ case TOK_VALTYPE:
+ NEED1("table value type required");
+ fset = fclear = 0;
+ val = fill_flags(tablevaltypes, *av, &e, &fset, &fclear);
+ if (val != -1) {
+ xi.vmask = fset;
+ ac--; av++;
+ break;
+ }
+ concat_tokens(tbuf, sizeof(tbuf), tablevaltypes, ", ");
+ errx(EX_USAGE, "Unknown value type: %s. Supported: %s",
+ e, tbuf);
+ break;
+ case TOK_ALGO:
+ NEED1("table algorithm name required");
+ if (strlen(*av) > sizeof(xi.algoname))
+ errx(EX_USAGE, "algorithm name too long");
+ strlcpy(xi.algoname, *av, sizeof(xi.algoname));
+ ac--; av++;
+ break;
+ case TOK_LOCK:
+ xi.flags |= IPFW_TGFLAGS_LOCKED;
+ break;
+ }
+ }
+
+ /* Set some defaults to preserve compability */
+ if (xi.algoname[0] == '\0' && xi.type == 0)
+ xi.type = IPFW_TABLE_ADDR;
+ if (xi.vmask == 0)
+ xi.vmask = IPFW_VTYPE_LEGACY;
+
+ if ((error = table_do_create(oh, &xi)) != 0)
+ err(EX_OSERR, "Table creation failed");
+}
+
+/*
+ * Creates new table
+ *
+ * Request: [ ipfw_obj_header ipfw_xtable_info ]
+ *
+ * Returns 0 on success.
+ */
+static int
+table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i)
+{
+ char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)];
+ int error;
+
+ memcpy(tbuf, oh, sizeof(*oh));
+ memcpy(tbuf + sizeof(*oh), i, sizeof(*i));
+ oh = (ipfw_obj_header *)tbuf;
+
+ error = do_set3(IP_FW_TABLE_XCREATE, &oh->opheader, sizeof(tbuf));
+
+ return (error);
+}
+
+/*
+ * Modifies existing table
+ *
+ * ipfw table NAME modify [ limit number ]
+ */
+static void
+table_modify(ipfw_obj_header *oh, int ac, char *av[])
+{
+ ipfw_xtable_info xi;
+ int tcmd;
+ size_t sz;
+ char tbuf[128];
+
+ sz = sizeof(tbuf);
+ memset(&xi, 0, sizeof(xi));
+
+ while (ac > 0) {
+ tcmd = get_token(tablenewcmds, *av, "option");
+ ac--; av++;
+
+ switch (tcmd) {
+ case TOK_LIMIT:
+ NEED1("limit value required");
+ xi.limit = strtol(*av, NULL, 10);
+ xi.mflags |= IPFW_TMFLAGS_LIMIT;
+ ac--; av++;
+ break;
+ default:
+ errx(EX_USAGE, "cmd is not supported for modificatiob");
+ }
+ }
+
+ if (table_do_modify(oh, &xi) != 0)
+ err(EX_OSERR, "Table modification failed");
+}
+
+/*
+ * Modifies existing table.
+ *
+ * Request: [ ipfw_obj_header ipfw_xtable_info ]
+ *
+ * Returns 0 on success.
+ */
+static int
+table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i)
+{
+ char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)];
+ int error;
+
+ memcpy(tbuf, oh, sizeof(*oh));
+ memcpy(tbuf + sizeof(*oh), i, sizeof(*i));
+ oh = (ipfw_obj_header *)tbuf;
+
+ error = do_set3(IP_FW_TABLE_XMODIFY, &oh->opheader, sizeof(tbuf));
+
+ return (error);
+}
+
+/*
+ * Locks or unlocks given table
+ */
+static void
+table_lock(ipfw_obj_header *oh, int lock)
+{
+ ipfw_xtable_info xi;
+
+ memset(&xi, 0, sizeof(xi));
+
+ xi.mflags |= IPFW_TMFLAGS_LOCK;
+ xi.flags |= (lock != 0) ? IPFW_TGFLAGS_LOCKED : 0;
+
+ if (table_do_modify(oh, &xi) != 0)
+ err(EX_OSERR, "Table %s failed", lock != 0 ? "lock" : "unlock");
+}
+
+/*
+ * Destroys given table specified by @oh->ntlv.
+ * Returns 0 on success.
+ */
+static int
+table_destroy(ipfw_obj_header *oh)
+{
+
+ if (do_set3(IP_FW_TABLE_XDESTROY, &oh->opheader, sizeof(*oh)) != 0)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * Flushes given table specified by @oh->ntlv.
+ * Returns 0 on success.
+ */
+static int
+table_flush(ipfw_obj_header *oh)
+{
+
+ if (do_set3(IP_FW_TABLE_XFLUSH, &oh->opheader, sizeof(*oh)) != 0)
+ return (-1);
+
+ return (0);
+}
+
+static int
+table_do_swap(ipfw_obj_header *oh, char *second)
+{
+ char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_ntlv)];
+ int error;
+
+ memset(tbuf, 0, sizeof(tbuf));
+ memcpy(tbuf, oh, sizeof(*oh));
+ oh = (ipfw_obj_header *)tbuf;
+ table_fill_ntlv((ipfw_obj_ntlv *)(oh + 1), second, oh->ntlv.set, 1);
+
+ error = do_set3(IP_FW_TABLE_XSWAP, &oh->opheader, sizeof(tbuf));
+
+ return (error);
+}
+
+/*
+ * Swaps given table with @second one.
+ */
+static int
+table_swap(ipfw_obj_header *oh, char *second)
+{
+ int error;
+
+ if (table_check_name(second) != 0)
+ errx(EX_USAGE, "table name %s is invalid", second);
+
+ error = table_do_swap(oh, second);
+
+ switch (error) {
+ case EINVAL:
+ errx(EX_USAGE, "Unable to swap table: check types");
+ case EFBIG:
+ errx(EX_USAGE, "Unable to swap table: check limits");
+ }
+
+ return (0);
+}
+
+
+/*
+ * Retrieves table in given table specified by @oh->ntlv.
+ * it inside @i.
+ * Returns 0 on success.
+ */
+static int
+table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i)
+{
+ char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)];
+ size_t sz;
+
+ sz = sizeof(tbuf);
+ memset(tbuf, 0, sizeof(tbuf));
+ memcpy(tbuf, oh, sizeof(*oh));
+ oh = (ipfw_obj_header *)tbuf;
+
+ if (do_get3(IP_FW_TABLE_XINFO, &oh->opheader, &sz) != 0)
+ return (errno);
+
+ if (sz < sizeof(tbuf))
+ return (EINVAL);
+
+ *i = *(ipfw_xtable_info *)(oh + 1);
+
+ return (0);
+}
+
+static struct _s_x tablealgoclass[] = {
+ { "hash", IPFW_TACLASS_HASH },
+ { "array", IPFW_TACLASS_ARRAY },
+ { "radix", IPFW_TACLASS_RADIX },
+ { NULL, 0 }
+};
+
+struct ta_cldata {
+ uint8_t taclass;
+ uint8_t spare4;
+ uint16_t itemsize;
+ uint16_t itemsize6;
+ uint32_t size;
+ uint32_t count;
+};
+
+/*
+ * Print global/per-AF table @i algorithm info.
+ */
+static void
+table_show_tainfo(ipfw_xtable_info *i, struct ta_cldata *d,
+ const char *af, const char *taclass)
+{
+
+ switch (d->taclass) {
+ case IPFW_TACLASS_HASH:
+ case IPFW_TACLASS_ARRAY:
+ printf(" %salgorithm %s info\n", af, taclass);
+ if (d->itemsize == d->itemsize6)
+ printf(" size: %u items: %u itemsize: %u\n",
+ d->size, d->count, d->itemsize);
+ else
+ printf(" size: %u items: %u "
+ "itemsize4: %u itemsize6: %u\n",
+ d->size, d->count,
+ d->itemsize, d->itemsize6);
+ break;
+ case IPFW_TACLASS_RADIX:
+ printf(" %salgorithm %s info\n", af, taclass);
+ if (d->itemsize == d->itemsize6)
+ printf(" items: %u itemsize: %u\n",
+ d->count, d->itemsize);
+ else
+ printf(" items: %u "
+ "itemsize4: %u itemsize6: %u\n",
+ d->count, d->itemsize, d->itemsize6);
+ break;
+ default:
+ printf(" algo class: %s\n", taclass);
+ }
+}
+
+static void
+table_print_valheader(char *buf, size_t bufsize, uint32_t vmask)
+{
+
+ if (vmask == IPFW_VTYPE_LEGACY) {
+ snprintf(buf, bufsize, "legacy");
+ return;
+ }
+
+ print_flags_buffer(buf, bufsize, tablevaltypes, vmask);
+}
+
+/*
+ * Prints table info struct @i in human-readable form.
+ */
+static int
+table_show_info(ipfw_xtable_info *i, void *arg)
+{
+ const char *vtype;
+ ipfw_ta_tinfo *tainfo;
+ int afdata, afitem;
+ struct ta_cldata d;
+ char ttype[64], tvtype[64];
+
+ table_print_type(ttype, sizeof(ttype), i->type, i->tflags);
+ table_print_valheader(tvtype, sizeof(tvtype), i->vmask);
+
+ printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
+ if ((i->flags & IPFW_TGFLAGS_LOCKED) != 0)
+ printf(" kindex: %d, type: %s, locked\n", i->kidx, ttype);
+ else
+ printf(" kindex: %d, type: %s\n", i->kidx, ttype);
+ printf(" references: %u, valtype: %s\n", i->refcnt, tvtype);
+ printf(" algorithm: %s\n", i->algoname);
+ printf(" items: %u, size: %u\n", i->count, i->size);
+ if (i->limit > 0)
+ printf(" limit: %u\n", i->limit);
+
+ /* Print algo-specific info if requested & set */
+ if (arg == NULL)
+ return (0);
+
+ if ((i->ta_info.flags & IPFW_TATFLAGS_DATA) == 0)
+ return (0);
+ tainfo = &i->ta_info;
+
+ afdata = 0;
+ afitem = 0;
+ if (tainfo->flags & IPFW_TATFLAGS_AFDATA)
+ afdata = 1;
+ if (tainfo->flags & IPFW_TATFLAGS_AFITEM)
+ afitem = 1;
+
+ memset(&d, 0, sizeof(d));
+ d.taclass = tainfo->taclass4;
+ d.size = tainfo->size4;
+ d.count = tainfo->count4;
+ d.itemsize = tainfo->itemsize4;
+ if (afdata == 0 && afitem != 0)
+ d.itemsize6 = tainfo->itemsize6;
+ else
+ d.itemsize6 = d.itemsize;
+ if ((vtype = match_value(tablealgoclass, d.taclass)) == NULL)
+ vtype = "unknown";
+
+ if (afdata == 0) {
+ table_show_tainfo(i, &d, "", vtype);
+ } else {
+ table_show_tainfo(i, &d, "IPv4 ", vtype);
+ memset(&d, 0, sizeof(d));
+ d.taclass = tainfo->taclass6;
+ if ((vtype = match_value(tablealgoclass, d.taclass)) == NULL)
+ vtype = "unknown";
+ d.size = tainfo->size6;
+ d.count = tainfo->count6;
+ d.itemsize = tainfo->itemsize6;
+ d.itemsize6 = d.itemsize;
+ table_show_tainfo(i, &d, "IPv6 ", vtype);
+ }
+
+ return (0);
+}
+
+
+/*
+ * Function wrappers which can be used either
+ * as is or as foreach function parameter.
+ */
+
+static int
+table_show_one(ipfw_xtable_info *i, void *arg)
+{
+ ipfw_obj_header *oh;
+ int error;
+
+ if ((error = table_do_get_list(i, &oh)) != 0) {
+ err(EX_OSERR, "Error requesting table %s list", i->tablename);
+ return (error);
+ }
+
+ table_show_list(oh, 1);
+
+ free(oh);
+ return (0);
+}
+
+static int
+table_flush_one(ipfw_xtable_info *i, void *arg)
+{
+ ipfw_obj_header *oh;
+
+ oh = (ipfw_obj_header *)arg;
+
+ table_fill_ntlv(&oh->ntlv, i->tablename, i->set, 1);
+
+ return (table_flush(oh));
+}
+
+static int
+table_do_modify_record(int cmd, ipfw_obj_header *oh,
+ ipfw_obj_tentry *tent, int count, int atomic)
+{
+ ipfw_obj_ctlv *ctlv;
+ ipfw_obj_tentry *tent_base;
+ caddr_t pbuf;
+ char xbuf[sizeof(*oh) + sizeof(ipfw_obj_ctlv) + sizeof(*tent)];
+ int error, i;
+ size_t sz;
+
+ sz = sizeof(*ctlv) + sizeof(*tent) * count;
+ if (count == 1) {
+ memset(xbuf, 0, sizeof(xbuf));
+ pbuf = xbuf;
+ } else {
+ if ((pbuf = calloc(1, sizeof(*oh) + sz)) == NULL)
+ return (ENOMEM);
+ }
+
+ memcpy(pbuf, oh, sizeof(*oh));
+ oh = (ipfw_obj_header *)pbuf;
+ oh->opheader.version = 1;
+
+ ctlv = (ipfw_obj_ctlv *)(oh + 1);
+ ctlv->count = count;
+ ctlv->head.length = sz;
+ if (atomic != 0)
+ ctlv->flags |= IPFW_CTF_ATOMIC;
+
+ tent_base = tent;
+ memcpy(ctlv + 1, tent, sizeof(*tent) * count);
+ tent = (ipfw_obj_tentry *)(ctlv + 1);
+ for (i = 0; i < count; i++, tent++) {
+ tent->head.length = sizeof(ipfw_obj_tentry);
+ tent->idx = oh->idx;
+ }
+
+ sz += sizeof(*oh);
+ error = do_get3(cmd, &oh->opheader, &sz);
+ tent = (ipfw_obj_tentry *)(ctlv + 1);
+ /* Copy result back to provided buffer */
+ memcpy(tent_base, ctlv + 1, sizeof(*tent) * count);
+
+ if (pbuf != xbuf)
+ free(pbuf);
+
+ return (error);
+}
+
+static void
+table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add,
+ int quiet, int update, int atomic)
+{
+ ipfw_obj_tentry *ptent, tent, *tent_buf;
+ ipfw_xtable_info xi;
+ uint8_t type;
+ uint32_t vmask;
+ int cmd, count, error, i, ignored;
+ char *texterr, *etxt, *px;
+
+ if (ac == 0)
+ errx(EX_USAGE, "address required");
+
+ if (add != 0) {
+ cmd = IP_FW_TABLE_XADD;
+ texterr = "Adding record failed";
+ } else {
+ cmd = IP_FW_TABLE_XDEL;
+ texterr = "Deleting record failed";
+ }
+
+ /*
+ * Calculate number of entries:
+ * Assume [key val] x N for add
+ * and
+ * key x N for delete
+ */
+ count = (add != 0) ? ac / 2 + 1 : ac;
+
+ if (count <= 1) {
+ /* Adding single entry with/without value */
+ memset(&tent, 0, sizeof(tent));
+ tent_buf = &tent;
+ } else {
+
+ if ((tent_buf = calloc(count, sizeof(tent))) == NULL)
+ errx(EX_OSERR,
+ "Unable to allocate memory for all entries");
+ }
+ ptent = tent_buf;
+
+ memset(&xi, 0, sizeof(xi));
+ count = 0;
+ while (ac > 0) {
+ tentry_fill_key(oh, ptent, *av, add, &type, &vmask, &xi);
+
+ /*
+ * compability layer: auto-create table if not exists
+ */
+ if (xi.tablename[0] == '\0') {
+ xi.type = type;
+ xi.vmask = vmask;
+ strlcpy(xi.tablename, oh->ntlv.name,
+ sizeof(xi.tablename));
+ fprintf(stderr, "DEPRECATED: inserting data info "
+ "non-existent table %s. (auto-created)\n",
+ xi.tablename);
+ table_do_create(oh, &xi);
+ }
+
+ oh->ntlv.type = type;
+ ac--; av++;
+
+ if (add != 0 && ac > 0) {
+ tentry_fill_value(oh, ptent, *av, type, vmask);
+ ac--; av++;
+ }
+
+ if (update != 0)
+ ptent->head.flags |= IPFW_TF_UPDATE;
+
+ count++;
+ ptent++;
+ }
+
+ error = table_do_modify_record(cmd, oh, tent_buf, count, atomic);
+
+ quiet = 0;
+
+ /*
+ * Compatibility stuff: do not yell on duplicate keys or
+ * failed deletions.
+ */
+ if (error == 0 || (error == EEXIST && add != 0) ||
+ (error == ENOENT && add == 0)) {
+ if (quiet != 0) {
+ if (tent_buf != &tent)
+ free(tent_buf);
+ return;
+ }
+ }
+
+ /* Report results back */
+ ptent = tent_buf;
+ for (i = 0; i < count; ptent++, i++) {
+ ignored = 0;
+ switch (ptent->result) {
+ case IPFW_TR_ADDED:
+ px = "added";
+ break;
+ case IPFW_TR_DELETED:
+ px = "deleted";
+ break;
+ case IPFW_TR_UPDATED:
+ px = "updated";
+ break;
+ case IPFW_TR_LIMIT:
+ px = "limit";
+ ignored = 1;
+ break;
+ case IPFW_TR_ERROR:
+ px = "error";
+ ignored = 1;
+ break;
+ case IPFW_TR_NOTFOUND:
+ px = "notfound";
+ ignored = 1;
+ break;
+ case IPFW_TR_EXISTS:
+ px = "exists";
+ ignored = 1;
+ break;
+ case IPFW_TR_IGNORED:
+ px = "ignored";
+ ignored = 1;
+ break;
+ default:
+ px = "unknown";
+ ignored = 1;
+ }
+
+ if (error != 0 && atomic != 0 && ignored == 0)
+ printf("%s(reverted): ", px);
+ else
+ printf("%s: ", px);
+
+ table_show_entry(&xi, ptent);
+ }
+
+ if (tent_buf != &tent)
+ free(tent_buf);
+
+ if (error == 0)
+ return;
+ /* Get real OS error */
+ error = errno;
+
+ /* Try to provide more human-readable error */
+ switch (error) {
+ case EEXIST:
+ etxt = "record already exists";
+ break;
+ case EFBIG:
+ etxt = "limit hit";
+ break;
+ case ESRCH:
+ etxt = "table not found";
+ break;
+ case ENOENT:
+ etxt = "record not found";
+ break;
+ case EACCES:
+ etxt = "table is locked";
+ break;
+ default:
+ etxt = strerror(error);
+ }
+
+ errx(EX_OSERR, "%s: %s", texterr, etxt);
+}
+
+static int
+table_do_lookup(ipfw_obj_header *oh, char *key, ipfw_xtable_info *xi,
+ ipfw_obj_tentry *xtent)
+{
+ char xbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_tentry)];
+ ipfw_obj_tentry *tent;
+ uint8_t type;
+ uint32_t vmask;
+ size_t sz;
+
+ memcpy(xbuf, oh, sizeof(*oh));
+ oh = (ipfw_obj_header *)xbuf;
+ tent = (ipfw_obj_tentry *)(oh + 1);
+
+ memset(tent, 0, sizeof(*tent));
+ tent->head.length = sizeof(*tent);
+ tent->idx = 1;
+
+ tentry_fill_key(oh, tent, key, 0, &type, &vmask, xi);
+ oh->ntlv.type = type;
+
+ sz = sizeof(xbuf);
+ if (do_get3(IP_FW_TABLE_XFIND, &oh->opheader, &sz) != 0)
+ return (errno);
+
+ if (sz < sizeof(xbuf))
+ return (EINVAL);
+
+ *xtent = *tent;
+
+ return (0);
+}
+
+static void
+table_lookup(ipfw_obj_header *oh, int ac, char *av[])
+{
+ ipfw_obj_tentry xtent;
+ ipfw_xtable_info xi;
+ char key[64];
+ int error;
+
+ if (ac == 0)
+ errx(EX_USAGE, "address required");
+
+ strlcpy(key, *av, sizeof(key));
+
+ memset(&xi, 0, sizeof(xi));
+ error = table_do_lookup(oh, key, &xi, &xtent);
+
+ switch (error) {
+ case 0:
+ break;
+ case ESRCH:
+ errx(EX_UNAVAILABLE, "Table %s not found", oh->ntlv.name);
+ case ENOENT:
+ errx(EX_UNAVAILABLE, "Entry %s not found", *av);
+ case ENOTSUP:
+ errx(EX_UNAVAILABLE, "Table %s algo does not support "
+ "\"lookup\" method", oh->ntlv.name);
+ default:
+ err(EX_OSERR, "getsockopt(IP_FW_TABLE_XFIND)");
+ }
+
+ table_show_entry(&xi, &xtent);
+}
+
+static void
+tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type,
+ uint8_t tflags)
+{
+ char *p, *pp;
+ int mask, af;
+ struct in6_addr *paddr, tmp;
+ struct tflow_entry *tfe;
+ uint32_t key, *pkey;
+ uint16_t port;
+ struct protoent *pent;
+ struct servent *sent;
+ int masklen;
+
+ masklen = 0;
+ af = 0;
+ paddr = (struct in6_addr *)&tentry->k;
+
+ switch (type) {
+ case IPFW_TABLE_ADDR:
+ /* Remove / if exists */
+ if ((p = strchr(arg, '/')) != NULL) {
+ *p = '\0';
+ mask = atoi(p + 1);
+ }
+
+ if (inet_pton(AF_INET, arg, paddr) == 1) {
+ if (p != NULL && mask > 32)
+ errx(EX_DATAERR, "bad IPv4 mask width: %s",
+ p + 1);
+
+ masklen = p ? mask : 32;
+ af = AF_INET;
+ } else if (inet_pton(AF_INET6, arg, paddr) == 1) {
+ if (IN6_IS_ADDR_V4COMPAT(paddr))
+ errx(EX_DATAERR,
+ "Use IPv4 instead of v4-compatible");
+ if (p != NULL && mask > 128)
+ errx(EX_DATAERR, "bad IPv6 mask width: %s",
+ p + 1);
+
+ masklen = p ? mask : 128;
+ af = AF_INET6;
+ } else {
+ /* Assume FQDN */
+ if (lookup_host(arg, (struct in_addr *)paddr) != 0)
+ errx(EX_NOHOST, "hostname ``%s'' unknown", arg);
+
+ masklen = 32;
+ type = IPFW_TABLE_ADDR;
+ af = AF_INET;
+ }
+ break;
+ case IPFW_TABLE_INTERFACE:
+ /* Assume interface name. Copy significant data only */
+ mask = MIN(strlen(arg), IF_NAMESIZE - 1);
+ memcpy(paddr, arg, mask);
+ /* Set mask to exact match */
+ masklen = 8 * IF_NAMESIZE;
+ break;
+ case IPFW_TABLE_NUMBER:
+ /* Port or any other key */
+ key = strtol(arg, &p, 10);
+ if (*p != '\0')
+ errx(EX_DATAERR, "Invalid number: %s", arg);
+
+ pkey = (uint32_t *)paddr;
+ *pkey = key;
+ masklen = 32;
+ break;
+ case IPFW_TABLE_FLOW:
+ /* Assume [src-ip][,proto][,src-port][,dst-ip][,dst-port] */
+ tfe = &tentry->k.flow;
+ af = 0;
+
+ /* Handle <ipv4|ipv6> */
+ if ((tflags & IPFW_TFFLAG_SRCIP) != 0) {
+ if ((p = strchr(arg, ',')) != NULL)
+ *p++ = '\0';
+ /* Determine family using temporary storage */
+ if (inet_pton(AF_INET, arg, &tmp) == 1) {
+ if (af != 0 && af != AF_INET)
+ errx(EX_DATAERR,
+ "Inconsistent address family\n");
+ af = AF_INET;
+ memcpy(&tfe->a.a4.sip, &tmp, 4);
+ } else if (inet_pton(AF_INET6, arg, &tmp) == 1) {
+ if (af != 0 && af != AF_INET6)
+ errx(EX_DATAERR,
+ "Inconsistent address family\n");
+ af = AF_INET6;
+ memcpy(&tfe->a.a6.sip6, &tmp, 16);
+ }
+
+ arg = p;
+ }
+
+ /* Handle <proto-num|proto-name> */
+ if ((tflags & IPFW_TFFLAG_PROTO) != 0) {
+ if (arg == NULL)
+ errx(EX_DATAERR, "invalid key: proto missing");
+ if ((p = strchr(arg, ',')) != NULL)
+ *p++ = '\0';
+
+ key = strtol(arg, &pp, 10);
+ if (*pp != '\0') {
+ if ((pent = getprotobyname(arg)) == NULL)
+ errx(EX_DATAERR, "Unknown proto: %s",
+ arg);
+ else
+ key = pent->p_proto;
+ }
+
+ if (key > 255)
+ errx(EX_DATAERR, "Bad protocol number: %u",key);
+
+ tfe->proto = key;
+
+ arg = p;
+ }
+
+ /* Handle <port-num|service-name> */
+ if ((tflags & IPFW_TFFLAG_SRCPORT) != 0) {
+ if (arg == NULL)
+ errx(EX_DATAERR, "invalid key: src port missing");
+ if ((p = strchr(arg, ',')) != NULL)
+ *p++ = '\0';
+
+ if ((port = htons(strtol(arg, NULL, 10))) == 0) {
+ if ((sent = getservbyname(arg, NULL)) == NULL)
+ errx(EX_DATAERR, "Unknown service: %s",
+ arg);
+ else
+ key = sent->s_port;
+ }
+
+ tfe->sport = port;
+
+ arg = p;
+ }
+
+ /* Handle <ipv4|ipv6>*/
+ if ((tflags & IPFW_TFFLAG_DSTIP) != 0) {
+ if (arg == NULL)
+ errx(EX_DATAERR, "invalid key: dst ip missing");
+ if ((p = strchr(arg, ',')) != NULL)
+ *p++ = '\0';
+ /* Determine family using temporary storage */
+ if (inet_pton(AF_INET, arg, &tmp) == 1) {
+ if (af != 0 && af != AF_INET)
+ errx(EX_DATAERR,
+ "Inconsistent address family");
+ af = AF_INET;
+ memcpy(&tfe->a.a4.dip, &tmp, 4);
+ } else if (inet_pton(AF_INET6, arg, &tmp) == 1) {
+ if (af != 0 && af != AF_INET6)
+ errx(EX_DATAERR,
+ "Inconsistent address family");
+ af = AF_INET6;
+ memcpy(&tfe->a.a6.dip6, &tmp, 16);
+ }
+
+ arg = p;
+ }
+
+ /* Handle <port-num|service-name> */
+ if ((tflags & IPFW_TFFLAG_DSTPORT) != 0) {
+ if (arg == NULL)
+ errx(EX_DATAERR, "invalid key: dst port missing");
+ if ((p = strchr(arg, ',')) != NULL)
+ *p++ = '\0';
+
+ if ((port = htons(strtol(arg, NULL, 10))) == 0) {
+ if ((sent = getservbyname(arg, NULL)) == NULL)
+ errx(EX_DATAERR, "Unknown service: %s",
+ arg);
+ else
+ key = sent->s_port;
+ }
+
+ tfe->dport = port;
+
+ arg = p;
+ }
+
+ tfe->af = af;
+
+ break;
+
+ default:
+ errx(EX_DATAERR, "Unsupported table type: %d", type);
+ }
+
+ tentry->subtype = af;
+ tentry->masklen = masklen;
+}
+
+static void
+tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key,
+ int add, uint8_t *ptype, uint32_t *pvmask, ipfw_xtable_info *xi)
+{
+ uint8_t type, tflags;
+ uint32_t vmask;
+ int error;
+ char *del;
+
+ type = 0;
+ tflags = 0;
+ vmask = 0;
+
+ if (xi->tablename[0] == '\0')
+ error = table_get_info(oh, xi);
+ else
+ error = 0;
+
+ if (error == 0) {
+ /* Table found. */
+ type = xi->type;
+ tflags = xi->tflags;
+ vmask = xi->vmask;
+ } else {
+ if (error != ESRCH)
+ errx(EX_OSERR, "Error requesting table %s info",
+ oh->ntlv.name);
+ if (add == 0)
+ errx(EX_DATAERR, "Table %s does not exist",
+ oh->ntlv.name);
+ /*
+ * Table does not exist.
+ * Compability layer: try to interpret data as ADDR
+ * before failing.
+ */
+ if ((del = strchr(key, '/')) != NULL)
+ *del = '\0';
+ if (inet_pton(AF_INET, key, &tent->k.addr6) == 1 ||
+ inet_pton(AF_INET6, key, &tent->k.addr6) == 1) {
+ /* OK Prepare and send */
+ type = IPFW_TABLE_ADDR;
+ vmask = IPFW_VTYPE_LEGACY;
+ } else {
+ /* Inknown key */
+ errx(EX_USAGE, "Table %s does not exist, cannot guess "
+ "key '%s' type", oh->ntlv.name, key);
+ }
+ if (del != NULL)
+ *del = '/';
+ }
+
+ tentry_fill_key_type(key, tent, type, tflags);
+
+ *ptype = type;
+ *pvmask = vmask;
+}
+
+static void
+set_legacy_value(uint32_t val, ipfw_table_value *v)
+{
+ v->tag = val;
+ v->pipe = val;
+ v->divert = val;
+ v->skipto = val;
+ v->netgraph = val;
+ v->fib = val;
+ v->nat = val;
+ v->nh4 = val;
+ v->dscp = (uint8_t)val;
+ v->limit = val;
+}
+
+static void
+tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *arg,
+ uint8_t type, uint32_t vmask)
+{
+ uint32_t a4, flag, val, vm;
+ ipfw_table_value *v;
+ uint32_t i;
+ int dval;
+ char *comma, *e, *etype, *n, *p;
+
+ v = &tent->v.value;
+ vm = vmask;
+
+ /* Compat layer: keep old behavior for legacy value types */
+ if (vmask == IPFW_VTYPE_LEGACY) {
+ /* Try to interpret as number first */
+ val = strtoul(arg, &p, 0);
+ if (*p == '\0') {
+ set_legacy_value(val, v);
+ return;
+ }
+ if (inet_pton(AF_INET, arg, &val) == 1) {
+ set_legacy_value(ntohl(val), v);
+ return;
+ }
+ /* Try hostname */
+ if (lookup_host(arg, (struct in_addr *)&val) == 0) {
+ set_legacy_value(val, v);
+ return;
+ }
+ errx(EX_OSERR, "Unable to parse value %s", arg);
+ }
+
+ /*
+ * Shorthands: handle single value if vmask consists
+ * of numbers only. e.g.:
+ * vmask = "fib,skipto" -> treat input "1" as "1,1"
+ */
+
+ n = arg;
+ etype = NULL;
+ for (i = 1; i < (1 << 31); i *= 2) {
+ if ((flag = (vmask & i)) == 0)
+ continue;
+ vmask &= ~flag;
+
+ if ((comma = strchr(n, ',')) != NULL)
+ *comma = '\0';
+
+ switch (flag) {
+ case IPFW_VTYPE_TAG:
+ v->tag = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "tag";
+ break;
+ case IPFW_VTYPE_PIPE:
+ v->pipe = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "pipe";
+ break;
+ case IPFW_VTYPE_DIVERT:
+ v->divert = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "divert";
+ break;
+ case IPFW_VTYPE_SKIPTO:
+ v->skipto = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "skipto";
+ break;
+ case IPFW_VTYPE_NETGRAPH:
+ v->netgraph = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "netgraph";
+ break;
+ case IPFW_VTYPE_FIB:
+ v->fib = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "fib";
+ break;
+ case IPFW_VTYPE_NAT:
+ v->nat = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "nat";
+ break;
+ case IPFW_VTYPE_LIMIT:
+ v->limit = strtol(n, &e, 10);
+ if (*e != '\0')
+ etype = "limit";
+ break;
+ case IPFW_VTYPE_NH4:
+ if (strchr(n, '.') != NULL &&
+ inet_pton(AF_INET, n, &a4) == 1) {
+ v->nh4 = ntohl(a4);
+ break;
+ }
+ if (lookup_host(n, (struct in_addr *)&v->nh4) == 0)
+ break;
+ etype = "ipv4";
+ break;
+ case IPFW_VTYPE_DSCP:
+ if (isalpha(*n)) {
+ if ((dval = match_token(f_ipdscp, n)) != -1) {
+ v->dscp = dval;
+ break;
+ } else
+ etype = "DSCP code";
+ } else {
+ v->dscp = strtol(n, &e, 10);
+ if (v->dscp > 63 || *e != '\0')
+ etype = "DSCP value";
+ }
+ break;
+ case IPFW_VTYPE_NH6:
+ if (strchr(n, ':') != NULL &&
+ inet_pton(AF_INET6, n, &v->nh6) == 1)
+ break;
+ etype = "ipv6";
+ break;
+ }
+
+ if (etype != NULL)
+ errx(EX_USAGE, "Unable to parse %s as %s", n, etype);
+
+ if (comma != NULL)
+ *comma++ = ',';
+
+ if ((n = comma) != NULL)
+ continue;
+
+ /* End of input. */
+ if (vmask != 0)
+ errx(EX_USAGE, "Not enough fields inside value");
+ }
+}
+
+/*
+ * Compare table names.
+ * Honor number comparison.
+ */
+static int
+tablename_cmp(const void *a, const void *b)
+{
+ ipfw_xtable_info *ia, *ib;
+
+ ia = (ipfw_xtable_info *)a;
+ ib = (ipfw_xtable_info *)b;
+
+ return (stringnum_cmp(ia->tablename, ib->tablename));
+}
+
+/*
+ * Retrieves table list from kernel,
+ * optionally sorts it and calls requested function for each table.
+ * Returns 0 on success.
+ */
+static int
+tables_foreach(table_cb_t *f, void *arg, int sort)
+{
+ ipfw_obj_lheader *olh;
+ ipfw_xtable_info *info;
+ size_t sz;
+ int i, error;
+
+ /* Start with reasonable default */
+ sz = sizeof(*olh) + 16 * sizeof(ipfw_xtable_info);
+
+ for (;;) {
+ if ((olh = calloc(1, sz)) == NULL)
+ return (ENOMEM);
+
+ olh->size = sz;
+ if (do_get3(IP_FW_TABLES_XLIST, &olh->opheader, &sz) != 0) {
+ sz = olh->size;
+ free(olh);
+ if (errno != ENOMEM)
+ return (errno);
+ continue;
+ }
+
+ if (sort != 0)
+ qsort(olh + 1, olh->count, olh->objsize, tablename_cmp);
+
+ info = (ipfw_xtable_info *)(olh + 1);
+ for (i = 0; i < olh->count; i++) {
+ error = f(info, arg); /* Ignore errors for now */
+ info = (ipfw_xtable_info *)((caddr_t)info + olh->objsize);
+ }
+
+ free(olh);
+ break;
+ }
+
+ return (0);
+}
+
+
+/*
+ * Retrieves all entries for given table @i in
+ * eXtended format. Allocate buffer large enough
+ * to store result. Called needs to free it later.
+ *
+ * Returns 0 on success.
+ */
+static int
+table_do_get_list(ipfw_xtable_info *i, ipfw_obj_header **poh)
+{
+ ipfw_obj_header *oh;
+ size_t sz;
+ int c;
+
+ sz = 0;
+ oh = NULL;
+ for (c = 0; c < 8; c++) {
+ if (sz < i->size)
+ sz = i->size + 44;
+ if (oh != NULL)
+ free(oh);
+ if ((oh = calloc(1, sz)) == NULL)
+ continue;
+ table_fill_objheader(oh, i);
+ oh->opheader.version = 1; /* Current version */
+ if (do_get3(IP_FW_TABLE_XLIST, &oh->opheader, &sz) == 0) {
+ *poh = oh;
+ return (0);
+ }
+
+ if (errno != ENOMEM)
+ break;
+ }
+ free(oh);
+
+ return (errno);
+}
+
+/*
+ * Shows all entries from @oh in human-readable format
+ */
+static void
+table_show_list(ipfw_obj_header *oh, int need_header)
+{
+ ipfw_obj_tentry *tent;
+ uint32_t count;
+ ipfw_xtable_info *i;
+
+ i = (ipfw_xtable_info *)(oh + 1);
+ tent = (ipfw_obj_tentry *)(i + 1);
+
+ if (need_header)
+ printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
+
+ count = i->count;
+ while (count > 0) {
+ table_show_entry(i, tent);
+ tent = (ipfw_obj_tentry *)((caddr_t)tent + tent->head.length);
+ count--;
+ }
+}
+
+static void
+table_show_value(char *buf, size_t bufsize, ipfw_table_value *v,
+ uint32_t vmask, int print_ip)
+{
+ uint32_t flag, i, l;
+ size_t sz;
+ struct in_addr a4;
+ char abuf[INET6_ADDRSTRLEN];
+
+ sz = bufsize;
+
+ /*
+ * Some shorthands for printing values:
+ * legacy assumes all values are equal, so keep the first one.
+ */
+ if (vmask == IPFW_VTYPE_LEGACY) {
+ if (print_ip != 0) {
+ flag = htonl(v->tag);
+ inet_ntop(AF_INET, &flag, buf, sz);
+ } else
+ snprintf(buf, sz, "%u", v->tag);
+ return;
+ }
+
+ for (i = 1; i < (1 << 31); i *= 2) {
+ if ((flag = (vmask & i)) == 0)
+ continue;
+ l = 0;
+
+ switch (flag) {
+ case IPFW_VTYPE_TAG:
+ l = snprintf(buf, sz, "%u,", v->tag);
+ break;
+ case IPFW_VTYPE_PIPE:
+ l = snprintf(buf, sz, "%u,", v->pipe);
+ break;
+ case IPFW_VTYPE_DIVERT:
+ l = snprintf(buf, sz, "%d,", v->divert);
+ break;
+ case IPFW_VTYPE_SKIPTO:
+ l = snprintf(buf, sz, "%d,", v->skipto);
+ break;
+ case IPFW_VTYPE_NETGRAPH:
+ l = snprintf(buf, sz, "%u,", v->netgraph);
+ break;
+ case IPFW_VTYPE_FIB:
+ l = snprintf(buf, sz, "%u,", v->fib);
+ break;
+ case IPFW_VTYPE_NAT:
+ l = snprintf(buf, sz, "%u,", v->nat);
+ break;
+ case IPFW_VTYPE_LIMIT:
+ l = snprintf(buf, sz, "%u,", v->limit);
+ break;
+ case IPFW_VTYPE_NH4:
+ a4.s_addr = htonl(v->nh4);
+ inet_ntop(AF_INET, &a4, abuf, sizeof(abuf));
+ l = snprintf(buf, sz, "%s,", abuf);
+ break;
+ case IPFW_VTYPE_DSCP:
+ l = snprintf(buf, sz, "%d,", v->dscp);
+ break;
+ case IPFW_VTYPE_NH6:
+ inet_ntop(AF_INET6, &v->nh6, abuf, sizeof(abuf));
+ l = snprintf(buf, sz, "%s,", abuf);
+ break;
+ }
+
+ buf += l;
+ sz -= l;
+ }
+
+ if (sz != bufsize)
+ *(buf - 1) = '\0';
+}
+
+static void
+table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent)
+{
+ char *comma, tbuf[128], pval[128];
+ void *paddr;
+ struct tflow_entry *tfe;
+
+ table_show_value(pval, sizeof(pval), &tent->v.value, i->vmask,
+ co.do_value_as_ip);
+
+ switch (i->type) {
+ case IPFW_TABLE_ADDR:
+ /* IPv4 or IPv6 prefixes */
+ inet_ntop(tent->subtype, &tent->k, tbuf, sizeof(tbuf));
+ printf("%s/%u %s\n", tbuf, tent->masklen, pval);
+ break;
+ case IPFW_TABLE_INTERFACE:
+ /* Interface names */
+ printf("%s %s\n", tent->k.iface, pval);
+ break;
+ case IPFW_TABLE_NUMBER:
+ /* numbers */
+ printf("%u %s\n", tent->k.key, pval);
+ break;
+ case IPFW_TABLE_FLOW:
+ /* flows */
+ tfe = &tent->k.flow;
+ comma = "";
+
+ if ((i->tflags & IPFW_TFFLAG_SRCIP) != 0) {
+ if (tfe->af == AF_INET)
+ paddr = &tfe->a.a4.sip;
+ else
+ paddr = &tfe->a.a6.sip6;
+
+ inet_ntop(tfe->af, paddr, tbuf, sizeof(tbuf));
+ printf("%s%s", comma, tbuf);
+ comma = ",";
+ }
+
+ if ((i->tflags & IPFW_TFFLAG_PROTO) != 0) {
+ printf("%s%d", comma, tfe->proto);
+ comma = ",";
+ }
+
+ if ((i->tflags & IPFW_TFFLAG_SRCPORT) != 0) {
+ printf("%s%d", comma, ntohs(tfe->sport));
+ comma = ",";
+ }
+ if ((i->tflags & IPFW_TFFLAG_DSTIP) != 0) {
+ if (tfe->af == AF_INET)
+ paddr = &tfe->a.a4.dip;
+ else
+ paddr = &tfe->a.a6.dip6;
+
+ inet_ntop(tfe->af, paddr, tbuf, sizeof(tbuf));
+ printf("%s%s", comma, tbuf);
+ comma = ",";
+ }
+
+ if ((i->tflags & IPFW_TFFLAG_DSTPORT) != 0) {
+ printf("%s%d", comma, ntohs(tfe->dport));
+ comma = ",";
+ }
+
+ printf(" %s\n", pval);
+ }
+}
+
+static int
+table_do_get_stdlist(uint16_t opcode, ipfw_obj_lheader **polh)
+{
+ ipfw_obj_lheader req, *olh;
+ size_t sz;
+
+ memset(&req, 0, sizeof(req));
+ sz = sizeof(req);
+
+ if (do_get3(opcode, &req.opheader, &sz) != 0)
+ if (errno != ENOMEM)
+ return (errno);
+
+ sz = req.size;
+ if ((olh = calloc(1, sz)) == NULL)
+ return (ENOMEM);
+
+ olh->size = sz;
+ if (do_get3(opcode, &olh->opheader, &sz) != 0) {
+ free(olh);
+ return (errno);
+ }
+
+ *polh = olh;
+ return (0);
+}
+
+static int
+table_do_get_algolist(ipfw_obj_lheader **polh)
+{
+
+ return (table_do_get_stdlist(IP_FW_TABLES_ALIST, polh));
+}
+
+static int
+table_do_get_vlist(ipfw_obj_lheader **polh)
+{
+
+ return (table_do_get_stdlist(IP_FW_TABLE_VLIST, polh));
+}
+
+void
+ipfw_list_ta(int ac, char *av[])
+{
+ ipfw_obj_lheader *olh;
+ ipfw_ta_info *info;
+ int error, i;
+ const char *atype;
+
+ error = table_do_get_algolist(&olh);
+ if (error != 0)
+ err(EX_OSERR, "Unable to request algorithm list");
+
+ info = (ipfw_ta_info *)(olh + 1);
+ for (i = 0; i < olh->count; i++) {
+ if ((atype = match_value(tabletypes, info->type)) == NULL)
+ atype = "unknown";
+ printf("--- %s ---\n", info->algoname);
+ printf(" type: %s\n refcount: %u\n", atype, info->refcnt);
+
+ info = (ipfw_ta_info *)((caddr_t)info + olh->objsize);
+ }
+
+ free(olh);
+}
+
+
+/* Copy of current kernel table_value structure */
+struct _table_value {
+ uint32_t tag; /* O_TAG/O_TAGGED */
+ uint32_t pipe; /* O_PIPE/O_QUEUE */
+ uint16_t divert; /* O_DIVERT/O_TEE */
+ uint16_t skipto; /* skipto, CALLRET */
+ uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */
+ uint32_t fib; /* O_SETFIB */
+ uint32_t nat; /* O_NAT */
+ uint32_t nh4;
+ uint8_t dscp;
+ uint8_t spare0[3];
+ /* -- 32 bytes -- */
+ struct in6_addr nh6;
+ uint32_t limit; /* O_LIMIT */
+ uint32_t spare1;
+ uint64_t refcnt; /* Number of references */
+};
+
+int
+compare_values(const void *_a, const void *_b)
+{
+ struct _table_value *a, *b;
+
+ a = (struct _table_value *)_a;
+ b = (struct _table_value *)_b;
+
+ if (a->spare1 < b->spare1)
+ return (-1);
+ else if (a->spare1 > b->spare1)
+ return (1);
+
+ return (0);
+}
+
+void
+ipfw_list_values(int ac, char *av[])
+{
+ ipfw_obj_lheader *olh;
+ struct _table_value *v;
+ int error, i;
+ uint32_t vmask;
+ char buf[128];
+
+ error = table_do_get_vlist(&olh);
+ if (error != 0)
+ err(EX_OSERR, "Unable to request value list");
+
+ vmask = 0x7FFFFFFF; /* Similar to IPFW_VTYPE_LEGACY */
+
+ table_print_valheader(buf, sizeof(buf), vmask);
+ printf("HEADER: %s\n", buf);
+ v = (struct _table_value *)(olh + 1);
+ qsort(v, olh->count, olh->objsize, compare_values);
+ for (i = 0; i < olh->count; i++) {
+ table_show_value(buf, sizeof(buf), (ipfw_table_value *)v,
+ vmask, 0);
+ printf("[%u] refs=%lu %s\n", v->spare1, v->refcnt, buf);
+ v = (struct _table_value *)((caddr_t)v + olh->objsize);
+ }
+
+ free(olh);
+}
+
+int
+compare_ntlv(const void *_a, const void *_b)
+{
+ ipfw_obj_ntlv *a, *b;
+
+ a = (ipfw_obj_ntlv *)_a;
+ b = (ipfw_obj_ntlv *)_b;
+
+ if (a->set < b->set)
+ return (-1);
+ else if (a->set > b->set)
+ return (1);
+
+ if (a->idx < b->idx)
+ return (-1);
+ else if (a->idx > b->idx)
+ return (1);
+
+ return (0);
+}
+
+int
+compare_kntlv(const void *k, const void *v)
+{
+ ipfw_obj_ntlv *ntlv;
+ uint16_t key;
+
+ key = *((uint16_t *)k);
+ ntlv = (ipfw_obj_ntlv *)v;
+
+ if (key < ntlv->idx)
+ return (-1);
+ else if (key > ntlv->idx)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Finds table name in @ctlv by @idx.
+ * Uses the following facts:
+ * 1) All TLVs are the same size
+ * 2) Kernel implementation provides already sorted list.
+ *
+ * Returns table name or NULL.
+ */
+char *
+table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx)
+{
+ ipfw_obj_ntlv *ntlv;
+
+ ntlv = bsearch(&idx, (ctlv + 1), ctlv->count, ctlv->objsize,
+ compare_kntlv);
+
+ if (ntlv != 0)
+ return (ntlv->name);
+
+ return (NULL);
+}
+
+void
+table_sort_ctlv(ipfw_obj_ctlv *ctlv)
+{
+
+ qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv);
+}
+
+int
+table_check_name(char *tablename)
+{
+ int c, i, l;
+
+ /*
+ * Check if tablename is null-terminated and contains
+ * valid symbols only. Valid mask is:
+ * [a-zA-Z0-9\-_\.]{1,63}
+ */
+ l = strlen(tablename);
+ if (l == 0 || l >= 64)
+ return (EINVAL);
+ for (i = 0; i < l; i++) {
+ c = tablename[i];
+ if (isalpha(c) || isdigit(c) || c == '_' ||
+ c == '-' || c == '.')
+ continue;
+ return (EINVAL);
+ }
+
+ /* Restrict some 'special' names */
+ if (strcmp(tablename, "all") == 0)
+ return (EINVAL);
+
+ return (0);
+}
+
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index 5c6086d..033c40a 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -172,15 +172,8 @@ main(int argc, char **argv)
continue;
if (strstr(fsp->fs_mntops, "noauto") != NULL)
continue;
- /*
- * Forcibly enable "late" option when file= is
- * specified. This is because mounting file
- * systems with rw option is typically
- * required to make the backing store ready.
- */
if (which_prog != SWAPOFF &&
- (strstr(fsp->fs_mntops, "late") != NULL ||
- strstr(fsp->fs_mntops, "file=") != NULL) &&
+ strstr(fsp->fs_mntops, "late") &&
late == 0)
continue;
swfile = swap_on_off(fsp->fs_spec, 1,
diff --git a/share/man/man4/alc.4 b/share/man/man4/alc.4
index 0c6af6a..73647c1 100644
--- a/share/man/man4/alc.4
+++ b/share/man/man4/alc.4
@@ -24,12 +24,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 9, 2010
+.Dd October 8, 2014
.Dt ALC 4
.Os
.Sh NAME
.Nm alc
-.Nd Atheros AR813x/AR815x Gigabit/Fast Ethernet driver
+.Nd Atheros AR813x/AR815x/AR816x/AR817x Gigabit/Fast Ethernet driver
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
@@ -48,8 +48,8 @@ if_alc_load="YES"
.Sh DESCRIPTION
The
.Nm
-device driver provides support for Atheros AR813x and AR815x PCI
-Express Gigabit/Fast Ethernet controllers.
+device driver provides support for Atheros AR813x, AR815x, AR816x
+and AR817x PCI Express Gigabit/Fast Ethernet controllers.
.Pp
All LOMs supported by the
.Nm
@@ -58,9 +58,9 @@ segmentation offload (TSO), hardware VLAN tag stripping/insertion
features, Wake On Lan (WOL) and an interrupt moderation mechanism
as well as a 64-bit multicast hash filter.
.Pp
-The AR813x and AR815x supports Jumbo Frames (up to 9216 and 6144
-bytes, respectively), which can be configured via the interface
-MTU setting.
+The AR813x, AR815x, AR816x and AR817x supports Jumbo Frames (up to
+9216, 6144, 9216 and 9216 bytes, respectively), which can be
+configured via the interface MTU setting.
Selecting an MTU larger than 1500 bytes with the
.Xr ifconfig 8
utility configures the adapter to receive and transmit Jumbo Frames.
@@ -112,6 +112,16 @@ Atheros AR8151 v2.0 PCI Express Gigabit Ethernet controller
Atheros AR8152 v1.1 PCI Express Fast Ethernet controller
.It
Atheros AR8152 v2.0 PCI Express Fast Ethernet controller
+.It
+Atheros AR8161 PCI Express Gigabit Ethernet controller
+.It
+Atheros AR8162 PCI Express Fast Ethernet controller
+.It
+Atheros AR8171 PCI Express Gigabit Ethernet controller
+.It
+Atheros AR8172 PCI Express Fast Ethernet controller
+.It
+Killer E2200 Gigabit Ethernet controller
.El
.Sh LOADER TUNABLES
Tunables can be set at the
diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5
index 47d9ef8..721fef0 100644
--- a/share/man/man5/rc.conf.5
+++ b/share/man/man5/rc.conf.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 27, 2014
+.Dd September 11, 2014
.Dt RC.CONF 5
.Os
.Sh NAME
diff --git a/share/man/man9/timeout.9 b/share/man/man9/timeout.9
index 1e82b71..fad8690 100644
--- a/share/man/man9/timeout.9
+++ b/share/man/man9/timeout.9
@@ -29,31 +29,31 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 21, 2014
+.Dd October 8, 2014
.Dt TIMEOUT 9
.Os
.Sh NAME
-.Nm timeout ,
-.Nm untimeout ,
+.Nm callout_active ,
+.Nm callout_deactivate ,
+.Nm callout_drain ,
.Nm callout_handle_init ,
.Nm callout_init ,
.Nm callout_init_mtx ,
.Nm callout_init_rm ,
.Nm callout_init_rw ,
-.Nm callout_stop ,
-.Nm callout_drain ,
+.Nm callout_pending ,
.Nm callout_reset ,
-.Nm callout_reset_on ,
.Nm callout_reset_curcpu ,
+.Nm callout_reset_on ,
.Nm callout_reset_sbt ,
-.Nm callout_reset_sbt_on ,
.Nm callout_reset_sbt_curcpu ,
+.Nm callout_reset_sbt_on ,
.Nm callout_schedule ,
-.Nm callout_schedule_on ,
.Nm callout_schedule_curcpu ,
-.Nm callout_pending ,
-.Nm callout_active ,
-.Nm callout_deactivate
+.Nm callout_schedule_on ,
+.Nm callout_stop ,
+.Nm timeout ,
+.Nm untimeout
.Nd execute a function after a specified length of time
.Sh SYNOPSIS
.In sys/types.h
@@ -61,16 +61,18 @@
.Bd -literal
typedef void timeout_t (void *);
.Ed
-.Ft struct callout_handle
-.Fn timeout "timeout_t *func" "void *arg" "int ticks"
+.Ft int
+.Fn callout_active "struct callout *c"
+.Ft void
+.Fn callout_deactivate "struct callout *c"
+.Ft int
+.Fn callout_drain "struct callout *c"
.Ft void
.Fn callout_handle_init "struct callout_handle *handle"
.Bd -literal
struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
.Ed
.Ft void
-.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle"
-.Ft void
.Fn callout_init "struct callout *c" "int mpsafe"
.Ft void
.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags"
@@ -79,314 +81,337 @@ struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
.Ft void
.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags"
.Ft int
-.Fn callout_stop "struct callout *c"
-.Ft int
-.Fn callout_drain "struct callout *c"
+.Fn callout_pending "struct callout *c"
.Ft int
.Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg"
.Ft int
+.Fn callout_reset_curcpu "struct callout *c" "int ticks" "timeout_t *func" \
+"void *arg"
+.Ft int
.Fn callout_reset_on "struct callout *c" "int ticks" "timeout_t *func" \
"void *arg" "int cpu"
.Ft int
+.Fn callout_reset_sbt "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
+.Ft int
+.Fn callout_reset_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
+.Ft int
.Fn callout_reset_sbt_on "struct callout *c" "sbintime_t sbt" \
"sbintime_t pr" "timeout_t *func" "void *arg" "int cpu" "int flags"
.Ft int
-.Fn callout_reset_curcpu "struct callout *c" "int ticks" "timeout_t *func" \
-"void *arg"
-.Ft int
.Fn callout_schedule "struct callout *c" "int ticks"
.Ft int
-.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
-.Ft int
.Fn callout_schedule_curcpu "struct callout *c" "int ticks"
.Ft int
-.Fn callout_pending "struct callout *c"
+.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
.Ft int
-.Fn callout_active "struct callout *c"
+.Fn callout_stop "struct callout *c"
+.Ft struct callout_handle
+.Fn timeout "timeout_t *func" "void *arg" "int ticks"
.Ft void
-.Fn callout_deactivate "struct callout *c"
+.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle"
.Sh DESCRIPTION
-The function
-.Fn timeout
-schedules a call to the function given by the argument
-.Fa func
-to take place after
-.Fa ticks Ns No /hz
-seconds.
-Non-positive values of
-.Fa ticks
-are silently converted to the value
-.Sq 1 .
-.Fa func
-should be a pointer to a function that takes a
-.Fa void *
-argument.
-Upon invocation,
-.Fa func
-will receive
-.Fa arg
-as its only argument.
-The return value from
-.Fn timeout
-is a
-.Ft struct callout_handle
-which can be used in conjunction with the
-.Fn untimeout
-function to request that a scheduled timeout be canceled.
The
-.Fn timeout
-call is the old style and new code should use the
-.Fn callout_*
-functions.
+.Nm callout
+API is used to schedule a call to an arbitrary function at a specific
+time in the future.
+Consumers of this API are required to allocate a callout structure
+.Pq struct callout
+for each pending function invocation.
+This structure stores state about the pending function invocation including
+the function to be called and the time at which the function should be invoked.
+Pending function calls can be cancelled or rescheduled to a different time.
+In addition,
+a callout structure may be reused to schedule a new function call after a
+scheduled call is completed.
.Pp
-The function
-.Fn callout_handle_init
-can be used to initialize a handle to a state which will cause
-any calls to
-.Fn untimeout
-with that handle to return with no side
-effects.
-.Pp
-Assigning a callout handle the value of
-.Fn CALLOUT_HANDLE_INITIALIZER
-performs the same function as
-.Fn callout_handle_init
-and is provided for use on statically declared or global callout handles.
-.Pp
-The function
-.Fn untimeout
-cancels the timeout associated with
-.Fa handle
-using the
-.Fa func
-and
-.Fa arg
-arguments to validate the handle.
-If the handle does not correspond to a timeout with
-the function
-.Fa func
-taking the argument
-.Fa arg
-no action is taken.
-.Fa handle
-must be initialized by a previous call to
-.Fn timeout ,
-.Fn callout_handle_init ,
-or assigned the value of
-.Fn CALLOUT_HANDLE_INITIALIZER "&handle"
-before being passed to
-.Fn untimeout .
-The behavior of calling
-.Fn untimeout
-with an uninitialized handle
-is undefined.
-The
-.Fn untimeout
-call is the old style and new code should use the
-.Fn callout_*
-functions.
+Callouts only provide a single-shot mode.
+If a consumer requires a periodic timer,
+it must explicitly reschedule each function call.
+This is normally done by rescheduling the subsequent call within the called
+function.
.Pp
-As handles are recycled by the system, it is possible (although unlikely)
-that a handle from one invocation of
-.Fn timeout
-may match the handle of another invocation of
-.Fn timeout
-if both calls used the same function pointer and argument, and the first
-timeout is expired or canceled before the second call.
-The timeout facility offers O(1) running time for
-.Fn timeout
-and
-.Fn untimeout .
-Timeouts are executed from
-.Fn softclock
-with the
-.Va Giant
-lock held.
-Thus they are protected from re-entrancy.
+Callout functions must not sleep.
+They may not acquire sleepable locks,
+wait on condition variables,
+perform blocking allocation requests,
+or invoke any other action that might sleep.
.Pp
-The functions
+Each callout structure must be initialized by
.Fn callout_init ,
.Fn callout_init_mtx ,
.Fn callout_init_rm ,
-.Fn callout_init_rw ,
-.Fn callout_stop ,
-.Fn callout_drain ,
-.Fn callout_reset
-and
-.Fn callout_schedule
-are low-level routines for clients who wish to allocate their own
-callout structures.
-.Pp
-The function
-.Fn callout_init
-initializes a callout so it can be passed to
-.Fn callout_stop ,
-.Fn callout_drain ,
-.Fn callout_reset
or
-.Fn callout_schedule
-without any side effects.
+.Fn callout_init_rw
+before it is passed to any of the other callout functions.
+The
+.Fn callout_init
+function initializes a callout structure in
+.Fa c
+that is not associated with a specific lock.
If the
.Fa mpsafe
argument is zero,
the callout structure is not considered to be
.Dq multi-processor safe ;
-that is,
-the Giant lock will be acquired before calling the callout function,
+and the Giant lock will be acquired before calling the callout function
and released when the callout function returns.
.Pp
The
-.Fn callout_init_mtx
-function may be used as an alternative to
-.Fn callout_init .
-The parameter
-.Fa mtx
-specifies a mutex that is to be acquired by the callout subsystem
-before calling the callout function, and released when the callout
-function returns.
-The following
-.Fa flags
-may be specified:
-.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED"
-.It Dv CALLOUT_RETURNUNLOCKED
-The callout function will release
-.Fa mtx
-itself, so the callout subsystem should not attempt to unlock it
-after the callout function returns.
-.El
-.Pp
-The
+.Fn callout_init_mtx ,
+.Fn callout_init_rm ,
+and
.Fn callout_init_rw
-and the
-.Fn callout_init_rm
-fuctions serve the need of using rwlocks and rmlocks in conjunction
-with callouts.
-The functions do the same as
-.Fn callout_init
-with the possibility of specifying an extra
-.Fa rw
+functions initialize a callout structure in
+.Fa c
+that is associated with a specific lock.
+The lock is specified by the
+.Fa mtx ,
+.Fa rm ,
or
-.Fa rm
-argument.
-If an
-.Fa rm
-argument is specified, the lock should be created without passing the
+.Fa rw
+parameter.
+The associated lock must be held while stopping or rescheduling the
+callout.
+The callout subsystem acquires the associated lock before calling the
+callout function and releases it after the function returns.
+If the callout was cancelled while the callout subsystem waited for the
+associated lock,
+the callout function is not called,
+and the associated lock is released.
+This ensures that stopping or rescheduling the callout will abort any
+previously scheduled invocation.
+.Pp
+Only regular mutexes may be used with
+.Fn callout_init_mtx ;
+spin mutexes are not supported.
+A sleepable read-mostly lock
+.Po
+one initialized with the
.Dv RM_SLEEPABLE
-flag.
-The usable lock classes are currently limited to mutexes, rwlocks and
-non-sleepable rmlocks, because callout handlers run in softclock swi,
-so they cannot sleep nor acquire sleepable locks like sx or lockmgr.
-The following
+flag
+.Pc
+may not be used with
+.Fn callout_init_rm .
+Similarly, other sleepable lock types such as
+.Xr sx 9
+and
+.Xr lockmgr 9
+cannot be used with callouts because sleeping is not permitted in
+the callout subsystem.
+.Pp
+These
.Fa flags
-may be specified:
-.Bl -tag -width ".Dv CALLOUT_SHAREDLOCK"
+may be specified for
+.Fn callout_init_mtx ,
+.Fn callout_init_rm ,
+or
+.Fn callout_init_rw :
+.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED"
+.It Dv CALLOUT_RETURNUNLOCKED
+The callout function will release the associated lock itself,
+so the callout subsystem should not attempt to unlock it
+after the callout function returns.
.It Dv CALLOUT_SHAREDLOCK
The lock is only acquired in read mode when running the callout handler.
-It has no effects when used in conjunction with
-.Fa mtx .
+This flag is ignored by
+.Fn callout_init_mtx .
.El
.Pp
The function
.Fn callout_stop
-cancels a callout if it is currently pending.
+cancels a callout
+.Fa c
+if it is currently pending.
If the callout is pending, then
.Fn callout_stop
-will return a non-zero value.
-If the callout is not set, has already been serviced or is currently
-being serviced, then zero will be returned.
-If the callout has an associated mutex, then that mutex must be
-held when this function is called.
+returns a non-zero value.
+If the callout is not set,
+has already been serviced,
+or is currently being serviced,
+then zero will be returned.
+If the callout has an associated lock,
+then that lock must be held when this function is called.
.Pp
The function
.Fn callout_drain
is identical to
.Fn callout_stop
-except that it will wait for the callout to be completed if it is
-already in progress.
+except that it will wait for the callout
+.Fa c
+to complete if it is already in progress.
This function MUST NOT be called while holding any
locks on which the callout might block, or deadlock will result.
Note that if the callout subsystem has already begun processing this
-callout, then the callout function may be invoked during the execution of
-.Fn callout_drain .
+callout, then the callout function may be invoked before
+.Fn callout_drain
+returns.
However, the callout subsystem does guarantee that the callout will be
fully stopped before
.Fn callout_drain
returns.
.Pp
-The function
-.Fn callout_reset
-first performs the equivalent of
-.Fn callout_stop
-to disestablish the callout, and then establishes a new callout in the
-same manner as
-.Fn timeout .
-If there was already a pending callout and it was rescheduled, then
-.Fn callout_reset
-will return a non-zero value.
-If the callout has an associated mutex, then that mutex must be
-held when this function is called.
-The function
-.Fn callout_schedule
-(re)schedules an existing callout for a new period of time;
-it is equivalent to calling
-.Fn callout_reset
-with the
-.Fa func
-and
-.Fa arg
-parameters extracted from the callout structure (though possibly with
-lower overhead).
-.Pp
-The functions
-.Fn callout_reset_on
-and
-.Fn callout_schedule_on
-are equivalent to
+The
.Fn callout_reset
and
.Fn callout_schedule
-but take an extra parameter specifying the target CPU for the callout.
+function families schedule a future function invocation for callout
+.Fa c .
+If
+.Fa c
+already has a pending callout,
+it is cancelled before the new invocation is scheduled.
+These functions return a non-zero value if a pending callout was cancelled
+and zero if there was no pending callout.
+If the callout has an associated lock,
+then that lock must be held when any of these functions are called.
.Pp
-The function
-.Fn callout_reset_sbt_on
-allows to get higher time resolution, taking relative or absolute time
-and precision instead of relative ticks count.
-If specified time is in past, it will be silently converted to present
-to run handler as soon as possible.
+The time at which the callout function will be invoked is determined by
+either the
+.Fa ticks
+argument or the
+.Fa sbt ,
+.Fa pr ,
+and
+.Fa flags
+arguments.
+When
+.Fa ticks
+is used,
+the callout is scheduled to execute after
+.Fa ticks Ns No /hz
+seconds.
+Non-positive values of
+.Fa ticks
+are silently converted to the value
+.Sq 1 .
.Pp
-The following
+The
+.Fa sbt ,
+.Fa pr ,
+and
+.Fa flags
+arguments provide more control over the scheduled time including
+support for higher resolution times,
+specifying the precision of the scheduled time,
+and setting an absolute deadline instead of a relative timeout.
+The callout is scheduled to execute in a time window which begins at
+the time specified in
+.Fa sbt
+and extends for the amount of time specified in
+.Fa pr .
+If
+.Fa sbt
+specifies a time in the past,
+the window is adjusted to start at the current time.
+A non-zero value for
+.Fa pr
+allows the callout subsystem to coalesce callouts scheduled close to each
+other into fewer timer interrupts,
+reducing processing overhead and power consumption.
+These
.Fa flags
-may be specified:
+may be specified to adjust the interpretation of
+.Fa sbt
+and
+.Fa pr :
.Bl -tag -width ".Dv C_DIRECT_EXEC"
.It Dv C_ABSOLUTE
Handle the
.Fa sbt
-argument as absolute time of the event since boot, or relative time otherwise.
+argument as an absolute time since boot.
+By default,
+.Fa sbt
+is treated as a relative amount of time,
+similar to
+.Fa ticks .
.It Dv C_DIRECT_EXEC
-Run handler directly from hardware interrupt context instead of softclock swi.
-It is faster, but puts more constraints on handlers.
-Handlers may use only spin mutexes for locking, and they must be fast because
-they run with absolute priority.
+Run the handler directly from hardware interrupt context instead of from the
+softclock thread.
+This reduces latency and overhead, but puts more constraints on the callout
+function.
+Callout functions run in this context may use only spin mutexes for locking
+and should be as small as possible because they run with absolute priority.
.It Fn C_PREL
Specifies relative event time precision as binary logarithm of time interval
divided by acceptable time deviation: 1 -- 1/2, 2 -- 1/4, etc.
-Smaller value allows to aggregate more events in one timer interrupt to
-reduce processing overhead and power consumption.
+Note that the larger of
+.Fa pr
+or this value is used as the length of the time window.
+Smaller values
+.Pq which result in larger time intervals
+allow the callout subsystem to aggregate more events in one timer interrupt.
.It Dv C_HARDCLOCK
-Align the timeouts, if possible, to
-.Fn hardclock
-calls.
+Align the timeouts to
+.Fn hardclock
+calls if possible.
.El
.Pp
-The functions
-.Fn callout_reset_curcpu
+The
+.Fn callout_reset
+functions accept a
+.Fa func
+argument which identifies the function to be called when the time expires.
+It must be a pointer to a function that takes a single
+.Fa void *
+argument.
+Upon invocation,
+.Fa func
+will receive
+.Fa arg
+as its only argument.
+The
+.Fn callout_schedule
+functions reuse the
+.Fa func
and
-.Fn callout_schedule_curcpu
-are wrappers for
-.Fn callout_reset_on
+.Fa arg
+arguments from the previous callout.
+Note that one of the
+.Fn callout_reset
+functions must always be called to initialize
+.Fa func
+and
+.Fa arg
+before one of the
+.Fn callout_schedule
+functions can be used.
+.Pp
+The callout subsystem provides a softclock thread for each CPU in the system.
+Callouts are assigned to a single CPU and are executed by the softclock thread
+for that CPU.
+Initially,
+callouts are assigned to CPU 0.
+The
+.Fn callout_reset_on ,
+.Fn callout_reset_sbt_on ,
and
.Fn callout_schedule_on
-using the current CPU as the target CPU.
+functions assign the callout to CPU
+.Fa cpu .
+The
+.Fn callout_reset_curcpu ,
+.Fn callout_reset_sbt_curpu ,
+and
+.Fn callout_schedule_curcpu
+functions assign the callout to the current CPU.
+The
+.Fn callout_reset ,
+.Fn callout_reset_sbt ,
+and
+.Fn callout_schedule
+functions schedule the callout to execute in the softclock thread of the CPU
+to which it is currently assigned.
+.Pp
+Softclock threads are not pinned to their respective CPUs by default.
+The softclock thread for CPU 0 can be pinned to CPU 0 by setting the
+.Va kern.pin_default_swi
+loader tunable to a non-zero value.
+Softclock threads for CPUs other than zero can be pinned to their
+respective CPUs by setting the
+.Va kern.pin_pcpu_swi
+loader tunable to a non-zero value.
.Pp
The macros
.Fn callout_pending ,
@@ -394,10 +419,6 @@ The macros
and
.Fn callout_deactivate
provide access to the current state of the callout.
-Careful use of these macros can avoid many of the race conditions
-that are inherent in asynchronous timer facilities; see
-.Sx "Avoiding Race Conditions"
-below for further details.
The
.Fn callout_pending
macro checks whether a callout is
@@ -410,7 +431,8 @@ starts to process this callout,
.Fn callout_pending
will return
.Dv FALSE
-even though the callout function may not have finished (or even begun)
+even though the callout function may not have finished
+.Pq or even begun
executing.
The
.Fn callout_active
@@ -434,45 +456,64 @@ but it
clear it when a callout expires normally via the execution of the
callout function.
.Ss "Avoiding Race Conditions"
-The callout subsystem invokes callout functions from its own timer
+The callout subsystem invokes callout functions from its own thread
context.
-Without some kind of synchronization it is possible that a callout
+Without some kind of synchronization,
+it is possible that a callout
function will be invoked concurrently with an attempt to stop or reset
the callout by another thread.
-In particular, since callout functions typically acquire a mutex as
+In particular, since callout functions typically acquire a lock as
their first action, the callout function may have already been invoked,
-but be blocked waiting for that mutex at the time that another thread
+but is blocked waiting for that lock at the time that another thread
tries to reset or stop the callout.
.Pp
-The callout subsystem provides a number of mechanisms to address these
-synchronization concerns:
+There are three main techniques for addressing these
+synchronization concerns.
+The first approach is preferred as it is the simplest:
.Bl -enum -offset indent
.It
-If the callout has an associated mutex that was specified using the
-.Fn callout_init_mtx
-function (or implicitly specified as the
-.Va Giant
-mutex using
+Callouts can be associated with a specific lock when they are initialized
+by
+.Fn callout_init_mtx ,
+.Fn callout_init_rm ,
+or
+.Fn callout_init_rw .
+When a callout is associated with a lock,
+the callout subsystem acquires the lock before the callout function is
+invoked.
+This allows the callout subsystem to transparently handle races between
+callout cancellation,
+scheduling,
+and execution.
+Note that the associated lock must be acquired before calling
+.Fn callout_stop
+or one of the
+.Fn callout_reset
+or
+.Fn callout_schedule
+functions to provide this safety.
+.Pp
+A callout initialized via
.Fn callout_init
with
.Fa mpsafe
-set to
-.Dv FALSE ) ,
-then this mutex is used to avoid the race conditions.
-The associated mutex must be acquired by the caller before calling
-.Fn callout_stop
-or
-.Fn callout_reset
-and it is guaranteed that the callout will be correctly stopped
-or reset as expected.
-Note that it is still necessary to use
-.Fn callout_drain
-before destroying the callout or its associated mutex.
+set to zero is implicitly associated with the
+.Va Giant
+mutex.
+If
+.Va Giant
+is held when cancelling or rescheduling the callout,
+then its use will prevent races with the callout function.
.It
The return value from
.Fn callout_stop
-and
+.Po
+or the
.Fn callout_reset
+and
+.Fn callout_schedule
+function families
+.Pc
indicates whether or not the callout was removed.
If it is known that the callout was set and the callout function has
not yet executed, then a return value of
@@ -607,19 +648,134 @@ data objects that have already been destroyed or recycled.
To ensure that the callout is completely finished, a call to
.Fn callout_drain
should be used.
-.Sh RETURN VALUES
-The
+In particular,
+a callout should always be drained prior to destroying its associated lock
+or releasing the storage for the callout structure.
+.Sh LEGACY API
+.Bf Sy
+The functions below are a legacy API that will be removed in a future release.
+New code should not use these routines.
+.Ef
+.Pp
+The function
.Fn timeout
-function returns a
+schedules a call to the function given by the argument
+.Fa func
+to take place after
+.Fa ticks Ns No /hz
+seconds.
+Non-positive values of
+.Fa ticks
+are silently converted to the value
+.Sq 1 .
+.Fa func
+should be a pointer to a function that takes a
+.Fa void *
+argument.
+Upon invocation,
+.Fa func
+will receive
+.Fa arg
+as its only argument.
+The return value from
+.Fn timeout
+is a
.Ft struct callout_handle
-that can be passed to
+which can be used in conjunction with the
+.Fn untimeout
+function to request that a scheduled timeout be canceled.
+.Pp
+The function
+.Fn callout_handle_init
+can be used to initialize a handle to a state which will cause
+any calls to
+.Fn untimeout
+with that handle to return with no side
+effects.
+.Pp
+Assigning a callout handle the value of
+.Fn CALLOUT_HANDLE_INITIALIZER
+performs the same function as
+.Fn callout_handle_init
+and is provided for use on statically declared or global callout handles.
+.Pp
+The function
+.Fn untimeout
+cancels the timeout associated with
+.Fa handle
+using the
+.Fa func
+and
+.Fa arg
+arguments to validate the handle.
+If the handle does not correspond to a timeout with
+the function
+.Fa func
+taking the argument
+.Fa arg
+no action is taken.
+.Fa handle
+must be initialized by a previous call to
+.Fn timeout ,
+.Fn callout_handle_init ,
+or assigned the value of
+.Fn CALLOUT_HANDLE_INITIALIZER "&handle"
+before being passed to
.Fn untimeout .
+The behavior of calling
+.Fn untimeout
+with an uninitialized handle
+is undefined.
+.Pp
+As handles are recycled by the system, it is possible (although unlikely)
+that a handle from one invocation of
+.Fn timeout
+may match the handle of another invocation of
+.Fn timeout
+if both calls used the same function pointer and argument, and the first
+timeout is expired or canceled before the second call.
+The timeout facility offers O(1) running time for
+.Fn timeout
+and
+.Fn untimeout .
+Timeouts are executed from
+.Fn softclock
+with the
+.Va Giant
+lock held.
+Thus they are protected from re-entrancy.
+.Sh RETURN VALUES
+The
+.Fn callout_active
+macro returns the state of a callout's
+.Em active
+flag.
+.Pp
+The
+.Fn callout_pending
+macro returns the state of a callout's
+.Em pending
+flag.
+.Pp
+The
+.Fn callout_reset
+and
+.Fn callout_schedule
+function families return non-zero if the callout was pending before the new
+function invocation was scheduled.
+.Pp
The
.Fn callout_stop
and
.Fn callout_drain
functions return non-zero if the callout was still pending when it was
called or zero otherwise.
+The
+.Fn timeout
+function returns a
+.Ft struct callout_handle
+that can be passed to
+.Fn untimeout .
.Sh HISTORY
The current timeout and untimeout routines are based on the work of
.An Adam M. Costello
diff --git a/share/mk/sys.mk b/share/mk/sys.mk
index 981b750..4ff4fc8 100644
--- a/share/mk/sys.mk
+++ b/share/mk/sys.mk
@@ -146,6 +146,10 @@ RFLAGS ?=
SHELL ?= sh
+.if !defined(%POSIX)
+SIZE ?= size
+.endif
+
YACC ?= yacc
.if defined(%POSIX)
YFLAGS ?=
diff --git a/sys/amd64/amd64/minidump_machdep.c b/sys/amd64/amd64/minidump_machdep.c
index 0ee8bcf..61b348e 100644
--- a/sys/amd64/amd64/minidump_machdep.c
+++ b/sys/amd64/amd64/minidump_machdep.c
@@ -215,7 +215,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
/* A fake page table page, to avoid having to handle both 4K and 2M pages */
static pd_entry_t fakepd[NPDEPG];
-void
+int
minidumpsys(struct dumperinfo *di)
{
uint32_t pmapsize;
@@ -441,7 +441,7 @@ minidumpsys(struct dumperinfo *di)
/* Signal completion, signoff and exit stage left. */
dump_write(di, NULL, 0, 0, 0);
printf("\nDump complete\n");
- return;
+ return (0);
fail:
if (error < 0)
@@ -462,6 +462,7 @@ minidumpsys(struct dumperinfo *di)
printf("Dump failed. Partition too small.\n");
else
printf("** DUMP FAILED (ERROR %d) **\n", error);
+ return (error);
}
void
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 65287e6..291fd76 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -1729,16 +1729,20 @@ pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde)
#define PMAP_CLFLUSH_THRESHOLD (2 * 1024 * 1024)
void
-pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
+pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva, boolean_t force)
{
- KASSERT((sva & PAGE_MASK) == 0,
- ("pmap_invalidate_cache_range: sva not page-aligned"));
- KASSERT((eva & PAGE_MASK) == 0,
- ("pmap_invalidate_cache_range: eva not page-aligned"));
+ if (force) {
+ sva &= ~(vm_offset_t)cpu_clflush_line_size;
+ } else {
+ KASSERT((sva & PAGE_MASK) == 0,
+ ("pmap_invalidate_cache_range: sva not page-aligned"));
+ KASSERT((eva & PAGE_MASK) == 0,
+ ("pmap_invalidate_cache_range: eva not page-aligned"));
+ }
- if (cpu_feature & CPUID_SS)
- ; /* If "Self Snoop" is supported, do nothing. */
+ if ((cpu_feature & CPUID_SS) != 0 && !force)
+ ; /* If "Self Snoop" is supported and allowed, do nothing. */
else if ((cpu_feature & CPUID_CLFSH) != 0 &&
eva - sva < PMAP_CLFLUSH_THRESHOLD) {
@@ -6241,7 +6245,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE)
pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
- pmap_invalidate_cache_range(va, va + tmpsize);
+ pmap_invalidate_cache_range(va, va + tmpsize, FALSE);
return ((void *)(va + offset));
}
@@ -6577,7 +6581,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
*/
if (changed) {
pmap_invalidate_range(kernel_pmap, base, tmpva);
- pmap_invalidate_cache_range(base, tmpva);
+ pmap_invalidate_cache_range(base, tmpva, FALSE);
}
return (error);
}
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index c7b89a6..e5e78f6 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -118,7 +118,7 @@ void pagezero(void *addr);
void printcpuinfo(void);
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
int user_dbreg_trap(void);
-void minidumpsys(struct dumperinfo *);
+int minidumpsys(struct dumperinfo *);
struct savefpu *get_pcb_user_save_td(struct thread *td);
struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
struct pcb *get_pcb_td(struct thread *td);
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
index e83e07e..ebf32c6 100644
--- a/sys/amd64/include/pmap.h
+++ b/sys/amd64/include/pmap.h
@@ -394,7 +394,8 @@ void pmap_invalidate_range(pmap_t, vm_offset_t, vm_offset_t);
void pmap_invalidate_all(pmap_t);
void pmap_invalidate_cache(void);
void pmap_invalidate_cache_pages(vm_page_t *pages, int count);
-void pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva);
+void pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva,
+ boolean_t force);
void pmap_get_mapping(pmap_t pmap, vm_offset_t va, uint64_t *ptr, int *num);
#endif /* _KERNEL */
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index 44fd2ea..548ea2a 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -485,6 +485,8 @@ enum vm_exitcode {
VM_EXITCODE_SUSPENDED,
VM_EXITCODE_INOUT_STR,
VM_EXITCODE_TASK_SWITCH,
+ VM_EXITCODE_MONITOR,
+ VM_EXITCODE_MWAIT,
VM_EXITCODE_SVM,
VM_EXITCODE_MAX
};
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 748be15b..c855697 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -81,6 +81,8 @@ __FBSDID("$FreeBSD$");
#define PROCBASED_CTLS_ONE_SETTING \
(PROCBASED_SECONDARY_CONTROLS | \
+ PROCBASED_MWAIT_EXITING | \
+ PROCBASED_MONITOR_EXITING | \
PROCBASED_IO_EXITING | \
PROCBASED_MSR_BITMAPS | \
PROCBASED_CTLS_WINDOW_SETTING | \
@@ -2372,6 +2374,12 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
case EXIT_REASON_XSETBV:
handled = vmx_emulate_xsetbv(vmx, vcpu, vmexit);
break;
+ case EXIT_REASON_MONITOR:
+ vmexit->exitcode = VM_EXITCODE_MONITOR;
+ break;
+ case EXIT_REASON_MWAIT:
+ vmexit->exitcode = VM_EXITCODE_MWAIT;
+ break;
default:
vmm_stat_incr(vmx->vm, vcpu, VMEXIT_UNKNOWN, 1);
break;
diff --git a/sys/amd64/vmm/intel/vmx_msr.c b/sys/amd64/vmm/intel/vmx_msr.c
index 94d52e3..746ca73 100644
--- a/sys/amd64/vmm/intel/vmx_msr.c
+++ b/sys/amd64/vmm/intel/vmx_msr.c
@@ -33,7 +33,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/cpuset.h>
+#include <machine/clock.h>
#include <machine/cpufunc.h>
+#include <machine/md_var.h>
#include <machine/specialreg.h>
#include <machine/vmm.h>
@@ -176,11 +178,64 @@ msr_bitmap_change_access(char *bitmap, u_int msr, int access)
}
static uint64_t misc_enable;
+static uint64_t platform_info;
+static uint64_t turbo_ratio_limit;
static uint64_t host_msrs[GUEST_MSR_NUM];
+static bool
+nehalem_cpu(void)
+{
+ u_int family, model;
+
+ /*
+ * The family:model numbers belonging to the Nehalem microarchitecture
+ * are documented in Section 35.5, Intel SDM dated Feb 2014.
+ */
+ family = CPUID_TO_FAMILY(cpu_id);
+ model = CPUID_TO_MODEL(cpu_id);
+ if (family == 0x6) {
+ switch (model) {
+ case 0x1A:
+ case 0x1E:
+ case 0x1F:
+ case 0x2E:
+ return (true);
+ default:
+ break;
+ }
+ }
+ return (false);
+}
+
+static bool
+westmere_cpu(void)
+{
+ u_int family, model;
+
+ /*
+ * The family:model numbers belonging to the Westmere microarchitecture
+ * are documented in Section 35.6, Intel SDM dated Feb 2014.
+ */
+ family = CPUID_TO_FAMILY(cpu_id);
+ model = CPUID_TO_MODEL(cpu_id);
+ if (family == 0x6) {
+ switch (model) {
+ case 0x25:
+ case 0x2C:
+ return (true);
+ default:
+ break;
+ }
+ }
+ return (false);
+}
+
void
vmx_msr_init(void)
{
+ uint64_t bus_freq, ratio;
+ int i;
+
/*
* It is safe to cache the values of the following MSRs because
* they don't change based on curcpu, curproc or curthread.
@@ -204,6 +259,44 @@ vmx_msr_init(void)
*/
misc_enable |= (1 << 12) | (1 << 11);
misc_enable &= ~((1 << 18) | (1 << 16));
+
+ if (nehalem_cpu() || westmere_cpu())
+ bus_freq = 133330000; /* 133Mhz */
+ else
+ bus_freq = 100000000; /* 100Mhz */
+
+ /*
+ * XXXtime
+ * The ratio should really be based on the virtual TSC frequency as
+ * opposed to the host TSC.
+ */
+ ratio = (tsc_freq / bus_freq) & 0xff;
+
+ /*
+ * The register definition is based on the micro-architecture
+ * but the following bits are always the same:
+ * [15:8] Maximum Non-Turbo Ratio
+ * [28] Programmable Ratio Limit for Turbo Mode
+ * [29] Programmable TDC-TDP Limit for Turbo Mode
+ * [47:40] Maximum Efficiency Ratio
+ *
+ * The other bits can be safely set to 0 on all
+ * micro-architectures up to Haswell.
+ */
+ platform_info = (ratio << 8) | (ratio << 40);
+
+ /*
+ * The number of valid bits in the MSR_TURBO_RATIO_LIMITx register is
+ * dependent on the maximum cores per package supported by the micro-
+ * architecture. For e.g., Westmere supports 6 cores per package and
+ * uses the low 48 bits. Sandybridge support 8 cores per package and
+ * uses up all 64 bits.
+ *
+ * However, the unused bits are reserved so we pretend that all bits
+ * in this MSR are valid.
+ */
+ for (i = 0; i < 8; i++)
+ turbo_ratio_limit = (turbo_ratio_limit << 8) | ratio;
}
void
@@ -266,6 +359,13 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu)
case MSR_IA32_MISC_ENABLE:
*val = misc_enable;
break;
+ case MSR_PLATFORM_INFO:
+ *val = platform_info;
+ break;
+ case MSR_TURBO_RATIO_LIMIT:
+ case MSR_TURBO_RATIO_LIMIT1:
+ *val = turbo_ratio_limit;
+ break;
default:
error = EINVAL;
break;
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index d73c7b3..af62294 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -1497,6 +1497,10 @@ restart:
case VM_EXITCODE_INOUT_STR:
error = vm_handle_inout(vm, vcpuid, vme, &retu);
break;
+ case VM_EXITCODE_MONITOR:
+ case VM_EXITCODE_MWAIT:
+ vm_inject_ud(vm, vcpuid);
+ break;
default:
retu = true; /* handled in userland */
break;
diff --git a/sys/arm/altera/socfpga/files.socfpga b/sys/arm/altera/socfpga/files.socfpga
index c420617..df92bff 100644
--- a/sys/arm/altera/socfpga/files.socfpga
+++ b/sys/arm/altera/socfpga/files.socfpga
@@ -19,3 +19,4 @@ arm/altera/socfpga/socfpga_manager.c standard
arm/altera/socfpga/socfpga_rstmgr.c standard
dev/dwc/if_dwc.c optional dwc
+dev/mmc/host/dwmmc.c optional dwmmc
diff --git a/sys/arm/altera/socfpga/socfpga_machdep.c b/sys/arm/altera/socfpga/socfpga_machdep.c
index b098663..703c88a 100644
--- a/sys/arm/altera/socfpga/socfpga_machdep.c
+++ b/sys/arm/altera/socfpga/socfpga_machdep.c
@@ -89,6 +89,9 @@ platform_devmap_init(void)
*/
arm_devmap_add_entry(0xffb00000, 0x100000);
+ /* dwmmc */
+ arm_devmap_add_entry(0xff700000, 0x100000);
+
return (0);
}
diff --git a/sys/arm/arm/dump_machdep.c b/sys/arm/arm/dump_machdep.c
index b5a37f2..d8104d1 100644
--- a/sys/arm/arm/dump_machdep.c
+++ b/sys/arm/arm/dump_machdep.c
@@ -280,10 +280,8 @@ dumpsys(struct dumperinfo *di)
size_t hdrsz;
int error;
- if (do_minidump) {
- minidumpsys(di);
- return (0);
- }
+ if (do_minidump)
+ return (minidumpsys(di));
bzero(&ehdr, sizeof(ehdr));
ehdr.e_ident[EI_MAG0] = ELFMAG0;
diff --git a/sys/arm/arm/minidump_machdep.c b/sys/arm/arm/minidump_machdep.c
index 13f3242..c12aefa 100644
--- a/sys/arm/arm/minidump_machdep.c
+++ b/sys/arm/arm/minidump_machdep.c
@@ -196,7 +196,7 @@ blk_write_cont(struct dumperinfo *di, vm_paddr_t pa, size_t sz)
/* A fake page table page, to avoid having to handle both 4K and 2M pages */
static pt_entry_t fakept[NPTEPG];
-void
+int
minidumpsys(struct dumperinfo *di)
{
struct minidumphdr mdhdr;
@@ -460,7 +460,7 @@ minidumpsys(struct dumperinfo *di)
/* Signal completion, signoff and exit stage left. */
dump_write(di, NULL, 0, 0, 0);
printf("\nDump complete\n");
- return;
+ return (0);
fail:
if (error < 0)
@@ -472,6 +472,7 @@ fail:
printf("\nDump failed. Partition too small.\n");
else
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+ return (error);
}
void
diff --git a/sys/arm/conf/EXYNOS5.common b/sys/arm/conf/EXYNOS5.common
index 89e978b..7cd577d 100644
--- a/sys/arm/conf/EXYNOS5.common
+++ b/sys/arm/conf/EXYNOS5.common
@@ -80,7 +80,7 @@ options NFS_ROOT # NFS usable as /, requires NFSCLIENT
device mmc # mmc/sd bus
device mmcsd # mmc/sd flash cards
-device sdhci # generic sdhci
+device dwmmc
options ROOTDEVNAME=\"ufs:/dev/da0\"
diff --git a/sys/arm/conf/SOCKIT b/sys/arm/conf/SOCKIT
index d56a7f2..a7c6a87 100644
--- a/sys/arm/conf/SOCKIT
+++ b/sys/arm/conf/SOCKIT
@@ -82,7 +82,7 @@ options NFS_ROOT # NFS usable as /, requires NFSCLIENT
device mmc # mmc/sd bus
device mmcsd # mmc/sd flash cards
-device sdhci # generic sdhci
+device dwmmc
options ROOTDEVNAME=\"ufs:/dev/da0\"
diff --git a/sys/arm/include/md_var.h b/sys/arm/include/md_var.h
index 7337b33..d54a425 100644
--- a/sys/arm/include/md_var.h
+++ b/sys/arm/include/md_var.h
@@ -68,6 +68,6 @@ extern int busdma_swi_pending;
void busdma_swi(void);
void dump_add_page(vm_paddr_t);
void dump_drop_page(vm_paddr_t);
-void minidumpsys(struct dumperinfo *);
+int minidumpsys(struct dumperinfo *);
#endif /* !_MACHINE_MD_VAR_H_ */
diff --git a/sys/arm/samsung/exynos/exynos5_machdep.c b/sys/arm/samsung/exynos/exynos5_machdep.c
index 170c01d..c5cf44e 100644
--- a/sys/arm/samsung/exynos/exynos5_machdep.c
+++ b/sys/arm/samsung/exynos/exynos5_machdep.c
@@ -78,6 +78,9 @@ platform_devmap_init(void)
/* UART */
arm_devmap_add_entry(0x12C00000, 0x100000);
+ /* DWMMC */
+ arm_devmap_add_entry(0x12200000, 0x100000);
+
return (0);
}
diff --git a/sys/arm/samsung/exynos/files.exynos5 b/sys/arm/samsung/exynos/files.exynos5
index 8dc6602..3883b28 100644
--- a/sys/arm/samsung/exynos/files.exynos5
+++ b/sys/arm/samsung/exynos/files.exynos5
@@ -33,4 +33,4 @@ arm/samsung/exynos/chrome_ec.c optional chrome_ec_i2c
arm/samsung/exynos/chrome_ec_spi.c optional chrome_ec_spi
arm/samsung/exynos/chrome_kb.c optional chrome_kb
-#dev/sdhci/sdhci_fdt.c optional sdhci
+dev/mmc/host/dwmmc.c optional dwmmc
diff --git a/sys/boot/common/disk.c b/sys/boot/common/disk.c
index a62f6fd..a541cb0 100644
--- a/sys/boot/common/disk.c
+++ b/sys/boot/common/disk.c
@@ -90,7 +90,7 @@ disk_lookup(struct disk_devdesc *dev)
entry->d_partition == dev->d_partition) {
dev->d_offset = entry->d_offset;
DEBUG("%s offset %lld", disk_fmtdev(dev),
- dev->d_offset);
+ (long long)dev->d_offset);
#ifdef DISK_DEBUG
entry->count++;
#endif
@@ -367,7 +367,7 @@ out:
dev->d_slice = slice;
dev->d_partition = partition;
DEBUG("%s offset %lld => %p", disk_fmtdev(dev),
- dev->d_offset, od);
+ (long long)dev->d_offset, od);
}
return (rc);
}
diff --git a/sys/boot/common/disk.h b/sys/boot/common/disk.h
index 1aaa031..6a78fbf 100644
--- a/sys/boot/common/disk.h
+++ b/sys/boot/common/disk.h
@@ -43,12 +43,12 @@
* BSD disklabel partition within an MBR slice:
*
* d_slice = MBR slice number (typically 1..4)
- * d_partition = disklabel partition (typically 0..7)
+ * d_partition = disklabel partition (typically 0..19)
*
* BSD disklabel partition on the true dedicated disk:
*
* d_slice = -1
- * d_partition = disklabel partition (typically 0..7)
+ * d_partition = disklabel partition (typically 0..19)
*
* GPT partition:
*
@@ -71,7 +71,7 @@
* if there are multiple slices/partitions of a given type, the first one
* is chosen.
*
- * The low-level disk device will typically call slice_open() from its open
+ * The low-level disk device will typically call disk_open() from its open
* method to interpret the disk partition tables according to the rules above.
* This will initialize d_offset to the block offset of the start of the
* selected partition - this offset should be added to the offset passed to
diff --git a/sys/boot/common/part.c b/sys/boot/common/part.c
index 086809f..f978663 100644
--- a/sys/boot/common/part.c
+++ b/sys/boot/common/part.c
@@ -53,6 +53,7 @@ static const uuid_t gpt_uuid_unused = GPT_ENT_TYPE_UNUSED;
static const uuid_t gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
static const uuid_t gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
static const uuid_t gpt_uuid_efi = GPT_ENT_TYPE_EFI;
+static const uuid_t gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD;
static const uuid_t gpt_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
static const uuid_t gpt_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS;
static const uuid_t gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
@@ -139,6 +140,8 @@ gpt_parttype(uuid_t type)
return (PART_FREEBSD_VINUM);
else if (uuid_equal(&type, &gpt_uuid_freebsd_nandfs, NULL))
return (PART_FREEBSD_NANDFS);
+ else if (uuid_equal(&type, &gpt_uuid_freebsd, NULL))
+ return (PART_FREEBSD);
return (PART_UNKNOWN);
}
@@ -298,6 +301,7 @@ ptable_gptread(struct ptable *table, void *dev, diskread_t dread)
}
}
}
+ DEBUG("GPT detected");
if (pri == 0 && sec == 0) {
/* Both primary and backup tables are invalid. */
table->type = PTABLE_NONE;
@@ -375,6 +379,7 @@ ptable_ebrread(struct ptable *table, void *dev, diskread_t dread)
buf = malloc(table->sectorsize);
if (buf == NULL)
return (table);
+ DEBUG("EBR detected");
for (i = 0; i < MAXEBRENTRIES; i++) {
#if 0 /* Some BIOSes return an incorrect number of sectors */
if (offset >= table->sectors)
@@ -467,6 +472,7 @@ ptable_bsdread(struct ptable *table, void *dev, diskread_t dread)
DEBUG("invalid number of partitions");
goto out;
}
+ DEBUG("BSD detected");
part = &dl->d_partitions[0];
raw_offset = le32toh(part[RAW_PART].p_offset);
for (i = 0; i < dl->d_npartitions; i++, part++) {
@@ -550,6 +556,7 @@ ptable_vtoc8read(struct ptable *table, void *dev, diskread_t dread)
DEBUG("invalid geometry");
goto out;
}
+ DEBUG("VTOC8 detected");
for (i = 0; i < VTOC8_NPARTS; i++) {
dl->part[i].tag = be16toh(dl->part[i].tag);
if (i == VTOC_RAW_PART ||
@@ -662,6 +669,7 @@ ptable_open(void *dev, off_t sectors, uint16_t sectorsize,
#endif
#ifdef LOADER_MBR_SUPPORT
/* Read MBR. */
+ DEBUG("MBR detected");
table->type = PTABLE_MBR;
for (i = has_ext = 0; i < NDOSPART; i++) {
if (dp[i].dp_typ == 0)
diff --git a/sys/boot/fdt/dts/arm/exynos5420-arndale-octa.dts b/sys/boot/fdt/dts/arm/exynos5420-arndale-octa.dts
index 29542c8..8f09065 100644
--- a/sys/boot/fdt/dts/arm/exynos5420-arndale-octa.dts
+++ b/sys/boot/fdt/dts/arm/exynos5420-arndale-octa.dts
@@ -47,8 +47,19 @@
status = "okay";
};
- sdhci@12220000 {
- status = "disabled";
+ mmc2: dwmmc@12220000 {
+ status = "okay";
+ num-slots = <1>;
+ supports-highspeed;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+ bus-frequency = <50000000>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ };
};
};
diff --git a/sys/boot/fdt/dts/arm/exynos5420-peach-pit.dts b/sys/boot/fdt/dts/arm/exynos5420-peach-pit.dts
index ebe3dfcf..80aca89 100644
--- a/sys/boot/fdt/dts/arm/exynos5420-peach-pit.dts
+++ b/sys/boot/fdt/dts/arm/exynos5420-peach-pit.dts
@@ -68,5 +68,20 @@
usbdrd_phy1: phy@12500000 {
vbus-supply = < 218 >;
};
+
+ mmc2: dwmmc@12220000 {
+ status = "okay";
+ num-slots = <1>;
+ supports-highspeed;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+ bus-frequency = <50000000>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ };
+ };
};
};
diff --git a/sys/boot/fdt/dts/arm/exynos5420.dtsi b/sys/boot/fdt/dts/arm/exynos5420.dtsi
index 7feb6d9..38a5a88 100644
--- a/sys/boot/fdt/dts/arm/exynos5420.dtsi
+++ b/sys/boot/fdt/dts/arm/exynos5420.dtsi
@@ -81,5 +81,32 @@
xhci@12400000 {
status = "okay";
};
+
+ mmc0: dwmmc@12200000 {
+ compatible = "samsung,exynos5420-dw-mshc-smu";
+ reg = <0x12200000 0x10000>;
+ interrupts = <107>;
+ interrupt-parent = <&GIC>;
+ fifo-depth = <0x40>;
+ status = "disabled";
+ };
+
+ mmc1: dwmmc@12210000 {
+ compatible = "samsung,exynos5420-dw-mshc-smu";
+ reg = <0x12210000 0x10000>;
+ interrupts = <108>;
+ interrupt-parent = <&GIC>;
+ fifo-depth = <0x40>;
+ status = "disabled";
+ };
+
+ mmc2: dwmmc@12220000 {
+ compatible = "samsung,exynos5420-dw-mshc";
+ reg = <0x12220000 0x10000>;
+ interrupts = <109>;
+ interrupt-parent = <&GIC>;
+ fifo-depth = <0x40>;
+ status = "disabled";
+ };
};
};
diff --git a/sys/boot/fdt/dts/arm/socfpga-sockit.dts b/sys/boot/fdt/dts/arm/socfpga-sockit.dts
index d76b6cf..058b957 100644
--- a/sys/boot/fdt/dts/arm/socfpga-sockit.dts
+++ b/sys/boot/fdt/dts/arm/socfpga-sockit.dts
@@ -55,6 +55,19 @@
gmac1: ethernet@ff702000 {
status = "okay";
};
+
+ mmc: dwmmc@ff704000 {
+ status = "okay";
+ num-slots = <1>;
+ supports-highspeed;
+ broken-cd;
+ bus-frequency = <25000000>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ };
+ };
};
chosen {
diff --git a/sys/boot/fdt/dts/arm/socfpga.dtsi b/sys/boot/fdt/dts/arm/socfpga.dtsi
index 2480484..1c8f149 100644
--- a/sys/boot/fdt/dts/arm/socfpga.dtsi
+++ b/sys/boot/fdt/dts/arm/socfpga.dtsi
@@ -152,5 +152,14 @@
phy-mode = "rgmii";
status = "disabled";
};
+
+ mmc: dwmmc@ff704000 {
+ compatible = "altr,socfpga-dw-mshc";
+ reg = <0xff704000 0x1000>;
+ interrupts = <171>;
+ interrupt-parent = <&GIC>;
+ fifo-depth = <0x400>;
+ status = "disabled";
+ };
};
};
diff --git a/sys/boot/i386/gptboot/gptboot.c b/sys/boot/i386/gptboot/gptboot.c
index 0596499..4fa5227 100644
--- a/sys/boot/i386/gptboot/gptboot.c
+++ b/sys/boot/i386/gptboot/gptboot.c
@@ -136,6 +136,7 @@ int
main(void)
{
char cmd[512], cmdtmp[512];
+ ssize_t sz;
int autoboot, dskupdated;
ufs_ino_t ino;
@@ -164,9 +165,10 @@ main(void)
for (;;) {
*kname = '\0';
if ((ino = lookup(PATH_CONFIG)) ||
- (ino = lookup(PATH_DOTCONFIG)))
- fsread(ino, cmd, sizeof(cmd));
-
+ (ino = lookup(PATH_DOTCONFIG))) {
+ sz = fsread(ino, cmd, sizeof(cmd) - 1);
+ cmd[(sz < 0) ? 0 : sz] = '\0';
+ }
if (*cmd != '\0') {
memcpy(cmdtmp, cmd, sizeof(cmdtmp));
if (parse(cmdtmp, &dskupdated))
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 3cba1b0..5042d91 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -2195,7 +2195,7 @@ xptperiphtraverse(struct cam_ed *device, struct cam_periph *start_periph,
next_periph = SLIST_NEXT(periph, periph_links);
while (next_periph != NULL &&
(next_periph->flags & CAM_PERIPH_FREE) != 0)
- next_periph = SLIST_NEXT(periph, periph_links);
+ next_periph = SLIST_NEXT(next_periph, periph_links);
if (next_periph)
next_periph->refcount++;
mtx_unlock(&bus->eb_mtx);
@@ -2269,7 +2269,7 @@ xptpdperiphtraverse(struct periph_driver **pdrv,
next_periph = TAILQ_NEXT(periph, unit_links);
while (next_periph != NULL &&
(next_periph->flags & CAM_PERIPH_FREE) != 0)
- next_periph = TAILQ_NEXT(periph, unit_links);
+ next_periph = TAILQ_NEXT(next_periph, unit_links);
if (next_periph)
next_periph->refcount++;
xpt_unlock_buses();
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 3627a50..4ed6a5a 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -293,7 +293,7 @@ static struct scsi_control_page control_page_changeable = {
/*page_length*/sizeof(struct scsi_control_page) - 2,
/*rlec*/SCP_DSENSE,
/*queue_flags*/SCP_QUEUE_ALG_MASK,
- /*eca_and_aen*/0,
+ /*eca_and_aen*/SCP_SWP,
/*flags4*/0,
/*aen_holdoff_period*/{0, 0},
/*busy_timeout_period*/{0, 0},
@@ -4447,7 +4447,7 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
struct ctl_port *port;
struct scsi_vpd_id_descriptor *desc;
struct scsi_vpd_id_t10 *t10id;
- const char *eui, *naa, *scsiname, *vendor;
+ const char *eui, *naa, *scsiname, *vendor, *value;
int lun_number, i, lun_malloced;
int devidlen, idlen1, idlen2 = 0, len;
@@ -4609,6 +4609,10 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
if (be_lun->flags & CTL_LUN_FLAG_PRIMARY)
lun->flags |= CTL_LUN_PRIMARY_SC;
+ value = ctl_get_opt(&be_lun->options, "readonly");
+ if (value != NULL && strcmp(value, "on") == 0)
+ lun->flags |= CTL_LUN_READONLY;
+
lun->ctl_softc = ctl_softc;
TAILQ_INIT(&lun->ooa_queue);
TAILQ_INIT(&lun->blocked_queue);
@@ -6219,6 +6223,14 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio,
saved_cp->queue_flags |= user_cp->queue_flags & SCP_QUEUE_ALG_MASK;
set_ua = 1;
}
+ if ((current_cp->eca_and_aen & SCP_SWP) !=
+ (user_cp->eca_and_aen & SCP_SWP)) {
+ current_cp->eca_and_aen &= ~SCP_SWP;
+ current_cp->eca_and_aen |= user_cp->eca_and_aen & SCP_SWP;
+ saved_cp->eca_and_aen &= ~SCP_SWP;
+ saved_cp->eca_and_aen |= user_cp->eca_and_aen & SCP_SWP;
+ set_ua = 1;
+ }
if (set_ua != 0) {
int i;
/*
@@ -7045,8 +7057,13 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
header = (struct scsi_mode_hdr_6 *)ctsio->kern_data_ptr;
header->datalen = ctl_min(total_len - 1, 254);
- if (control_dev == 0)
+ if (control_dev == 0) {
header->dev_specific = 0x10; /* DPOFUA */
+ if ((lun->flags & CTL_LUN_READONLY) ||
+ (lun->mode_pages.control_page[CTL_PAGE_CURRENT]
+ .eca_and_aen & SCP_SWP) != 0)
+ header->dev_specific |= 0x80; /* WP */
+ }
if (dbd)
header->block_descr_len = 0;
else
@@ -7063,8 +7080,13 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
datalen = ctl_min(total_len - 2, 65533);
scsi_ulto2b(datalen, header->datalen);
- if (control_dev == 0)
+ if (control_dev == 0) {
header->dev_specific = 0x10; /* DPOFUA */
+ if ((lun->flags & CTL_LUN_READONLY) ||
+ (lun->mode_pages.control_page[CTL_PAGE_CURRENT]
+ .eca_and_aen & SCP_SWP) != 0)
+ header->dev_specific |= 0x80; /* WP */
+ }
if (dbd)
scsi_ulto2b(0, header->block_descr_len);
else
@@ -9126,6 +9148,31 @@ ctl_read_write(struct ctl_scsiio *ctsio)
num_blocks = scsi_4btoul(cdb->length);
break;
}
+ case WRITE_ATOMIC_16: {
+ struct scsi_rw_16 *cdb;
+
+ if (lun->be_lun->atomicblock == 0) {
+ ctl_set_invalid_opcode(ctsio);
+ ctl_done((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+ }
+
+ cdb = (struct scsi_rw_16 *)ctsio->cdb;
+ if (cdb->byte2 & SRW12_FUA)
+ flags |= CTL_LLF_FUA;
+ if (cdb->byte2 & SRW12_DPO)
+ flags |= CTL_LLF_DPO;
+ lba = scsi_8btou64(cdb->addr);
+ num_blocks = scsi_4btoul(cdb->length);
+ if (num_blocks > lun->be_lun->atomicblock) {
+ ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
+ /*command*/ 1, /*field*/ 12, /*bit_valid*/ 0,
+ /*bit*/ 0);
+ ctl_done((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
+ }
+ break;
+ }
case WRITE_VERIFY_16: {
struct scsi_write_verify_16 *cdb;
@@ -9912,9 +9959,7 @@ ctl_inquiry_evpd_eid(struct ctl_scsiio *ctsio, int alloc_len)
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- data_len = sizeof(struct scsi_vpd_mode_page_policy) +
- sizeof(struct scsi_vpd_mode_page_policy_descr);
-
+ data_len = sizeof(struct scsi_vpd_extended_inquiry_data);
ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
eid_ptr = (struct scsi_vpd_extended_inquiry_data *)ctsio->kern_data_ptr;
ctsio->kern_sg_entries = 0;
@@ -10301,6 +10346,10 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
bl_ptr->unmap_grain_align);
}
}
+ scsi_ulto4b(lun->be_lun->atomicblock,
+ bl_ptr->max_atomic_transfer_length);
+ scsi_ulto4b(0, bl_ptr->atomic_alignment);
+ scsi_ulto4b(0, bl_ptr->atomic_transfer_length_granularity);
}
scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length);
@@ -10696,13 +10745,13 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
}
if (lun == NULL) {
- /* SBC-3 (no version claimed) */
- scsi_ulto2b(0x04C0, inq_ptr->version4);
+ /* SBC-4 (no version claimed) */
+ scsi_ulto2b(0x0600, inq_ptr->version4);
} else {
switch (lun->be_lun->lun_type) {
case T_DIRECT:
- /* SBC-3 (no version claimed) */
- scsi_ulto2b(0x04C0, inq_ptr->version4);
+ /* SBC-4 (no version claimed) */
+ scsi_ulto2b(0x0600, inq_ptr->version4);
break;
case T_PROCESSOR:
default:
@@ -10820,7 +10869,8 @@ ctl_get_lba_len(union ctl_io *io, uint64_t *lba, uint64_t *len)
break;
}
case READ_16:
- case WRITE_16: {
+ case WRITE_16:
+ case WRITE_ATOMIC_16: {
struct scsi_rw_16 *cdb;
cdb = (struct scsi_rw_16 *)io->scsiio.cdb;
@@ -10834,7 +10884,6 @@ ctl_get_lba_len(union ctl_io *io, uint64_t *lba, uint64_t *len)
cdb = (struct scsi_write_verify_16 *)io->scsiio.cdb;
-
*lba = scsi_8btou64(cdb->addr);
*len = scsi_4btoul(cdb->length);
break;
@@ -11286,6 +11335,24 @@ ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
}
#endif
+ if (entry->pattern & CTL_LUN_PAT_WRITE) {
+ if (lun->flags & CTL_LUN_READONLY) {
+ ctl_set_sense(ctsio, /*current_error*/ 1,
+ /*sense_key*/ SSD_KEY_DATA_PROTECT,
+ /*asc*/ 0x27, /*ascq*/ 0x01, SSD_ELEM_NONE);
+ retval = 1;
+ goto bailout;
+ }
+ if ((lun->mode_pages.control_page[CTL_PAGE_CURRENT]
+ .eca_and_aen & SCP_SWP) != 0) {
+ ctl_set_sense(ctsio, /*current_error*/ 1,
+ /*sense_key*/ SSD_KEY_DATA_PROTECT,
+ /*asc*/ 0x27, /*ascq*/ 0x02, SSD_ELEM_NONE);
+ retval = 1;
+ goto bailout;
+ }
+ }
+
/*
* Check for a reservation conflict. If this command isn't allowed
* even on reserved LUNs, and if this initiator isn't the one who
diff --git a/sys/cam/ctl/ctl_backend.h b/sys/cam/ctl/ctl_backend.h
index c2066c5..d8e78ab 100644
--- a/sys/cam/ctl/ctl_backend.h
+++ b/sys/cam/ctl/ctl_backend.h
@@ -144,6 +144,8 @@ typedef void (*be_lun_config_t)(void *be_lun,
*
* pblockoff is the lowest LBA on the LUN aligned ot physical sector.
*
+ * atomicblock is the number of blocks that can be written atomically.
+ *
* req_lun_id is the requested LUN ID. CTL only pays attention to this
* field if the CTL_LUN_FLAG_ID_REQ flag is set. If the requested LUN ID is
* not available, the LUN addition will fail. If a particular LUN ID isn't
@@ -188,6 +190,7 @@ struct ctl_be_lun {
uint32_t blocksize; /* passed to CTL */
uint16_t pblockexp; /* passed to CTL */
uint16_t pblockoff; /* passed to CTL */
+ uint32_t atomicblock; /* passed to CTL */
uint32_t req_lun_id; /* passed to CTL */
uint32_t lun_id; /* returned from CTL */
uint8_t serial_num[CTL_SN_LEN]; /* passed to CTL */
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index 0ae8ecb..eb16474 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -2003,6 +2003,9 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
if (unmap)
be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_UNMAP;
+ if (be_lun->dispatch == ctl_be_block_dispatch_zvol)
+ be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE /
+ be_lun->blocksize;
be_lun->ctl_be_lun.be_lun = be_lun;
be_lun->ctl_be_lun.blocksize = be_lun->blocksize;
be_lun->ctl_be_lun.pblockexp = be_lun->pblockexp;
diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c
index 6613e8e..5f45035 100644
--- a/sys/cam/ctl/ctl_backend_ramdisk.c
+++ b/sys/cam/ctl/ctl_backend_ramdisk.c
@@ -595,6 +595,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
if (unmap)
be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_UNMAP;
+ be_lun->ctl_be_lun.atomicblock = UINT32_MAX;
be_lun->ctl_be_lun.be_lun = be_lun;
if (params->flags & CTL_LUN_FLAG_ID_REQ) {
diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c
index eb1b0ee..e2323a2 100644
--- a/sys/cam/ctl/ctl_cmd_table.c
+++ b/sys/cam/ctl/ctl_cmd_table.c
@@ -1117,8 +1117,11 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* 9B */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
-/* 9C */
-{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
+/* 9C WRITE ATOMIC (16) */
+{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
+ CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
+ 16, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0, 0, 0xff, 0xff, 0, 0x07}},
/* 9D */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c
index 72f8dd8..7cdd5b7 100644
--- a/sys/cam/ctl/ctl_frontend_cam_sim.c
+++ b/sys/cam/ctl/ctl_frontend_cam_sim.c
@@ -609,14 +609,16 @@ cfcs_action(struct cam_sim *sim, union ccb *ccb)
bcopy(csio->cdb_io.cdb_bytes, io->scsiio.cdb,
io->scsiio.cdb_len);
+ ccb->ccb_h.status |= CAM_SIM_QUEUED;
err = ctl_queue(io);
if (err != CTL_RETVAL_COMPLETE) {
printf("%s: func %d: error %d returned by "
"ctl_queue()!\n", __func__,
ccb->ccb_h.func_code, err);
ctl_free_io(io);
- } else {
- ccb->ccb_h.status |= CAM_SIM_QUEUED;
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ return;
}
break;
}
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index 85a0667..448cc73 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -154,6 +154,8 @@ static uint32_t cfiscsi_lun_map(void *arg, uint32_t lun);
static int cfiscsi_ioctl(struct cdev *dev,
u_long cmd, caddr_t addr, int flag, struct thread *td);
static void cfiscsi_datamove(union ctl_io *io);
+static void cfiscsi_datamove_in(union ctl_io *io);
+static void cfiscsi_datamove_out(union ctl_io *io);
static void cfiscsi_done(union ctl_io *io);
static bool cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request);
static void cfiscsi_pdu_handle_nop_out(struct icl_pdu *request);
@@ -824,7 +826,7 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
return (true);
}
- if (io->scsiio.ext_data_filled == io->scsiio.kern_data_len &&
+ if (io->scsiio.ext_data_filled == cdw->cdw_r2t_end &&
(bhsdo->bhsdo_flags & BHSDO_FLAGS_F) == 0) {
CFISCSI_SESSION_WARN(cs, "got the final packet without "
"the F flag; flags = 0x%x; dropping connection",
@@ -834,7 +836,7 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
return (true);
}
- if (io->scsiio.ext_data_filled != io->scsiio.kern_data_len &&
+ if (io->scsiio.ext_data_filled != cdw->cdw_r2t_end &&
(bhsdo->bhsdo_flags & BHSDO_FLAGS_F) != 0) {
if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
ISCSI_BHS_OPCODE_SCSI_DATA_OUT) {
@@ -842,7 +844,7 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
"transmitted size was %zd bytes instead of %d; "
"dropping connection",
(size_t)io->scsiio.ext_data_filled,
- io->scsiio.kern_data_len);
+ cdw->cdw_r2t_end);
ctl_set_data_phase_error(&io->scsiio);
cfiscsi_session_terminate(cs);
return (true);
@@ -855,7 +857,7 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
}
}
- if (io->scsiio.ext_data_filled == io->scsiio.kern_data_len) {
+ if (io->scsiio.ext_data_filled == cdw->cdw_r2t_end) {
#if 0
CFISCSI_SESSION_DEBUG(cs, "no longer expecting Data-Out with target "
"transfer tag 0x%x", cdw->cdw_target_transfer_tag);
@@ -911,8 +913,13 @@ cfiscsi_pdu_handle_data_out(struct icl_pdu *request)
CFISCSI_SESSION_LOCK(cs);
TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next);
CFISCSI_SESSION_UNLOCK(cs);
+ done = (io->scsiio.ext_data_filled != cdw->cdw_r2t_end ||
+ io->scsiio.ext_data_filled == io->scsiio.kern_data_len);
uma_zfree(cfiscsi_data_wait_zone, cdw);
- io->scsiio.be_move_done(io);
+ if (done)
+ io->scsiio.be_move_done(io);
+ else
+ cfiscsi_datamove_out(io);
}
icl_pdu_free(request);
@@ -1128,7 +1135,6 @@ cfiscsi_maintenance_thread(void *arg)
* that anymore. We might need to revisit that.
*/
callout_drain(&cs->cs_callout);
- icl_conn_shutdown(cs->cs_conn);
icl_conn_close(cs->cs_conn);
/*
@@ -2567,6 +2573,8 @@ cfiscsi_datamove_out(union ctl_io *io)
const struct iscsi_bhs_scsi_command *bhssc;
struct iscsi_bhs_r2t *bhsr2t;
struct cfiscsi_data_wait *cdw;
+ struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
+ uint32_t expected_len, r2t_off, r2t_len;
uint32_t target_transfer_tag;
bool done;
@@ -2585,9 +2593,16 @@ cfiscsi_datamove_out(union ctl_io *io)
PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len;
/*
- * We hadn't received anything during this datamove yet.
+ * Report write underflow as error since CTL and backends don't
+ * really support it, and SCSI does not tell how to do it right.
*/
- io->scsiio.ext_data_filled = 0;
+ expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length);
+ if (io->scsiio.kern_rel_offset + io->scsiio.kern_data_len >
+ expected_len) {
+ io->scsiio.io_hdr.port_status = 43;
+ io->scsiio.be_move_done(io);
+ return;
+ }
target_transfer_tag =
atomic_fetchadd_32(&cs->cs_target_transfer_tag, 1);
@@ -2609,8 +2624,35 @@ cfiscsi_datamove_out(union ctl_io *io)
cdw->cdw_ctl_io = io;
cdw->cdw_target_transfer_tag = target_transfer_tag;
cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
+ cdw->cdw_r2t_end = io->scsiio.kern_data_len;
+
+ /* Set initial data pointer for the CDW respecting ext_data_filled. */
+ if (io->scsiio.kern_sg_entries > 0) {
+ ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
+ } else {
+ ctl_sglist = &ctl_sg_entry;
+ ctl_sglist->addr = io->scsiio.kern_data_ptr;
+ ctl_sglist->len = io->scsiio.kern_data_len;
+ }
+ cdw->cdw_sg_index = 0;
+ cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr;
+ cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len;
+ r2t_off = io->scsiio.ext_data_filled;
+ while (r2t_off > 0) {
+ if (r2t_off >= cdw->cdw_sg_len) {
+ r2t_off -= cdw->cdw_sg_len;
+ cdw->cdw_sg_index++;
+ cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr;
+ cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len;
+ continue;
+ }
+ cdw->cdw_sg_addr += r2t_off;
+ cdw->cdw_sg_len -= r2t_off;
+ r2t_off = 0;
+ }
- if (cs->cs_immediate_data && io->scsiio.kern_rel_offset <
+ if (cs->cs_immediate_data &&
+ io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled <
icl_pdu_data_segment_length(request)) {
done = cfiscsi_handle_data_segment(request, cdw);
if (done) {
@@ -2620,6 +2662,11 @@ cfiscsi_datamove_out(union ctl_io *io)
}
}
+ r2t_off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled;
+ r2t_len = MIN(io->scsiio.kern_data_len - io->scsiio.ext_data_filled,
+ cs->cs_max_burst_length);
+ cdw->cdw_r2t_end = io->scsiio.ext_data_filled + r2t_len;
+
CFISCSI_SESSION_LOCK(cs);
TAILQ_INSERT_TAIL(&cs->cs_waiting_for_data_out, cdw, cdw_next);
CFISCSI_SESSION_UNLOCK(cs);
@@ -2659,16 +2706,13 @@ cfiscsi_datamove_out(union ctl_io *io)
* The ext_data_filled is to account for unsolicited
* (immediate) data that might have already arrived.
*/
- bhsr2t->bhsr2t_buffer_offset =
- htonl(io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled);
+ bhsr2t->bhsr2t_buffer_offset = htonl(r2t_off);
/*
* This is the total length (sum of S/G lengths) this call
- * to cfiscsi_datamove() is supposed to handle.
- *
- * XXX: Limit it to MaxBurstLength.
+ * to cfiscsi_datamove() is supposed to handle, limited by
+ * MaxBurstLength.
*/
- bhsr2t->bhsr2t_desired_data_transfer_length =
- htonl(io->scsiio.kern_data_len - io->scsiio.ext_data_filled);
+ bhsr2t->bhsr2t_desired_data_transfer_length = htonl(r2t_len);
cfiscsi_pdu_queue(response);
}
@@ -2678,8 +2722,11 @@ cfiscsi_datamove(union ctl_io *io)
if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN)
cfiscsi_datamove_in(io);
- else
+ else {
+ /* We hadn't received anything during this datamove yet. */
+ io->scsiio.ext_data_filled = 0;
cfiscsi_datamove_out(io);
+ }
}
static void
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.h b/sys/cam/ctl/ctl_frontend_iscsi.h
index 0ac0e98..af4de87 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.h
+++ b/sys/cam/ctl/ctl_frontend_iscsi.h
@@ -56,6 +56,7 @@ struct cfiscsi_data_wait {
int cdw_sg_index;
char *cdw_sg_addr;
size_t cdw_sg_len;
+ uint32_t cdw_r2t_end;
};
#define CFISCSI_SESSION_STATE_INVALID 0
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index 43ee394..4f22250 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -198,7 +198,8 @@ typedef enum {
CTL_LUN_OFFLINE = 0x080,
CTL_LUN_PR_RESERVED = 0x100,
CTL_LUN_PRIMARY_SC = 0x200,
- CTL_LUN_SENSE_DESC = 0x400
+ CTL_LUN_SENSE_DESC = 0x400,
+ CTL_LUN_READONLY = 0x800
} ctl_lun_flags;
typedef enum {
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 3529683..9347ed1 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -1115,6 +1115,7 @@ ctlfe_adjust_cdb(struct ccb_accept_tio *atio, uint32_t offset)
}
case READ_16:
case WRITE_16:
+ case WRITE_ATOMIC_16:
{
struct scsi_rw_16 *cdb = (struct scsi_rw_16 *)cmdbyt;
lba = scsi_8btou64(cdb->addr);
diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h
index 8eb58fe..fbb131e 100644
--- a/sys/cam/scsi/scsi_all.h
+++ b/sys/cam/scsi/scsi_all.h
@@ -1720,6 +1720,7 @@ struct ata_pass_16 {
#define VERIFY_16 0x8F
#define SYNCHRONIZE_CACHE_16 0x91
#define WRITE_SAME_16 0x93
+#define WRITE_ATOMIC_16 0x9C
#define SERVICE_ACTION_IN 0x9E
#define REPORT_LUNS 0xA0
#define ATA_PASS_12 0xA1
@@ -2437,8 +2438,7 @@ struct scsi_vpd_logical_block_prov
};
/*
- * Block Limits VDP Page based on
- * T10/1799-D Revision 31
+ * Block Limits VDP Page based on SBC-4 Revision 2
*/
struct scsi_vpd_block_limits
{
@@ -2459,7 +2459,10 @@ struct scsi_vpd_block_limits
u_int8_t opt_unmap_grain[4];
u_int8_t unmap_grain_align[4];
u_int8_t max_write_same_length[8];
- u_int8_t reserved2[20];
+ u_int8_t max_atomic_transfer_length[4];
+ u_int8_t atomic_alignment[4];
+ u_int8_t atomic_transfer_length_granularity[4];
+ u_int8_t reserved2[8];
};
struct scsi_read_capacity
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_kmem.c b/sys/cddl/compat/opensolaris/kern/opensolaris_kmem.c
index fd8798d..aa26618 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris_kmem.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_kmem.c
@@ -126,42 +126,6 @@ kmem_size_init(void *unused __unused)
}
SYSINIT(kmem_size_init, SI_SUB_KMEM, SI_ORDER_ANY, kmem_size_init, NULL);
-/*
- * The return values from kmem_free_* are only valid once the pagedaemon
- * has been initialised, before then they return 0.
- *
- * To ensure the returns are valid the caller can use a SYSINIT with
- * subsystem set to SI_SUB_KTHREAD_PAGE and an order of at least
- * SI_ORDER_SECOND.
- */
-u_int
-kmem_free_target(void)
-{
-
- return (vm_cnt.v_free_target);
-}
-
-u_int
-kmem_free_min(void)
-{
-
- return (vm_cnt.v_free_min);
-}
-
-u_int
-kmem_free_count(void)
-{
-
- return (vm_cnt.v_free_count + vm_cnt.v_cache_count);
-}
-
-u_int
-kmem_page_count(void)
-{
-
- return (vm_cnt.v_page_count);
-}
-
uint64_t
kmem_size(void)
{
@@ -169,13 +133,6 @@ kmem_size(void)
return (kmem_size_val);
}
-uint64_t
-kmem_used(void)
-{
-
- return (vmem_size(kmem_arena, VMEM_ALLOC));
-}
-
static int
kmem_std_constructor(void *mem, int size __unused, void *private, int flags)
{
diff --git a/sys/cddl/compat/opensolaris/sys/assfail.h b/sys/cddl/compat/opensolaris/sys/assfail.h
index e6ff258..553da69 100644
--- a/sys/cddl/compat/opensolaris/sys/assfail.h
+++ b/sys/cddl/compat/opensolaris/sys/assfail.h
@@ -46,20 +46,24 @@ void assfail3(const char *, uintmax_t, const char *, uintmax_t, const char *,
#else /* !defined(_KERNEL) */
#ifndef HAVE_ASSFAIL
+extern int aok;
+
static __inline int
__assfail(const char *expr, const char *file, int line)
{
(void)fprintf(stderr, "Assertion failed: (%s), file %s, line %d.\n",
expr, file, line);
- abort();
- /* NOTREACHED */
+ if (!aok)
+ abort();
return (0);
}
#define assfail __assfail
#endif
#ifndef HAVE_ASSFAIL3
+extern int aok;
+
static __inline void
__assfail3(const char *expr, uintmax_t lv, const char *op, uintmax_t rv,
const char *file, int line) {
@@ -67,8 +71,8 @@ __assfail3(const char *expr, uintmax_t lv, const char *op, uintmax_t rv,
(void)fprintf(stderr,
"Assertion failed: %s (0x%jx %s 0x%jx), file %s, line %d.\n",
expr, lv, op, rv, file, line);
- abort();
- /* NOTREACHED */
+ if (!aok)
+ abort();
}
#define assfail3 __assfail3
#endif
diff --git a/sys/cddl/compat/opensolaris/sys/kmem.h b/sys/cddl/compat/opensolaris/sys/kmem.h
index 1879ba4..5616067 100644
--- a/sys/cddl/compat/opensolaris/sys/kmem.h
+++ b/sys/cddl/compat/opensolaris/sys/kmem.h
@@ -66,17 +66,6 @@ typedef struct kmem_cache {
void *zfs_kmem_alloc(size_t size, int kmflags);
void zfs_kmem_free(void *buf, size_t size);
uint64_t kmem_size(void);
-uint64_t kmem_used(void);
-u_int kmem_page_count(void);
-
-/*
- * The return values from kmem_free_* are only valid once the pagedaemon
- * has been initialised, before then they return 0.
- */
-u_int kmem_free_count(void);
-u_int kmem_free_target(void);
-u_int kmem_free_min(void);
-
kmem_cache_t *kmem_cache_create(char *name, size_t bufsize, size_t align,
int (*constructor)(void *, void *, int), void (*destructor)(void *, void *),
void (*reclaim)(void *) __unused, void *private, vmem_t *vmp, int cflags);
@@ -88,6 +77,9 @@ void kmem_reap(void);
int kmem_debugging(void);
void *calloc(size_t n, size_t s);
+#define freemem (vm_cnt.v_free_count + vm_cnt.v_cache_count)
+#define minfree vm_cnt.v_free_min
+#define heap_arena kmem_arena
#define kmem_alloc(size, kmflags) zfs_kmem_alloc((size), (kmflags))
#define kmem_zalloc(size, kmflags) zfs_kmem_alloc((size), (kmflags) | M_ZERO)
#define kmem_free(buf, size) zfs_kmem_free((buf), (size))
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
index fb70c9b..60d2ff9 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
@@ -138,6 +138,7 @@
#include <sys/sdt.h>
#include <vm/vm_pageout.h>
+#include <machine/vmparam.h>
#ifdef illumos
#ifndef _KERNEL
@@ -201,7 +202,7 @@ int zfs_arc_shrink_shift = 0;
int zfs_arc_p_min_shift = 0;
int zfs_disable_dup_eviction = 0;
uint64_t zfs_arc_average_blocksize = 8 * 1024; /* 8KB */
-u_int zfs_arc_free_target = (1 << 19); /* default before pagedaemon init only */
+u_int zfs_arc_free_target = 0;
static int sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS);
@@ -210,11 +211,10 @@ static void
arc_free_target_init(void *unused __unused)
{
- zfs_arc_free_target = kmem_free_target();
+ zfs_arc_free_target = vm_pageout_wakeup_thresh;
}
SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY,
arc_free_target_init, NULL);
-#endif
TUNABLE_QUAD("vfs.zfs.arc_meta_limit", &zfs_arc_meta_limit);
SYSCTL_DECL(_vfs_zfs);
@@ -245,15 +245,16 @@ sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS)
if (err != 0 || req->newptr == NULL)
return (err);
- if (val < kmem_free_min())
+ if (val < minfree)
return (EINVAL);
- if (val > kmem_page_count())
+ if (val > vm_cnt.v_page_count)
return (EINVAL);
zfs_arc_free_target = val;
return (0);
}
+#endif
/*
* Note that buffers can be in one of 6 states:
@@ -2445,8 +2446,8 @@ arc_shrink(void)
if (arc_c > arc_c_min) {
uint64_t to_free;
- DTRACE_PROBE2(arc__shrink, uint64_t, arc_c, uint64_t,
- arc_c_min);
+ DTRACE_PROBE4(arc__shrink, uint64_t, arc_c, uint64_t,
+ arc_c_min, uint64_t, arc_p, uint64_t, to_free);
#ifdef _KERNEL
to_free = arc_c >> arc_shrink_shift;
#else
@@ -2462,6 +2463,10 @@ arc_shrink(void)
arc_c = MAX(arc_size, arc_c_min);
if (arc_p > arc_c)
arc_p = (arc_c >> 1);
+
+ DTRACE_PROBE2(arc__shrunk, uint64_t, arc_c, uint64_t,
+ arc_p);
+
ASSERT(arc_c >= arc_c_min);
ASSERT((int64_t)arc_p >= 0);
}
@@ -2486,18 +2491,13 @@ arc_reclaim_needed(void)
return (1);
}
- if (kmem_free_count() < zfs_arc_free_target) {
- DTRACE_PROBE2(arc__reclaim_freetarget, uint64_t,
- kmem_free_count(), uint64_t, zfs_arc_free_target);
- return (1);
- }
-
/*
* Cooperate with pagedaemon when it's time for it to scan
* and reclaim some pages.
*/
- if (vm_paging_needed()) {
- DTRACE_PROBE(arc__reclaim_paging);
+ if (freemem < zfs_arc_free_target) {
+ DTRACE_PROBE2(arc__reclaim_freemem, uint64_t,
+ freemem, uint64_t, zfs_arc_free_target);
return (1);
}
@@ -2527,7 +2527,18 @@ arc_reclaim_needed(void)
if (availrmem < swapfs_minfree + swapfs_reserve + extra)
return (1);
-#if defined(__i386)
+ /*
+ * Check that we have enough availrmem that memory locking (e.g., via
+ * mlock(3C) or memcntl(2)) can still succeed. (pages_pp_maximum
+ * stores the number of pages that cannot be locked; when availrmem
+ * drops below pages_pp_maximum, page locking mechanisms such as
+ * page_pp_lock() will fail.)
+ */
+ if (availrmem <= pages_pp_maximum)
+ return (1);
+
+#endif /* sun */
+#if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC)
/*
* If we're on an i386 platform, it's possible that we'll exhaust the
* kernel heap space before we ever run out of available physical
@@ -2539,25 +2550,33 @@ arc_reclaim_needed(void)
* heap is allocated. (Or, in the calculation, if less than 1/4th is
* free)
*/
- if (btop(vmem_size(heap_arena, VMEM_FREE)) <
- (btop(vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC)) >> 2))
- return (1);
-#endif
-#else /* sun */
-#ifdef __i386__
- /* i386 has KVA limits that the raw page counts above don't consider */
- if (kmem_used() > (kmem_size() * 3) / 4) {
+ if (vmem_size(heap_arena, VMEM_FREE) <
+ (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC) >> 2)) {
DTRACE_PROBE2(arc__reclaim_used, uint64_t,
- kmem_used(), uint64_t, (kmem_size() * 3) / 4);
+ vmem_size(heap_arena, VMEM_FREE), uint64_t,
+ (vmem_size(heap_arena, VMEM_FREE | VMEM_ALLOC)) >> 2);
return (1);
}
#endif
+#ifdef sun
+ /*
+ * If zio data pages are being allocated out of a separate heap segment,
+ * then enforce that the size of available vmem for this arena remains
+ * above about 1/16th free.
+ *
+ * Note: The 1/16th arena free requirement was put in place
+ * to aggressively evict memory from the arc in order to avoid
+ * memory fragmentation issues.
+ */
+ if (zio_arena != NULL &&
+ vmem_size(zio_arena, VMEM_FREE) <
+ (vmem_size(zio_arena, VMEM_ALLOC) >> 4))
+ return (1);
#endif /* sun */
-
-#else
+#else /* _KERNEL */
if (spa_get_random(100) == 0)
return (1);
-#endif
+#endif /* _KERNEL */
DTRACE_PROBE(arc__reclaim_no);
return (0);
@@ -2565,14 +2584,16 @@ arc_reclaim_needed(void)
extern kmem_cache_t *zio_buf_cache[];
extern kmem_cache_t *zio_data_buf_cache[];
+extern kmem_cache_t *range_seg_cache;
-static void
+static void __noinline
arc_kmem_reap_now(arc_reclaim_strategy_t strat)
{
size_t i;
kmem_cache_t *prev_cache = NULL;
kmem_cache_t *prev_data_cache = NULL;
+ DTRACE_PROBE(arc__kmem_reap_start);
#ifdef _KERNEL
if (arc_meta_used >= arc_meta_limit) {
/*
@@ -2608,6 +2629,17 @@ arc_kmem_reap_now(arc_reclaim_strategy_t strat)
}
kmem_cache_reap_now(buf_cache);
kmem_cache_reap_now(hdr_cache);
+ kmem_cache_reap_now(range_seg_cache);
+
+#ifdef sun
+ /*
+ * Ask the vmem arena to reclaim unused memory from its
+ * quantum caches.
+ */
+ if (zio_arena != NULL && strat == ARC_RECLAIM_AGGR)
+ vmem_qcache_reap(zio_arena);
+#endif
+ DTRACE_PROBE(arc__kmem_reap_end);
}
static void
@@ -2625,6 +2657,7 @@ arc_reclaim_thread(void *dummy __unused)
if (arc_no_grow) {
if (last_reclaim == ARC_RECLAIM_CONS) {
+ DTRACE_PROBE(arc__reclaim_aggr_no_grow);
last_reclaim = ARC_RECLAIM_AGGR;
} else {
last_reclaim = ARC_RECLAIM_CONS;
@@ -2632,6 +2665,7 @@ arc_reclaim_thread(void *dummy __unused)
} else {
arc_no_grow = TRUE;
last_reclaim = ARC_RECLAIM_AGGR;
+ DTRACE_PROBE(arc__reclaim_aggr);
membar_producer();
}
@@ -2736,6 +2770,7 @@ arc_adapt(int bytes, arc_state_t *state)
* cache size, increment the target cache size
*/
if (arc_size > arc_c - (2ULL << SPA_MAXBLOCKSHIFT)) {
+ DTRACE_PROBE1(arc__inc_adapt, int, bytes);
atomic_add_64(&arc_c, (int64_t)bytes);
if (arc_c > arc_c_max)
arc_c = arc_c_max;
@@ -2757,20 +2792,6 @@ arc_evict_needed(arc_buf_contents_t type)
if (type == ARC_BUFC_METADATA && arc_meta_used >= arc_meta_limit)
return (1);
-#ifdef sun
-#ifdef _KERNEL
- /*
- * If zio data pages are being allocated out of a separate heap segment,
- * then enforce that the size of available vmem for this area remains
- * above about 1/32nd free.
- */
- if (type == ARC_BUFC_DATA && zio_arena != NULL &&
- vmem_size(zio_arena, VMEM_FREE) <
- (vmem_size(zio_arena, VMEM_ALLOC) >> 5))
- return (1);
-#endif
-#endif /* sun */
-
if (arc_reclaim_needed())
return (1);
@@ -3929,20 +3950,16 @@ static int
arc_memory_throttle(uint64_t reserve, uint64_t txg)
{
#ifdef _KERNEL
- uint64_t available_memory =
- ptoa((uintmax_t)vm_cnt.v_free_count + vm_cnt.v_cache_count);
+ uint64_t available_memory = ptob(freemem);
static uint64_t page_load = 0;
static uint64_t last_txg = 0;
-#ifdef sun
-#if defined(__i386)
+#if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC)
available_memory =
- MIN(available_memory, vmem_size(heap_arena, VMEM_FREE));
+ MIN(available_memory, ptob(vmem_size(heap_arena, VMEM_FREE)));
#endif
-#endif /* sun */
- if (vm_cnt.v_free_count + vm_cnt.v_cache_count >
- (uint64_t)physmem * arc_lotsfree_percent / 100)
+ if (freemem > (uint64_t)physmem * arc_lotsfree_percent / 100)
return (0);
if (txg > last_txg) {
@@ -3955,7 +3972,7 @@ arc_memory_throttle(uint64_t reserve, uint64_t txg)
* continue to let page writes occur as quickly as possible.
*/
if (curproc == pageproc) {
- if (page_load > available_memory / 4)
+ if (page_load > MAX(ptob(minfree), available_memory) / 4)
return (SET_ERROR(ERESTART));
/* Note: reserve is inflated, so we deflate */
page_load += reserve / 8;
@@ -3983,8 +4000,10 @@ arc_tempreserve_space(uint64_t reserve, uint64_t txg)
int error;
uint64_t anon_size;
- if (reserve > arc_c/4 && !arc_no_grow)
+ if (reserve > arc_c/4 && !arc_no_grow) {
arc_c = MIN(arc_c_max, reserve * 4);
+ DTRACE_PROBE1(arc__set_reserve, uint64_t, arc_c);
+ }
if (reserve > arc_c)
return (SET_ERROR(ENOMEM));
@@ -4038,6 +4057,7 @@ arc_lowmem(void *arg __unused, int howto __unused)
mutex_enter(&arc_lowmem_lock);
mutex_enter(&arc_reclaim_thr_lock);
needfree = 1;
+ DTRACE_PROBE(arc__needfree);
cv_signal(&arc_reclaim_thr_cv);
/*
@@ -5027,7 +5047,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
if (ab == NULL)
ARCSTAT_BUMP(arcstat_l2_write_buffer_list_null_iter);
- headroom = target_sz * l2arc_headroom;
+ headroom = target_sz * l2arc_headroom * 2 / ARC_BUFC_NUMLISTS;
if (do_headroom_boost)
headroom = (headroom * l2arc_headroom_boost) / 100;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
index 9102322c..c9ea6c0 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
@@ -671,6 +671,8 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
db->db_state == DB_FILL) {
ASSERT(db->db_state == DB_READ ||
(flags & DB_RF_HAVESTRUCT) == 0);
+ DTRACE_PROBE2(blocked__read, dmu_buf_impl_t *,
+ db, zio_t *, zio);
cv_wait(&db->db_changed, &db->db_mtx);
}
if (db->db_state == DB_UNCACHED)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
index 7f7f3dc..c86d3a7 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
@@ -1021,8 +1021,8 @@ xuio_stat_wbuf_nocopy()
}
#ifdef _KERNEL
-int
-dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
+static int
+dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size)
{
dmu_buf_t **dbp;
int numbufs, i, err;
@@ -1032,8 +1032,8 @@ dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
* NB: we could do this block-at-a-time, but it's nice
* to be reading in parallel.
*/
- err = dmu_buf_hold_array(os, object, uio->uio_loffset, size, TRUE, FTAG,
- &numbufs, &dbp);
+ err = dmu_buf_hold_array_by_dnode(dn, uio->uio_loffset, size,
+ TRUE, FTAG, &numbufs, &dbp, 0);
if (err)
return (err);
@@ -1080,6 +1080,58 @@ dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
return (err);
}
+/*
+ * Read 'size' bytes into the uio buffer.
+ * From object zdb->db_object.
+ * Starting at offset uio->uio_loffset.
+ *
+ * If the caller already has a dbuf in the target object
+ * (e.g. its bonus buffer), this routine is faster than dmu_read_uio(),
+ * because we don't have to find the dnode_t for the object.
+ */
+int
+dmu_read_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size)
+{
+ dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
+ dnode_t *dn;
+ int err;
+
+ if (size == 0)
+ return (0);
+
+ DB_DNODE_ENTER(db);
+ dn = DB_DNODE(db);
+ err = dmu_read_uio_dnode(dn, uio, size);
+ DB_DNODE_EXIT(db);
+
+ return (err);
+}
+
+/*
+ * Read 'size' bytes into the uio buffer.
+ * From the specified object
+ * Starting at offset uio->uio_loffset.
+ */
+int
+dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
+{
+ dnode_t *dn;
+ int err;
+
+ if (size == 0)
+ return (0);
+
+ err = dnode_hold(os, object, FTAG, &dn);
+ if (err)
+ return (err);
+
+ err = dmu_read_uio_dnode(dn, uio, size);
+
+ dnode_rele(dn, FTAG);
+
+ return (err);
+}
+
static int
dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
{
@@ -1132,6 +1184,15 @@ dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
return (err);
}
+/*
+ * Write 'size' bytes from the uio buffer.
+ * To object zdb->db_object.
+ * Starting at offset uio->uio_loffset.
+ *
+ * If the caller already has a dbuf in the target object
+ * (e.g. its bonus buffer), this routine is faster than dmu_write_uio(),
+ * because we don't have to find the dnode_t for the object.
+ */
int
dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
dmu_tx_t *tx)
@@ -1151,6 +1212,11 @@ dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
return (err);
}
+/*
+ * Write 'size' bytes from the uio buffer.
+ * To the specified object.
+ * Starting at offset uio->uio_loffset.
+ */
int
dmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size,
dmu_tx_t *tx)
@@ -1332,7 +1398,14 @@ dmu_assign_arcbuf(dmu_buf_t *handle, uint64_t offset, arc_buf_t *buf,
rw_exit(&dn->dn_struct_rwlock);
DB_DNODE_EXIT(dbuf);
- if (offset == db->db.db_offset && blksz == db->db.db_size) {
+ /*
+ * We can only assign if the offset is aligned, the arc buf is the
+ * same size as the dbuf, and the dbuf is not metadata. It
+ * can't be metadata because the loaned arc buf comes from the
+ * user-data kmem arena.
+ */
+ if (offset == db->db.db_offset && blksz == db->db.db_size &&
+ DBUF_GET_BUFC_TYPE(db) == ARC_BUFC_DATA) {
dbuf_assign_arcbuf(db, buf, tx);
dbuf_rele(db, FTAG);
} else {
@@ -1845,6 +1918,7 @@ dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi)
doi->doi_indirection = dn->dn_nlevels;
doi->doi_checksum = dn->dn_checksum;
doi->doi_compress = dn->dn_compress;
+ doi->doi_nblkptr = dn->dn_nblkptr;
doi->doi_physical_blocks_512 = (DN_USED_BYTES(dnp) + 256) >> 9;
doi->doi_max_offset = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
doi->doi_fill_count = 0;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
index 5b512ad..808864a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
@@ -20,7 +20,8 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+ * Copyright 2014 HybridCluster. All rights reserved.
*/
#include <sys/dmu.h>
@@ -107,11 +108,9 @@ dmu_object_claim(objset_t *os, uint64_t object, dmu_object_type_t ot,
int
dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
- int blocksize, dmu_object_type_t bonustype, int bonuslen)
+ int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
{
dnode_t *dn;
- dmu_tx_t *tx;
- int nblkptr;
int err;
if (object == DMU_META_DNODE_OBJECT)
@@ -122,44 +121,9 @@ dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
if (err)
return (err);
- if (dn->dn_type == ot && dn->dn_datablksz == blocksize &&
- dn->dn_bonustype == bonustype && dn->dn_bonuslen == bonuslen) {
- /* nothing is changing, this is a noop */
- dnode_rele(dn, FTAG);
- return (0);
- }
-
- if (bonustype == DMU_OT_SA) {
- nblkptr = 1;
- } else {
- nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
- }
-
- /*
- * If we are losing blkptrs or changing the block size this must
- * be a new file instance. We must clear out the previous file
- * contents before we can change this type of metadata in the dnode.
- */
- if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize) {
- err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
- if (err)
- goto out;
- }
-
- tx = dmu_tx_create(os);
- dmu_tx_hold_bonus(tx, object);
- err = dmu_tx_assign(tx, TXG_WAIT);
- if (err) {
- dmu_tx_abort(tx);
- goto out;
- }
-
dnode_reallocate(dn, ot, blocksize, bonustype, bonuslen, tx);
- dmu_tx_commit(tx);
-out:
dnode_rele(dn, FTAG);
-
return (err);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
index 7c5b5f3..1a0cab5 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
@@ -24,6 +24,7 @@
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>. All rights reserved.
+ * Copyright 2014 HybridCluster. All rights reserved.
*/
#include <sys/dmu.h>
@@ -1273,18 +1274,20 @@ restore_bytes(struct restorearg *ra, void *buf, int len, off_t off, ssize_t *res
}
static void *
-restore_read(struct restorearg *ra, int len)
+restore_read(struct restorearg *ra, int len, char *buf)
{
- void *rv;
int done = 0;
+ if (buf == NULL)
+ buf = ra->buf;
+
/* some things will require 8-byte alignment, so everything must */
ASSERT0(len % 8);
while (done < len) {
ssize_t resid;
- ra->err = restore_bytes(ra, (caddr_t)ra->buf + done,
+ ra->err = restore_bytes(ra, buf + done,
len - done, ra->voff, &resid);
if (resid == len - done)
@@ -1296,12 +1299,11 @@ restore_read(struct restorearg *ra, int len)
}
ASSERT3U(done, ==, len);
- rv = ra->buf;
if (ra->byteswap)
- fletcher_4_incremental_byteswap(rv, len, &ra->cksum);
+ fletcher_4_incremental_byteswap(buf, len, &ra->cksum);
else
- fletcher_4_incremental_native(rv, len, &ra->cksum);
- return (rv);
+ fletcher_4_incremental_native(buf, len, &ra->cksum);
+ return (buf);
}
static void
@@ -1391,12 +1393,25 @@ backup_byteswap(dmu_replay_record_t *drr)
#undef DO32
}
+static inline uint8_t
+deduce_nblkptr(dmu_object_type_t bonus_type, uint64_t bonus_size)
+{
+ if (bonus_type == DMU_OT_SA) {
+ return (1);
+ } else {
+ return (1 +
+ ((DN_MAX_BONUSLEN - bonus_size) >> SPA_BLKPTRSHIFT));
+ }
+}
+
static int
restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
{
- int err;
+ dmu_object_info_t doi;
dmu_tx_t *tx;
void *data = NULL;
+ uint64_t object;
+ int err;
if (drro->drr_type == DMU_OT_NONE ||
!DMU_OT_IS_VALID(drro->drr_type) ||
@@ -1410,48 +1425,65 @@ restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
return (SET_ERROR(EINVAL));
}
- err = dmu_object_info(os, drro->drr_object, NULL);
+ err = dmu_object_info(os, drro->drr_object, &doi);
if (err != 0 && err != ENOENT)
return (SET_ERROR(EINVAL));
+ object = err == 0 ? drro->drr_object : DMU_NEW_OBJECT;
if (drro->drr_bonuslen) {
- data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8));
+ data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8), NULL);
if (ra->err != 0)
return (ra->err);
}
- if (err == ENOENT) {
- /* currently free, want to be allocated */
- tx = dmu_tx_create(os);
- dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
- err = dmu_tx_assign(tx, TXG_WAIT);
- if (err != 0) {
- dmu_tx_abort(tx);
- return (err);
+ /*
+ * If we are losing blkptrs or changing the block size this must
+ * be a new file instance. We must clear out the previous file
+ * contents before we can change this type of metadata in the dnode.
+ */
+ if (err == 0) {
+ int nblkptr;
+
+ nblkptr = deduce_nblkptr(drro->drr_bonustype,
+ drro->drr_bonuslen);
+
+ if (drro->drr_blksz != doi.doi_data_block_size ||
+ nblkptr < doi.doi_nblkptr) {
+ err = dmu_free_long_range(os, drro->drr_object,
+ 0, DMU_OBJECT_END);
+ if (err != 0)
+ return (SET_ERROR(EINVAL));
}
+ }
+
+ tx = dmu_tx_create(os);
+ dmu_tx_hold_bonus(tx, object);
+ err = dmu_tx_assign(tx, TXG_WAIT);
+ if (err != 0) {
+ dmu_tx_abort(tx);
+ return (err);
+ }
+
+ if (object == DMU_NEW_OBJECT) {
+ /* currently free, want to be allocated */
err = dmu_object_claim(os, drro->drr_object,
drro->drr_type, drro->drr_blksz,
drro->drr_bonustype, drro->drr_bonuslen, tx);
- dmu_tx_commit(tx);
- } else {
- /* currently allocated, want to be allocated */
+ } else if (drro->drr_type != doi.doi_type ||
+ drro->drr_blksz != doi.doi_data_block_size ||
+ drro->drr_bonustype != doi.doi_bonus_type ||
+ drro->drr_bonuslen != doi.doi_bonus_size) {
+ /* currently allocated, but with different properties */
err = dmu_object_reclaim(os, drro->drr_object,
drro->drr_type, drro->drr_blksz,
- drro->drr_bonustype, drro->drr_bonuslen);
+ drro->drr_bonustype, drro->drr_bonuslen, tx);
}
if (err != 0) {
+ dmu_tx_commit(tx);
return (SET_ERROR(EINVAL));
}
- tx = dmu_tx_create(os);
- dmu_tx_hold_bonus(tx, drro->drr_object);
- err = dmu_tx_assign(tx, TXG_WAIT);
- if (err != 0) {
- dmu_tx_abort(tx);
- return (err);
- }
-
dmu_object_set_checksum(os, drro->drr_object, drro->drr_checksumtype,
tx);
dmu_object_set_compress(os, drro->drr_object, drro->drr_compress, tx);
@@ -1513,19 +1545,30 @@ restore_write(struct restorearg *ra, objset_t *os,
!DMU_OT_IS_VALID(drrw->drr_type))
return (SET_ERROR(EINVAL));
- data = restore_read(ra, drrw->drr_length);
- if (data == NULL)
- return (ra->err);
-
if (dmu_object_info(os, drrw->drr_object, NULL) != 0)
return (SET_ERROR(EINVAL));
+ dmu_buf_t *bonus;
+ if (dmu_bonus_hold(os, drrw->drr_object, FTAG, &bonus) != 0)
+ return (SET_ERROR(EINVAL));
+
+ arc_buf_t *abuf = dmu_request_arcbuf(bonus, drrw->drr_length);
+
+ data = restore_read(ra, drrw->drr_length, abuf->b_data);
+ if (data == NULL) {
+ dmu_return_arcbuf(abuf);
+ dmu_buf_rele(bonus, FTAG);
+ return (ra->err);
+ }
+
tx = dmu_tx_create(os);
dmu_tx_hold_write(tx, drrw->drr_object,
drrw->drr_offset, drrw->drr_length);
err = dmu_tx_assign(tx, TXG_WAIT);
if (err != 0) {
+ dmu_return_arcbuf(abuf);
+ dmu_buf_rele(bonus, FTAG);
dmu_tx_abort(tx);
return (err);
}
@@ -1534,9 +1577,9 @@ restore_write(struct restorearg *ra, objset_t *os,
DMU_OT_BYTESWAP(drrw->drr_type);
dmu_ot_byteswap[byteswap].ob_func(data, drrw->drr_length);
}
- dmu_write(os, drrw->drr_object,
- drrw->drr_offset, drrw->drr_length, data, tx);
+ dmu_assign_arcbuf(bonus, drrw->drr_offset, abuf, tx);
dmu_tx_commit(tx);
+ dmu_buf_rele(bonus, FTAG);
return (0);
}
@@ -1618,7 +1661,7 @@ restore_write_embedded(struct restorearg *ra, objset_t *os,
if (drrwnp->drr_compression >= ZIO_COMPRESS_FUNCTIONS)
return (EINVAL);
- data = restore_read(ra, P2ROUNDUP(drrwnp->drr_psize, 8));
+ data = restore_read(ra, P2ROUNDUP(drrwnp->drr_psize, 8), NULL);
if (data == NULL)
return (ra->err);
@@ -1653,7 +1696,7 @@ restore_spill(struct restorearg *ra, objset_t *os, struct drr_spill *drrs)
drrs->drr_length > SPA_MAXBLOCKSIZE)
return (SET_ERROR(EINVAL));
- data = restore_read(ra, drrs->drr_length);
+ data = restore_read(ra, drrs->drr_length, NULL);
if (data == NULL)
return (ra->err);
@@ -1795,7 +1838,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, struct file *fp, offset_t *voffp,
*/
pcksum = ra.cksum;
while (ra.err == 0 &&
- NULL != (drr = restore_read(&ra, sizeof (*drr)))) {
+ NULL != (drr = restore_read(&ra, sizeof (*drr), NULL))) {
if (issig(JUSTLOOKING) && issig(FORREAL)) {
ra.err = SET_ERROR(EINTR);
goto out;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
index d013206..a3efe92 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Portions Copyright (c) 2011 Martin Matuska <mm@FreeBSD.org>
- * Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 RackTop Systems.
*/
@@ -699,7 +699,13 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
dsphys->ds_uncompressed_bytes =
origin->ds_phys->ds_uncompressed_bytes;
dsphys->ds_bp = origin->ds_phys->ds_bp;
- dsphys->ds_flags |= origin->ds_phys->ds_flags;
+
+ /*
+ * Inherit flags that describe the dataset's contents
+ * (INCONSISTENT) or properties (Case Insensitive).
+ */
+ dsphys->ds_flags |= origin->ds_phys->ds_flags &
+ (DS_FLAG_INCONSISTENT | DS_FLAG_CI_DATASET);
dmu_buf_will_dirty(origin->ds_dbuf, tx);
origin->ds_phys->ds_num_children++;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
index 03dc702..bcf04c1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
@@ -375,13 +375,12 @@ dsl_scan_cancel(dsl_pool_t *dp)
dsl_scan_cancel_sync, NULL, 3, ZFS_SPACE_CHECK_RESERVED));
}
-static void dsl_scan_visitbp(blkptr_t *bp,
- const zbookmark_phys_t *zb, dnode_phys_t *dnp, arc_buf_t *pbuf,
- dsl_dataset_t *ds, dsl_scan_t *scn, dmu_objset_type_t ostype,
- dmu_tx_t *tx);
+static void dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
+ dnode_phys_t *dnp, dsl_dataset_t *ds, dsl_scan_t *scn,
+ dmu_objset_type_t ostype, dmu_tx_t *tx);
static void dsl_scan_visitdnode(dsl_scan_t *, dsl_dataset_t *ds,
dmu_objset_type_t ostype,
- dnode_phys_t *dnp, arc_buf_t *buf, uint64_t object, dmu_tx_t *tx);
+ dnode_phys_t *dnp, uint64_t object, dmu_tx_t *tx);
void
dsl_free(dsl_pool_t *dp, uint64_t txg, const blkptr_t *bp)
@@ -615,7 +614,7 @@ dsl_scan_check_resume(dsl_scan_t *scn, const dnode_phys_t *dnp,
static int
dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
dnode_phys_t *dnp, const blkptr_t *bp,
- const zbookmark_phys_t *zb, dmu_tx_t *tx, arc_buf_t **bufp)
+ const zbookmark_phys_t *zb, dmu_tx_t *tx)
{
dsl_pool_t *dp = scn->scn_dp;
int zio_flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SCAN_THREAD;
@@ -626,76 +625,72 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
int i;
blkptr_t *cbp;
int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
+ arc_buf_t *buf;
- err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
+ err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, &buf,
ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
if (err) {
scn->scn_phys.scn_errors++;
return (err);
}
- for (i = 0, cbp = (*bufp)->b_data; i < epb; i++, cbp++) {
- dsl_scan_prefetch(scn, *bufp, cbp, zb->zb_objset,
+ for (i = 0, cbp = buf->b_data; i < epb; i++, cbp++) {
+ dsl_scan_prefetch(scn, buf, cbp, zb->zb_objset,
zb->zb_object, zb->zb_blkid * epb + i);
}
- for (i = 0, cbp = (*bufp)->b_data; i < epb; i++, cbp++) {
+ for (i = 0, cbp = buf->b_data; i < epb; i++, cbp++) {
zbookmark_phys_t czb;
SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
zb->zb_level - 1,
zb->zb_blkid * epb + i);
dsl_scan_visitbp(cbp, &czb, dnp,
- *bufp, ds, scn, ostype, tx);
- }
- } else if (BP_GET_TYPE(bp) == DMU_OT_USERGROUP_USED) {
- uint32_t flags = ARC_WAIT;
-
- err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
- ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
- if (err) {
- scn->scn_phys.scn_errors++;
- return (err);
+ ds, scn, ostype, tx);
}
+ (void) arc_buf_remove_ref(buf, &buf);
} else if (BP_GET_TYPE(bp) == DMU_OT_DNODE) {
uint32_t flags = ARC_WAIT;
dnode_phys_t *cdnp;
int i, j;
int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT;
+ arc_buf_t *buf;
- err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
+ err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, &buf,
ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
if (err) {
scn->scn_phys.scn_errors++;
return (err);
}
- for (i = 0, cdnp = (*bufp)->b_data; i < epb; i++, cdnp++) {
+ for (i = 0, cdnp = buf->b_data; i < epb; i++, cdnp++) {
for (j = 0; j < cdnp->dn_nblkptr; j++) {
blkptr_t *cbp = &cdnp->dn_blkptr[j];
- dsl_scan_prefetch(scn, *bufp, cbp,
+ dsl_scan_prefetch(scn, buf, cbp,
zb->zb_objset, zb->zb_blkid * epb + i, j);
}
}
- for (i = 0, cdnp = (*bufp)->b_data; i < epb; i++, cdnp++) {
+ for (i = 0, cdnp = buf->b_data; i < epb; i++, cdnp++) {
dsl_scan_visitdnode(scn, ds, ostype,
- cdnp, *bufp, zb->zb_blkid * epb + i, tx);
+ cdnp, zb->zb_blkid * epb + i, tx);
}
+ (void) arc_buf_remove_ref(buf, &buf);
} else if (BP_GET_TYPE(bp) == DMU_OT_OBJSET) {
uint32_t flags = ARC_WAIT;
objset_phys_t *osp;
+ arc_buf_t *buf;
- err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
+ err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, &buf,
ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
if (err) {
scn->scn_phys.scn_errors++;
return (err);
}
- osp = (*bufp)->b_data;
+ osp = buf->b_data;
dsl_scan_visitdnode(scn, ds, osp->os_type,
- &osp->os_meta_dnode, *bufp, DMU_META_DNODE_OBJECT, tx);
+ &osp->os_meta_dnode, DMU_META_DNODE_OBJECT, tx);
- if (OBJSET_BUF_HAS_USERUSED(*bufp)) {
+ if (OBJSET_BUF_HAS_USERUSED(buf)) {
/*
* We also always visit user/group accounting
* objects, and never skip them, even if we are
@@ -703,12 +698,13 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
* deltas from this txg get integrated.
*/
dsl_scan_visitdnode(scn, ds, osp->os_type,
- &osp->os_groupused_dnode, *bufp,
+ &osp->os_groupused_dnode,
DMU_GROUPUSED_OBJECT, tx);
dsl_scan_visitdnode(scn, ds, osp->os_type,
- &osp->os_userused_dnode, *bufp,
+ &osp->os_userused_dnode,
DMU_USERUSED_OBJECT, tx);
}
+ (void) arc_buf_remove_ref(buf, &buf);
}
return (0);
@@ -716,7 +712,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
static void
dsl_scan_visitdnode(dsl_scan_t *scn, dsl_dataset_t *ds,
- dmu_objset_type_t ostype, dnode_phys_t *dnp, arc_buf_t *buf,
+ dmu_objset_type_t ostype, dnode_phys_t *dnp,
uint64_t object, dmu_tx_t *tx)
{
int j;
@@ -727,7 +723,7 @@ dsl_scan_visitdnode(dsl_scan_t *scn, dsl_dataset_t *ds,
SET_BOOKMARK(&czb, ds ? ds->ds_object : 0, object,
dnp->dn_nlevels - 1, j);
dsl_scan_visitbp(&dnp->dn_blkptr[j],
- &czb, dnp, buf, ds, scn, ostype, tx);
+ &czb, dnp, ds, scn, ostype, tx);
}
if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
@@ -735,7 +731,7 @@ dsl_scan_visitdnode(dsl_scan_t *scn, dsl_dataset_t *ds,
SET_BOOKMARK(&czb, ds ? ds->ds_object : 0, object,
0, DMU_SPILL_BLKID);
dsl_scan_visitbp(&dnp->dn_spill,
- &czb, dnp, buf, ds, scn, ostype, tx);
+ &czb, dnp, ds, scn, ostype, tx);
}
}
@@ -745,9 +741,8 @@ dsl_scan_visitdnode(dsl_scan_t *scn, dsl_dataset_t *ds,
*/
static void
dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
- dnode_phys_t *dnp, arc_buf_t *pbuf,
- dsl_dataset_t *ds, dsl_scan_t *scn, dmu_objset_type_t ostype,
- dmu_tx_t *tx)
+ dnode_phys_t *dnp, dsl_dataset_t *ds, dsl_scan_t *scn,
+ dmu_objset_type_t ostype, dmu_tx_t *tx)
{
dsl_pool_t *dp = scn->scn_dp;
arc_buf_t *buf = NULL;
@@ -767,16 +762,15 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
scn->scn_visited_this_txg++;
dprintf_bp(bp,
- "visiting ds=%p/%llu zb=%llx/%llx/%llx/%llx buf=%p bp=%p",
+ "visiting ds=%p/%llu zb=%llx/%llx/%llx/%llx bp=%p",
ds, ds ? ds->ds_object : 0,
zb->zb_objset, zb->zb_object, zb->zb_level, zb->zb_blkid,
- pbuf, bp);
+ bp);
if (bp->blk_birth <= scn->scn_phys.scn_cur_min_txg)
return;
- if (dsl_scan_recurse(scn, ds, ostype, dnp, &bp_toread, zb, tx,
- &buf) != 0)
+ if (dsl_scan_recurse(scn, ds, ostype, dnp, &bp_toread, zb, tx) != 0)
return;
/*
@@ -800,8 +794,6 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
if (BP_PHYSICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_max_txg) {
scan_funcs[scn->scn_phys.scn_func](dp, bp, zb);
}
- if (buf)
- (void) arc_buf_remove_ref(buf, &buf);
}
static void
@@ -812,7 +804,7 @@ dsl_scan_visit_rootbp(dsl_scan_t *scn, dsl_dataset_t *ds, blkptr_t *bp,
SET_BOOKMARK(&zb, ds ? ds->ds_object : DMU_META_OBJSET,
ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
- dsl_scan_visitbp(bp, &zb, NULL, NULL,
+ dsl_scan_visitbp(bp, &zb, NULL,
ds, scn, DMU_OST_NONE, tx);
dprintf_ds(ds, "finished scan%s", "");
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
index 370556f..c2bcbfd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
@@ -75,7 +75,7 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, condense_pct, CTLFLAG_RWTUN,
/*
* Condensing a metaslab is not guaranteed to actually reduce the amount of
* space used on disk. In particular, a space map uses data in increments of
- * MAX(1 << ashift, SPACE_MAP_INITIAL_BLOCKSIZE), so a metaslab might use the
+ * MAX(1 << ashift, space_map_blksize), so a metaslab might use the
* same number of blocks after condensing. Since the goal of condensing is to
* reduce the number of IOPs required to read the space map, we only want to
* condense when we can be sure we will reduce the number of blocks used by the
@@ -1470,10 +1470,12 @@ metaslab_fragmentation(metaslab_t *msp)
uint64_t txg = spa_syncing_txg(spa);
vdev_t *vd = msp->ms_group->mg_vd;
- msp->ms_condense_wanted = B_TRUE;
- vdev_dirty(vd, VDD_METASLAB, msp, txg + 1);
- spa_dbgmsg(spa, "txg %llu, requesting force condense: "
- "msp %p, vd %p", txg, msp, vd);
+ if (spa_writeable(spa)) {
+ msp->ms_condense_wanted = B_TRUE;
+ vdev_dirty(vd, VDD_METASLAB, msp, txg + 1);
+ spa_dbgmsg(spa, "txg %llu, requesting force condense: "
+ "msp %p, vd %p", txg, msp, vd);
+ }
return (ZFS_FRAG_INVALID);
}
@@ -1917,6 +1919,15 @@ metaslab_sync(metaslab_t *msp, uint64_t txg)
mutex_enter(&msp->ms_lock);
+ /*
+ * Note: metaslab_condense() clears the space_map's histogram.
+ * Therefore we must verify and remove this histogram before
+ * condensing.
+ */
+ metaslab_group_histogram_verify(mg);
+ metaslab_class_histogram_verify(mg->mg_class);
+ metaslab_group_histogram_remove(mg, msp);
+
if (msp->ms_loaded && spa_sync_pass(spa) == 1 &&
metaslab_should_condense(msp)) {
metaslab_condense(msp, txg, tx);
@@ -1925,9 +1936,6 @@ metaslab_sync(metaslab_t *msp, uint64_t txg)
space_map_write(msp->ms_sm, *freetree, SM_FREE, tx);
}
- metaslab_group_histogram_verify(mg);
- metaslab_class_histogram_verify(mg->mg_class);
- metaslab_group_histogram_remove(mg, msp);
if (msp->ms_loaded) {
/*
* When the space map is loaded, we have an accruate
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/range_tree.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/range_tree.c
index 22175e0..6422fd1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/range_tree.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/range_tree.c
@@ -33,7 +33,7 @@
#include <sys/zio.h>
#include <sys/range_tree.h>
-static kmem_cache_t *range_seg_cache;
+kmem_cache_t *range_seg_cache;
void
range_tree_init(void)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
index 0100206..2cdfeb0 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -1277,7 +1277,9 @@ spa_unload(spa_t *spa)
* Wait for any outstanding async I/O to complete.
*/
if (spa->spa_async_zio_root != NULL) {
- (void) zio_wait(spa->spa_async_zio_root);
+ for (int i = 0; i < max_ncpus; i++)
+ (void) zio_wait(spa->spa_async_zio_root[i]);
+ kmem_free(spa->spa_async_zio_root, max_ncpus * sizeof (void *));
spa->spa_async_zio_root = NULL;
}
@@ -2213,8 +2215,13 @@ spa_load_impl(spa_t *spa, uint64_t pool_guid, nvlist_t *config,
/*
* Create "The Godfather" zio to hold all async IOs
*/
- spa->spa_async_zio_root = zio_root(spa, NULL, NULL,
- ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE | ZIO_FLAG_GODFATHER);
+ spa->spa_async_zio_root = kmem_alloc(max_ncpus * sizeof (void *),
+ KM_SLEEP);
+ for (int i = 0; i < max_ncpus; i++) {
+ spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
+ ZIO_FLAG_GODFATHER);
+ }
/*
* Parse the configuration into a vdev tree. We explicitly set the
@@ -3567,8 +3574,13 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
/*
* Create "The Godfather" zio to hold all async IOs
*/
- spa->spa_async_zio_root = zio_root(spa, NULL, NULL,
- ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE | ZIO_FLAG_GODFATHER);
+ spa->spa_async_zio_root = kmem_alloc(max_ncpus * sizeof (void *),
+ KM_SLEEP);
+ for (int i = 0; i < max_ncpus; i++) {
+ spa->spa_async_zio_root[i] = zio_root(spa, NULL, NULL,
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE |
+ ZIO_FLAG_GODFATHER);
+ }
/*
* Create the root vdev.
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
index d158b24..94790b9 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
@@ -38,15 +38,12 @@
#include <sys/zfeature.h>
/*
- * This value controls how the space map's block size is allowed to grow.
- * If the value is set to the same size as SPACE_MAP_INITIAL_BLOCKSIZE then
- * the space map block size will remain fixed. Setting this value to something
- * greater than SPACE_MAP_INITIAL_BLOCKSIZE will allow the space map to
- * increase its block size as needed. To maintain backwards compatibilty the
- * space map's block size must be a power of 2 and SPACE_MAP_INITIAL_BLOCKSIZE
- * or larger.
+ * The data for a given space map can be kept on blocks of any size.
+ * Larger blocks entail fewer i/o operations, but they also cause the
+ * DMU to keep more data in-core, and also to waste more i/o bandwidth
+ * when only a few blocks have changed since the last transaction group.
*/
-int space_map_max_blksz = (1 << 12);
+int space_map_blksz = (1 << 12);
/*
* Load the space map disk into the specified range tree. Segments of maptype
@@ -233,58 +230,6 @@ space_map_entries(space_map_t *sm, range_tree_t *rt)
return (entries);
}
-void
-space_map_set_blocksize(space_map_t *sm, uint64_t size, dmu_tx_t *tx)
-{
- uint32_t blksz;
- u_longlong_t blocks;
-
- ASSERT3U(sm->sm_blksz, !=, 0);
- ASSERT3U(space_map_object(sm), !=, 0);
- ASSERT(sm->sm_dbuf != NULL);
- VERIFY(ISP2(space_map_max_blksz));
-
- if (sm->sm_blksz >= space_map_max_blksz)
- return;
-
- /*
- * The object contains more than one block so we can't adjust
- * its size.
- */
- if (sm->sm_phys->smp_objsize > sm->sm_blksz)
- return;
-
- if (size > sm->sm_blksz) {
- uint64_t newsz;
-
- /*
- * Older software versions treat space map blocks as fixed
- * entities. The DMU is capable of handling different block
- * sizes making it possible for us to increase the
- * block size and maintain backwards compatibility. The
- * caveat is that the new block sizes must be a
- * power of 2 so that old software can append to the file,
- * adding more blocks. The block size can grow until it
- * reaches space_map_max_blksz.
- */
- newsz = ISP2(size) ? size : 1ULL << highbit64(size);
- if (newsz > space_map_max_blksz)
- newsz = space_map_max_blksz;
-
- VERIFY0(dmu_object_set_blocksize(sm->sm_os,
- space_map_object(sm), newsz, 0, tx));
- dmu_object_size_from_db(sm->sm_dbuf, &blksz, &blocks);
-
- zfs_dbgmsg("txg %llu, spa %s, increasing blksz from %d to %d",
- dmu_tx_get_txg(tx), spa_name(dmu_objset_spa(sm->sm_os)),
- sm->sm_blksz, blksz);
-
- VERIFY3U(newsz, ==, blksz);
- VERIFY3U(sm->sm_blksz, <, blksz);
- sm->sm_blksz = blksz;
- }
-}
-
/*
* Note: space_map_write() will drop sm_lock across dmu_write() calls.
*/
@@ -298,7 +243,7 @@ space_map_write(space_map_t *sm, range_tree_t *rt, maptype_t maptype,
range_seg_t *rs;
uint64_t size, total, rt_space, nodes;
uint64_t *entry, *entry_map, *entry_map_end;
- uint64_t newsz, expected_entries, actual_entries = 1;
+ uint64_t expected_entries, actual_entries = 1;
ASSERT(MUTEX_HELD(rt->rt_lock));
ASSERT(dsl_pool_sync_context(dmu_objset_pool(os)));
@@ -324,13 +269,6 @@ space_map_write(space_map_t *sm, range_tree_t *rt, maptype_t maptype,
expected_entries = space_map_entries(sm, rt);
- /*
- * Calculate the new size for the space map on-disk and see if
- * we can grow the block size to accommodate the new size.
- */
- newsz = sm->sm_phys->smp_objsize + expected_entries * sizeof (uint64_t);
- space_map_set_blocksize(sm, newsz, tx);
-
entry_map = zio_buf_alloc(sm->sm_blksz);
entry_map_end = entry_map + (sm->sm_blksz / sizeof (uint64_t));
entry = entry_map;
@@ -457,46 +395,48 @@ space_map_close(space_map_t *sm)
kmem_free(sm, sizeof (*sm));
}
-static void
-space_map_reallocate(space_map_t *sm, dmu_tx_t *tx)
-{
- ASSERT(dmu_tx_is_syncing(tx));
-
- space_map_free(sm, tx);
- dmu_buf_rele(sm->sm_dbuf, sm);
-
- sm->sm_object = space_map_alloc(sm->sm_os, tx);
- VERIFY0(space_map_open_impl(sm));
-}
-
void
space_map_truncate(space_map_t *sm, dmu_tx_t *tx)
{
objset_t *os = sm->sm_os;
spa_t *spa = dmu_objset_spa(os);
dmu_object_info_t doi;
- int bonuslen;
ASSERT(dsl_pool_sync_context(dmu_objset_pool(os)));
ASSERT(dmu_tx_is_syncing(tx));
- VERIFY0(dmu_free_range(os, space_map_object(sm), 0, -1ULL, tx));
dmu_object_info_from_db(sm->sm_dbuf, &doi);
- if (spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM)) {
- bonuslen = sizeof (space_map_phys_t);
- ASSERT3U(bonuslen, <=, dmu_bonus_max());
- } else {
- bonuslen = SPACE_MAP_SIZE_V0;
- }
-
- if (bonuslen != doi.doi_bonus_size ||
- doi.doi_data_block_size != SPACE_MAP_INITIAL_BLOCKSIZE) {
+ /*
+ * If the space map has the wrong bonus size (because
+ * SPA_FEATURE_SPACEMAP_HISTOGRAM has recently been enabled), or
+ * the wrong block size (because space_map_blksz has changed),
+ * free and re-allocate its object with the updated sizes.
+ *
+ * Otherwise, just truncate the current object.
+ */
+ if ((spa_feature_is_enabled(spa, SPA_FEATURE_SPACEMAP_HISTOGRAM) &&
+ doi.doi_bonus_size != sizeof (space_map_phys_t)) ||
+ doi.doi_data_block_size != space_map_blksz) {
zfs_dbgmsg("txg %llu, spa %s, reallocating: "
"old bonus %u, old blocksz %u", dmu_tx_get_txg(tx),
spa_name(spa), doi.doi_bonus_size, doi.doi_data_block_size);
- space_map_reallocate(sm, tx);
- VERIFY3U(sm->sm_blksz, ==, SPACE_MAP_INITIAL_BLOCKSIZE);
+
+ space_map_free(sm, tx);
+ dmu_buf_rele(sm->sm_dbuf, sm);
+
+ sm->sm_object = space_map_alloc(sm->sm_os, tx);
+ VERIFY0(space_map_open_impl(sm));
+ } else {
+ VERIFY0(dmu_free_range(os, space_map_object(sm), 0, -1ULL, tx));
+
+ /*
+ * If the spacemap is reallocated, its histogram
+ * will be reset. Do the same in the common case so that
+ * bugs related to the uncommon case do not go unnoticed.
+ */
+ bzero(sm->sm_phys->smp_histogram,
+ sizeof (sm->sm_phys->smp_histogram));
}
dmu_buf_will_dirty(sm->sm_dbuf, tx);
@@ -535,7 +475,7 @@ space_map_alloc(objset_t *os, dmu_tx_t *tx)
}
object = dmu_object_alloc(os,
- DMU_OT_SPACE_MAP, SPACE_MAP_INITIAL_BLOCKSIZE,
+ DMU_OT_SPACE_MAP, space_map_blksz,
DMU_OT_SPACE_MAP_HEADER, bonuslen, tx);
return (object);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
index 2c0b5ae..ad19266 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
@@ -25,6 +25,7 @@
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright 2013 DEY Storage Systems, Inc.
+ * Copyright 2014 HybridCluster. All rights reserved.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -341,7 +342,7 @@ uint64_t dmu_object_alloc(objset_t *os, dmu_object_type_t ot,
int dmu_object_claim(objset_t *os, uint64_t object, dmu_object_type_t ot,
int blocksize, dmu_object_type_t bonus_type, int bonus_len, dmu_tx_t *tx);
int dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
- int blocksize, dmu_object_type_t bonustype, int bonuslen);
+ int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *txp);
/*
* Free an object from this objset.
@@ -616,6 +617,7 @@ void dmu_write(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
void dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
dmu_tx_t *tx);
int dmu_read_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size);
+int dmu_read_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size);
int dmu_write_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size,
dmu_tx_t *tx);
int dmu_write_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size,
@@ -661,7 +663,8 @@ typedef struct dmu_object_info {
uint8_t doi_indirection; /* 2 = dnode->indirect->data */
uint8_t doi_checksum;
uint8_t doi_compress;
- uint8_t doi_pad[5];
+ uint8_t doi_nblkptr;
+ uint8_t doi_pad[4];
uint64_t doi_physical_blocks_512; /* data + metadata, 512b blks */
uint64_t doi_max_offset;
uint64_t doi_fill_count; /* number of non-empty blocks */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
index a1943e7..40f5b06 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
@@ -206,7 +206,8 @@ struct spa {
uint64_t spa_failmode; /* failure mode for the pool */
uint64_t spa_delegation; /* delegation on/off */
list_t spa_config_list; /* previous cache file(s) */
- zio_t *spa_async_zio_root; /* root of all async I/O */
+ /* per-CPU array of root of async I/O: */
+ zio_t **spa_async_zio_root;
zio_t *spa_suspend_zio_root; /* root of all suspended I/O */
kmutex_t spa_suspend_lock; /* protects suspend_zio_root */
kcondvar_t spa_suspend_cv; /* notification of resume */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h
index 67fa276..a59e6d3 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h
@@ -133,17 +133,6 @@ typedef enum {
SM_FREE
} maptype_t;
-/*
- * The data for a given space map can be kept on blocks of any size.
- * Larger blocks entail fewer i/o operations, but they also cause the
- * DMU to keep more data in-core, and also to waste more i/o bandwidth
- * when only a few blocks have changed since the last transaction group.
- * Rather than having a fixed block size for all space maps the block size
- * can adjust as needed (see space_map_max_blksz). Set the initial block
- * size for the space map to 4k.
- */
-#define SPACE_MAP_INITIAL_BLOCKSIZE (1ULL << 12)
-
int space_map_load(space_map_t *sm, range_tree_t *rt, maptype_t maptype);
void space_map_histogram_clear(space_map_t *sm);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
index 7eac42c..dea1a8f 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
@@ -156,6 +156,15 @@ static vdev_ops_t *vdev_ops_table[] = {
/*
+ * When a vdev is added, it will be divided into approximately (but no
+ * more than) this number of metaslabs.
+ */
+int metaslabs_per_vdev = 200;
+SYSCTL_INT(_vfs_zfs_vdev, OID_AUTO, metaslabs_per_vdev, CTLFLAG_RDTUN,
+ &metaslabs_per_vdev, 0,
+ "When a vdev is added, how many metaslabs the vdev should be divided into");
+
+/*
* Given a vdev type, return the appropriate ops vector.
*/
static vdev_ops_t *
@@ -1663,9 +1672,9 @@ void
vdev_metaslab_set_size(vdev_t *vd)
{
/*
- * Aim for roughly 200 metaslabs per vdev.
+ * Aim for roughly metaslabs_per_vdev (default 200) metaslabs per vdev.
*/
- vd->vdev_ms_shift = highbit64(vd->vdev_asize / 200);
+ vd->vdev_ms_shift = highbit64(vd->vdev_asize / metaslabs_per_vdev);
vd->vdev_ms_shift = MAX(vd->vdev_ms_shift, SPA_MAXBLOCKSHIFT);
}
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 109a339..5fec709 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
@@ -582,7 +582,6 @@ static int
mappedread(vnode_t *vp, int nbytes, uio_t *uio)
{
znode_t *zp = VTOZ(vp);
- objset_t *os = zp->z_zfsvfs->z_os;
vm_object_t obj;
int64_t start;
caddr_t va;
@@ -613,7 +612,8 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
page_unhold(pp);
} else {
zfs_vmobject_wunlock(obj);
- error = dmu_read_uio(os, zp->z_id, uio, bytes);
+ error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
+ uio, bytes);
zfs_vmobject_wlock(obj);
}
len -= bytes;
@@ -650,7 +650,6 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- objset_t *os;
ssize_t n, nbytes;
int error = 0;
rl_t *rl;
@@ -658,7 +657,6 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
- os = zfsvfs->z_os;
if (zp->z_pflags & ZFS_AV_QUARANTINED) {
ZFS_EXIT(zfsvfs);
@@ -756,10 +754,12 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
error = mappedread_sf(vp, nbytes, uio);
else
#endif /* __FreeBSD__ */
- if (vn_has_cached_data(vp))
+ if (vn_has_cached_data(vp)) {
error = mappedread(vp, nbytes, uio);
- else
- error = dmu_read_uio(os, zp->z_id, uio, nbytes);
+ } else {
+ error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
+ uio, nbytes);
+ }
if (error) {
/* convert checksum errors into IO errors */
if (error == ECKSUM)
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 895b0ce..3586f872 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
@@ -1457,7 +1457,7 @@ zio_nowait(zio_t *zio)
*/
spa_t *spa = zio->io_spa;
- zio_add_child(spa->spa_async_zio_root, zio);
+ zio_add_child(spa->spa_async_zio_root[CPU_SEQID], zio);
}
zio_execute(zio);
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 e8a79f2..f56efe8 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
@@ -167,6 +167,14 @@ static LIST_HEAD(, zvol_state) all_zvols;
*/
int zvol_maxphys = DMU_MAX_ACCESS/2;
+/*
+ * Toggle unmap functionality.
+ */
+boolean_t zvol_unmap_enabled = B_TRUE;
+SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, unmap_enabled, CTLFLAG_RWTUN,
+ &zvol_unmap_enabled, 0,
+ "Enable UNMAP functionality");
+
static d_open_t zvol_d_open;
static d_close_t zvol_d_close;
static d_read_t zvol_read;
@@ -1971,6 +1979,9 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
dkioc_free_t df;
dmu_tx_t *tx;
+ if (!zvol_unmap_enabled)
+ break;
+
if (ddi_copyin((void *)arg, &df, sizeof (df), flag)) {
error = SET_ERROR(EFAULT);
break;
@@ -1983,8 +1994,8 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
*/
if (df.df_start >= zv->zv_volsize)
break; /* No need to do anything... */
- if (df.df_start + df.df_length > zv->zv_volsize)
- df.df_length = DMU_OBJECT_END;
+
+ mutex_exit(&spa_namespace_lock);
rl = zfs_range_lock(&zv->zv_znode, df.df_start, df.df_length,
RL_WRITER);
@@ -2023,7 +2034,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
dmu_objset_pool(zv->zv_objset), 0);
}
}
- break;
+ return (error);
}
default:
@@ -2815,6 +2826,9 @@ zvol_d_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct threa
zil_commit(zv->zv_zilog, ZVOL_OBJ);
break;
case DIOCGDELETE:
+ if (!zvol_unmap_enabled)
+ break;
+
offset = ((off_t *)data)[0];
length = ((off_t *)data)[1];
if ((offset % DEV_BSIZE) != 0 || (length % DEV_BSIZE) != 0 ||
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
index 9bffe80..d426e19 100644
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 270691 2014-08-27 01:02:02Z kib
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
#ifndef _FREEBSD32_SYSPROTO_H_
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
index b1c45d9..e627ff3 100644
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 270691 2014-08-27 01:02:02Z kib
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
#define FREEBSD32_SYS_syscall 0
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
index 1e6edf5..2bf45ea 100644
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 270691 2014-08-27 01:02:02Z kib
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
const char *freebsd32_syscallnames[] = {
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
index c93e44a..9735e30 100644
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 270691 2014-08-27 01:02:02Z kib
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
#include "opt_compat.h"
@@ -518,10 +518,10 @@ struct sysent freebsd32_sysent[] = {
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 468 = nosys */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 469 = __getpath_fromfd */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 470 = __getpath_fromaddr */
- { AS(sctp_peeloff_args), (sy_call_t *)sys_sctp_peeloff, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 471 = sctp_peeloff */
- { AS(sctp_generic_sendmsg_args), (sy_call_t *)sys_sctp_generic_sendmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 472 = sctp_generic_sendmsg */
- { AS(sctp_generic_sendmsg_iov_args), (sy_call_t *)sys_sctp_generic_sendmsg_iov, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 473 = sctp_generic_sendmsg_iov */
- { AS(sctp_generic_recvmsg_args), (sy_call_t *)sys_sctp_generic_recvmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 474 = sctp_generic_recvmsg */
+ { AS(sctp_peeloff_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 471 = sctp_peeloff */
+ { AS(sctp_generic_sendmsg_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 472 = sctp_generic_sendmsg */
+ { AS(sctp_generic_sendmsg_iov_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 473 = sctp_generic_sendmsg_iov */
+ { AS(sctp_generic_recvmsg_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 474 = sctp_generic_recvmsg */
#ifdef PAD64_REQUIRED
{ AS(freebsd32_pread_args), (sy_call_t *)freebsd32_pread, AUE_PREAD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 475 = freebsd32_pread */
{ AS(freebsd32_pwrite_args), (sy_call_t *)freebsd32_pwrite, AUE_PWRITE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 476 = freebsd32_pwrite */
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 161f69d..2fafc0c 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -845,14 +845,14 @@
468 AUE_NULL UNIMPL nosys
469 AUE_NULL UNIMPL __getpath_fromfd
470 AUE_NULL UNIMPL __getpath_fromaddr
-471 AUE_NULL NOPROTO { int sctp_peeloff(int sd, uint32_t name); }
-472 AUE_NULL NOPROTO { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
+471 AUE_NULL NOPROTO|NOSTD { int sctp_peeloff(int sd, uint32_t name); }
+472 AUE_NULL NOPROTO|NOSTD { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
caddr_t to, __socklen_t tolen, \
struct sctp_sndrcvinfo *sinfo, int flags); }
-473 AUE_NULL NOPROTO { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
+473 AUE_NULL NOPROTO|NOSTD { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
caddr_t to, __socklen_t tolen, \
struct sctp_sndrcvinfo *sinfo, int flags); }
-474 AUE_NULL NOPROTO { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
+474 AUE_NULL NOPROTO|NOSTD { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
struct sockaddr * from, __socklen_t *fromlenaddr, \
struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
#ifdef PAD64_REQUIRED
diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm
index 08e70f3..2727f81 100644
--- a/sys/conf/Makefile.arm
+++ b/sys/conf/Makefile.arm
@@ -42,6 +42,9 @@ STRIP_FLAGS = -S
# We don't support gcc's thump interwork stuff, so disable it
CFLAGS.gcc += -mno-thumb-interwork
+# We generally don't want fpu instructions in the kernel.
+CFLAGS.clang += -mfpu=none
+
.if !empty(DDB_ENABLED)
CFLAGS += -funwind-tables
# clang requires us to tell it to emit assembly with unwind information
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 5baa306..5cc146e 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2958,6 +2958,7 @@ options SC_RENDER_DEBUG # syscons rendering debugging
options VFS_BIO_DEBUG # VFS buffer I/O debugging
options KSTACK_MAX_PAGES=32 # Maximum pages to give the kernel stack
+options KSTACK_USAGE_PROF
# Adaptec Array Controller driver options
options AAC_DEBUG # Debugging levels:
diff --git a/sys/conf/files b/sys/conf/files
index 20f0d6e..0a59317 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3163,6 +3163,7 @@ libkern/arc4random.c standard
libkern/bcd.c standard
libkern/bsearch.c standard
libkern/crc32.c standard
+libkern/explicit_bzero.c standard
libkern/fnmatch.c standard
libkern/iconv.c optional libiconv
libkern/iconv_converter_if.m optional libiconv
@@ -3428,6 +3429,7 @@ netinet/sctp_output.c optional inet sctp | inet6 sctp
netinet/sctp_pcb.c optional inet sctp | inet6 sctp
netinet/sctp_peeloff.c optional inet sctp | inet6 sctp
netinet/sctp_ss_functions.c optional inet sctp | inet6 sctp
+netinet/sctp_syscalls.c optional inet sctp | inet6 sctp
netinet/sctp_sysctl.c optional inet sctp | inet6 sctp
netinet/sctp_timer.c optional inet sctp | inet6 sctp
netinet/sctp_usrreq.c optional inet sctp | inet6 sctp
@@ -3512,6 +3514,9 @@ netpfil/ipfw/ip_fw_log.c optional inet ipfirewall
netpfil/ipfw/ip_fw_pfil.c optional inet ipfirewall
netpfil/ipfw/ip_fw_sockopt.c optional inet ipfirewall
netpfil/ipfw/ip_fw_table.c optional inet ipfirewall
+netpfil/ipfw/ip_fw_table_algo.c optional inet ipfirewall
+netpfil/ipfw/ip_fw_table_value.c optional inet ipfirewall
+netpfil/ipfw/ip_fw_iface.c optional inet ipfirewall
netpfil/ipfw/ip_fw_nat.c optional inet ipfirewall_nat
netpfil/pf/if_pflog.c optional pflog pf inet
netpfil/pf/if_pfsync.c optional pfsync pf inet
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 555b443..be67ce4 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -89,7 +89,8 @@ dev/agp/agp_via.c optional agp
dev/aic/aic_cbus.c optional aic isa
dev/ce/ceddk.c optional ce
dev/ce/if_ce.c optional ce
-dev/ce/tau32-ddk.c optional ce
+dev/ce/tau32-ddk.c optional ce \
+ compile-with "${NORMAL_C} ${NO_WCONSTANT_CONVERSION}"
dev/cp/cpddk.c optional cp
dev/cp/if_cp.c optional cp
dev/ct/bshw_machdep.c optional ct
@@ -148,6 +149,7 @@ i386/i386/initcpu.c standard
i386/i386/io.c optional io
i386/i386/k6_mem.c optional mem
i386/i386/locore.s standard no-obj
+i386/i386/machdep.c standard
i386/i386/mem.c optional mem
i386/i386/minidump_machdep.c standard
i386/i386/mp_clock.c optional smp
@@ -236,12 +238,11 @@ pc98/pc98/busiosubr.c standard
pc98/pc98/canbepm.c optional canbepm
pc98/pc98/canbus.c optional canbus
pc98/pc98/canbus_if.m optional canbus
-pc98/pc98/machdep.c standard
pc98/pc98/pc98_machdep.c standard
#
# x86 shared code between IA32, AMD64 and PC98 architectures
#
-x86/isa/atpic.c optional atpic
+x86/isa/atpic.c optional atpic
x86/isa/clock.c standard
x86/isa/isa.c optional isa
x86/pci/pci_bus.c optional pci
@@ -259,5 +260,4 @@ x86/x86/mptable_pci.c optional apic pci
x86/x86/msi.c optional apic pci
x86/x86/nexus.c standard
x86/x86/tsc.c standard
-x86/x86/tsc.c standard
x86/x86/delay.c standard
diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk
index c3fb969..ac94936 100644
--- a/sys/conf/kern.mk
+++ b/sys/conf/kern.mk
@@ -33,7 +33,13 @@ CWARNEXTRA?= -Wno-error-tautological-compare -Wno-error-empty-body \
.endif
.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} >= 40300
-CWARNEXTRA?= -Wno-inline
+# Catch-all for all the things that are in our tree, but for which we're
+# not yet ready for this compiler. Note: we likely only really "support"
+# building with gcc 4.8 and newer. Nothing older has been tested.
+CWARNEXTRA?= -Wno-error=inline -Wno-error=enum-compare -Wno-error=unused-but-set-variable \
+ -Wno-error=aggressive-loop-optimizations -Wno-error=maybe-uninitialized \
+ -Wno-error=array-bounds -Wno-error=address \
+ -Wno-error=cast-qual -Wno-error=sequence-point -Wno-error=attributes
.endif
# External compilers may not support our format extensions. Allow them
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 73bf267..f323a0d 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -89,7 +89,7 @@ fi
touch version
v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} t=`date`
i=`${MAKE:-make} -V KERN_IDENT`
-compiler_v=$($(${MAKE:-make} -V CC) -v 2>&1 | grep 'version')
+compiler_v=$($(${MAKE:-make} -V CC) -v 2>&1 | grep -w 'version')
for dir in /usr/bin /usr/local/bin; do
if [ ! -z "${svnversion}" ] ; then
diff --git a/sys/conf/options b/sys/conf/options
index 42113c3..8337521 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -136,6 +136,7 @@ KDTRACE_FRAME opt_kdtrace.h
KN_HASHSIZE opt_kqueue.h
KSTACK_MAX_PAGES
KSTACK_PAGES
+KSTACK_USAGE_PROF
KTRACE
KTRACE_REQUEST_POOL opt_ktrace.h
LIBICONV
diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98
index a10737b..a19ebd1 100644
--- a/sys/conf/options.pc98
+++ b/sys/conf/options.pc98
@@ -31,12 +31,6 @@ KVA_PAGES opt_global.h
TIMER_FREQ opt_clock.h
-# options for serial support
-COM_ESP opt_sio.h
-COM_MULTIPORT opt_sio.h
-CONSPEED opt_sio.h
-GDBSPEED opt_sio.h
-
CPU_BLUELIGHTNING_3X opt_cpu.h
CPU_BLUELIGHTNING_FPU_OP_CACHE opt_cpu.h
CPU_BTB_EN opt_cpu.h
@@ -67,8 +61,17 @@ I486_CPU opt_global.h
I586_CPU opt_global.h
I686_CPU opt_global.h
+# options for serial support
+COM_ESP opt_sio.h
+COM_MULTIPORT opt_sio.h
+CONSPEED opt_sio.h
+GDBSPEED opt_sio.h
+
GDC
+# AGP debugging support
+AGP_DEBUG opt_agp.h
+
# Video spigot
SPIGOT_UNSECURE opt_spigot.h
@@ -96,7 +99,6 @@ DEV_NPX opt_npx.h
# Debugging
NPX_DEBUG opt_npx.h
-AGP_DEBUG opt_agp.h
# BPF just-in-time compiler
BPF_JITTER opt_bpf.h
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c
index 2adfe26..4d86e47 100644
--- a/sys/contrib/ipfilter/netinet/fil.c
+++ b/sys/contrib/ipfilter/netinet/fil.c
@@ -4436,6 +4436,39 @@ ipf_matchicmpqueryreply(v, ic, icmp, rev)
/* ------------------------------------------------------------------------ */
+/* Function: ipf_rule_compare */
+/* Parameters: fr1(I) - first rule structure to compare */
+/* fr2(I) - second rule structure to compare */
+/* Returns: int - 0 == rules are the same, else mismatch */
+/* */
+/* Compare two rules and return 0 if they match or a number indicating */
+/* which of the individual checks failed. */
+/* ------------------------------------------------------------------------ */
+static int
+ipf_rule_compare(frentry_t *fr1, frentry_t *fr2)
+{
+ if (fr1->fr_cksum != fr2->fr_cksum)
+ return 1;
+ if (fr1->fr_size != fr2->fr_size)
+ return 2;
+ if (fr1->fr_dsize != fr2->fr_dsize)
+ return 3;
+ if (bcmp((char *)&fr1->fr_func, (char *)&fr2->fr_func,
+ fr1->fr_size - offsetof(struct frentry, fr_func)) != 0)
+ return 4;
+ if (fr1->fr_data && !fr2->fr_data)
+ return 5;
+ if (!fr1->fr_data && fr2->fr_data)
+ return 6;
+ if (fr1->fr_data) {
+ if (bcmp(fr1->fr_caddr, fr2->fr_caddr, fr1->fr_dsize))
+ return 7;
+ }
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
/* Function: frrequest */
/* Returns: int - 0 == success, > 0 == errno value */
/* Parameters: unit(I) - device for which this is for */
@@ -4496,7 +4529,15 @@ frrequest(softc, unit, req, data, set, makecopy)
fp = f;
f = NULL;
+ fp->fr_next = NULL;
fp->fr_dnext = NULL;
+ fp->fr_pnext = NULL;
+ fp->fr_pdnext = NULL;
+ fp->fr_grp = NULL;
+ fp->fr_grphead = NULL;
+ fp->fr_icmpgrp = NULL;
+ fp->fr_isc = (void *)-1;
+ fp->fr_ptr = NULL;
fp->fr_ref = 0;
fp->fr_flags |= FR_COPIED;
} else {
@@ -4920,17 +4961,7 @@ frrequest(softc, unit, req, data, set, makecopy)
}
for (; (f = *ftail) != NULL; ftail = &f->fr_next) {
- DT2(rule_cmp, frentry_t *, fp, frentry_t *, f);
- if ((fp->fr_cksum != f->fr_cksum) ||
- (fp->fr_size != f->fr_size) ||
- (f->fr_dsize != fp->fr_dsize))
- continue;
- if (bcmp((char *)&f->fr_func, (char *)&fp->fr_func,
- fp->fr_size - offsetof(struct frentry, fr_func)) != 0)
- continue;
- if ((!ptr && !f->fr_data) ||
- (ptr && f->fr_data &&
- !bcmp((char *)ptr, (char *)f->fr_data, f->fr_dsize)))
+ if (ipf_rule_compare(fp, f) == 0)
break;
}
@@ -5000,7 +5031,9 @@ frrequest(softc, unit, req, data, set, makecopy)
if (f->fr_collect > fp->fr_collect)
break;
ftail = &f->fr_next;
+ fprev = ftail;
}
+ ftail = fprev;
f = NULL;
ptr = NULL;
} else if (req == (ioctlcmd_t)SIOCINAFR ||
@@ -5091,6 +5124,8 @@ frrequest(softc, unit, req, data, set, makecopy)
fp->fr_ref = 1;
fp->fr_pnext = ftail;
fp->fr_next = *ftail;
+ if (fp->fr_next != NULL)
+ fp->fr_next->fr_pnext = &fp->fr_next;
*ftail = fp;
if (addrem == 0)
ipf_fixskip(ftail, fp, 1);
diff --git a/sys/contrib/ipfilter/netinet/ip_dns_pxy.c b/sys/contrib/ipfilter/netinet/ip_dns_pxy.c
index df863b8..ff1bc79 100644
--- a/sys/contrib/ipfilter/netinet/ip_dns_pxy.c
+++ b/sys/contrib/ipfilter/netinet/ip_dns_pxy.c
@@ -29,7 +29,7 @@ typedef struct ipf_dns_softc_s {
int ipf_p_dns_allow_query __P((ipf_dns_softc_t *, dnsinfo_t *));
int ipf_p_dns_ctl __P((ipf_main_softc_t *, void *, ap_ctl_t *));
-int ipf_p_dns_del __P((ipf_main_softc_t *, ap_session_t *));
+void ipf_p_dns_del __P((ipf_main_softc_t *, ap_session_t *));
int ipf_p_dns_get_name __P((ipf_dns_softc_t *, char *, int, char *, int));
int ipf_p_dns_inout __P((void *, fr_info_t *, ap_session_t *, nat_t *));
int ipf_p_dns_match __P((fr_info_t *, ap_session_t *, nat_t *));
@@ -214,7 +214,7 @@ ipf_p_dns_new(arg, fin, aps, nat)
/* ARGSUSED */
-int
+void
ipf_p_dns_del(softc, aps)
ipf_main_softc_t *softc;
ap_session_t *aps;
@@ -227,7 +227,6 @@ ipf_p_dns_del(softc, aps)
KFREES(aps->aps_data, aps->aps_psiz);
aps->aps_data = NULL;
aps->aps_psiz = 0;
- return 0;
}
diff --git a/sys/contrib/ipfilter/netinet/ip_dstlist.c b/sys/contrib/ipfilter/netinet/ip_dstlist.c
index d516556..dc7dacb 100644
--- a/sys/contrib/ipfilter/netinet/ip_dstlist.c
+++ b/sys/contrib/ipfilter/netinet/ip_dstlist.c
@@ -1193,7 +1193,7 @@ ipf_dstlist_select(fin, d)
MD5Update(&ctx, (u_char *)&fin->fin_dst6,
sizeof(fin->fin_dst6));
MD5Final((u_char *)hash, &ctx);
- x = hash[0] % d->ipld_nodes;
+ x = ntohl(hash[0]) % d->ipld_nodes;
sel = d->ipld_dests[x];
break;
@@ -1203,7 +1203,7 @@ ipf_dstlist_select(fin, d)
MD5Update(&ctx, (u_char *)&fin->fin_src6,
sizeof(fin->fin_src6));
MD5Final((u_char *)hash, &ctx);
- x = hash[0] % d->ipld_nodes;
+ x = ntohl(hash[0]) % d->ipld_nodes;
sel = d->ipld_dests[x];
break;
@@ -1213,7 +1213,7 @@ ipf_dstlist_select(fin, d)
MD5Update(&ctx, (u_char *)&fin->fin_dst6,
sizeof(fin->fin_dst6));
MD5Final((u_char *)hash, &ctx);
- x = hash[0] % d->ipld_nodes;
+ x = ntohl(hash[0]) % d->ipld_nodes;
sel = d->ipld_dests[x];
break;
diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c
index d664708..6c93810 100644
--- a/sys/contrib/ipfilter/netinet/ip_nat.c
+++ b/sys/contrib/ipfilter/netinet/ip_nat.c
@@ -2946,10 +2946,11 @@ ipf_nat_newrdr(fin, nat, ni)
*/
if (np->in_flags & IPN_SPLIT) {
in.s_addr = np->in_dnip;
+ inb.s_addr = htonl(in.s_addr);
if ((np->in_flags & (IPN_ROUNDR|IPN_STICKY)) == IPN_STICKY) {
hm = ipf_nat_hostmap(softn, NULL, fin->fin_src,
- fin->fin_dst, in, (u_32_t)dport);
+ fin->fin_dst, inb, (u_32_t)dport);
if (hm != NULL) {
in.s_addr = hm->hm_ndstip.s_addr;
move = 0;
@@ -3050,13 +3051,14 @@ ipf_nat_newrdr(fin, nat, ni)
return -1;
}
+ inb.s_addr = htonl(in.s_addr);
nat->nat_ndstaddr = htonl(in.s_addr);
nat->nat_odstip = fin->fin_dst;
nat->nat_nsrcip = fin->fin_src;
nat->nat_osrcip = fin->fin_src;
if ((nat->nat_hm == NULL) && ((np->in_flags & IPN_STICKY) != 0))
nat->nat_hm = ipf_nat_hostmap(softn, np, fin->fin_src,
- fin->fin_dst, in, (u_32_t)dport);
+ fin->fin_dst, inb, (u_32_t)dport);
if (flags & IPN_TCPUDP) {
nat->nat_odport = dport;
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 37c79a5..abbc9b5 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -208,6 +208,7 @@ static device_method_t acpi_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_hint_device_unit, acpi_hint_device_unit),
+ DEVMETHOD(bus_get_domain, acpi_get_domain),
/* ACPI bus */
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
@@ -794,6 +795,7 @@ acpi_print_child(device_t bus, device_t child)
retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld");
if (device_get_flags(child))
retval += printf(" flags %#x", device_get_flags(child));
+ retval += bus_print_child_domain(bus, child);
retval += bus_print_child_footer(bus, child);
return (retval);
@@ -1067,6 +1069,35 @@ acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
}
/*
+ * Fech the NUMA domain for the given device.
+ *
+ * If a device has a _PXM method, map that to a NUMA domain.
+ *
+ * If none is found, then it'll call the parent method.
+ * If there's no domain, return ENOENT.
+ */
+int
+acpi_get_domain(device_t dev, device_t child, int *domain)
+{
+#if MAXMEMDOM > 1
+ ACPI_HANDLE h;
+ int d, pxm;
+
+ h = acpi_get_handle(child);
+ if ((h != NULL) &&
+ ACPI_SUCCESS(acpi_GetInteger(h, "_PXM", &pxm))) {
+ d = acpi_map_pxm_to_vm_domainid(pxm);
+ if (d < 0)
+ return (ENOENT);
+ *domain = d;
+ return (0);
+ }
+#endif
+ /* No _PXM node; go up a level */
+ return (bus_generic_get_domain(dev, child, domain));
+}
+
+/*
* Pre-allocate/manage all memory and IO resources. Since rman can't handle
* duplicates, we merge any in the sysresource attach routine.
*/
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index d94b6f0..3d07205 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -94,6 +94,7 @@ static device_method_t acpi_pci_methods[] = {
DEVMETHOD(bus_write_ivar, acpi_pci_write_ivar),
DEVMETHOD(bus_child_location_str, acpi_pci_child_location_str_method),
DEVMETHOD(bus_get_dma_tag, acpi_pci_get_dma_tag),
+ DEVMETHOD(bus_get_domain, acpi_get_domain),
/* PCI interface */
DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method),
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 1bc7ee0..a314098 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -489,5 +489,16 @@ ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj);
SYSCTL_DECL(_debug_acpi);
+/*
+ * Map a PXM to a VM domain.
+ *
+ * Returns the VM domain ID if found, or -1 if not found / invalid.
+ */
+#if MAXMEMDOM > 1
+extern int acpi_map_pxm_to_vm_domainid(int pxm);
+#endif
+
+extern int acpi_get_domain(device_t dev, device_t child, int *domain);
+
#endif /* _KERNEL */
#endif /* !_ACPIVAR_H_ */
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 69fa76b..ab4944a 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -360,7 +360,7 @@ ahci_setup_interrupt(device_t dev)
for (i = 0; i < ctlr->numirqs; i++) {
ctlr->irqs[i].ctlr = ctlr;
ctlr->irqs[i].r_irq_rid = i + (ctlr->msi ? 1 : 0);
- if (ctlr->channels == 1 && !ctlr->ccc)
+ if (ctlr->channels == 1 && !ctlr->ccc && ctlr->msi)
ctlr->irqs[i].mode = AHCI_IRQ_MODE_ONE;
else if (ctlr->numirqs == 1 || i >= ctlr->channels ||
(ctlr->ccc && i == ctlr->cccv))
diff --git a/sys/dev/alc/if_alc.c b/sys/dev/alc/if_alc.c
index ecb3b47..6fed142 100644
--- a/sys/dev/alc/if_alc.c
+++ b/sys/dev/alc/if_alc.c
@@ -111,17 +111,31 @@ static struct alc_ident alc_ident_table[] = {
"Atheros AR8152 v1.1 PCIe Fast Ethernet" },
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8152_B2, 6 * 1024,
"Atheros AR8152 v2.0 PCIe Fast Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8161, 9 * 1024,
+ "Atheros AR8161 PCIe Gigabit Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8162, 9 * 1024,
+ "Atheros AR8161 PCIe Fast Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8171, 9 * 1024,
+ "Atheros AR8161 PCIe Gigabit Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8172, 9 * 1024,
+ "Atheros AR8161 PCIe Fast Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_E2200, 9 * 1024,
+ "Killer E2200 Gigabit Ethernet" },
{ 0, 0, 0, NULL}
};
-static void alc_aspm(struct alc_softc *, int);
+static void alc_aspm(struct alc_softc *, int, int);
+static void alc_aspm_813x(struct alc_softc *, int);
+static void alc_aspm_816x(struct alc_softc *, int);
static int alc_attach(device_t);
static int alc_check_boundary(struct alc_softc *);
+static void alc_config_msi(struct alc_softc *);
static int alc_detach(device_t);
static void alc_disable_l0s_l1(struct alc_softc *);
static int alc_dma_alloc(struct alc_softc *);
static void alc_dma_free(struct alc_softc *);
static void alc_dmamap_cb(void *, bus_dma_segment_t *, int, int);
+static void alc_dsp_fixup(struct alc_softc *, int);
static int alc_encap(struct alc_softc *, struct mbuf **);
static struct alc_ident *
alc_find_ident(device_t);
@@ -130,6 +144,9 @@ static struct mbuf *
alc_fixup_rx(struct ifnet *, struct mbuf *);
#endif
static void alc_get_macaddr(struct alc_softc *);
+static void alc_get_macaddr_813x(struct alc_softc *);
+static void alc_get_macaddr_816x(struct alc_softc *);
+static void alc_get_macaddr_par(struct alc_softc *);
static void alc_init(void *);
static void alc_init_cmb(struct alc_softc *);
static void alc_init_locked(struct alc_softc *);
@@ -141,14 +158,26 @@ static void alc_int_task(void *, int);
static int alc_intr(void *);
static int alc_ioctl(struct ifnet *, u_long, caddr_t);
static void alc_mac_config(struct alc_softc *);
+static uint32_t alc_mii_readreg_813x(struct alc_softc *, int, int);
+static uint32_t alc_mii_readreg_816x(struct alc_softc *, int, int);
+static uint32_t alc_mii_writereg_813x(struct alc_softc *, int, int, int);
+static uint32_t alc_mii_writereg_816x(struct alc_softc *, int, int, int);
static int alc_miibus_readreg(device_t, int, int);
static void alc_miibus_statchg(device_t);
static int alc_miibus_writereg(device_t, int, int, int);
+static uint32_t alc_miidbg_readreg(struct alc_softc *, int);
+static uint32_t alc_miidbg_writereg(struct alc_softc *, int, int);
+static uint32_t alc_miiext_readreg(struct alc_softc *, int, int);
+static uint32_t alc_miiext_writereg(struct alc_softc *, int, int, int);
static int alc_mediachange(struct ifnet *);
+static int alc_mediachange_locked(struct alc_softc *);
static void alc_mediastatus(struct ifnet *, struct ifmediareq *);
static int alc_newbuf(struct alc_softc *, struct alc_rxdesc *);
+static void alc_osc_reset(struct alc_softc *);
static void alc_phy_down(struct alc_softc *);
static void alc_phy_reset(struct alc_softc *);
+static void alc_phy_reset_813x(struct alc_softc *);
+static void alc_phy_reset_816x(struct alc_softc *);
static int alc_probe(device_t);
static void alc_reset(struct alc_softc *);
static int alc_resume(device_t);
@@ -158,6 +187,8 @@ static void alc_rxfilter(struct alc_softc *);
static void alc_rxvlan(struct alc_softc *);
static void alc_setlinkspeed(struct alc_softc *);
static void alc_setwol(struct alc_softc *);
+static void alc_setwol_813x(struct alc_softc *);
+static void alc_setwol_816x(struct alc_softc *);
static int alc_shutdown(device_t);
static void alc_start(struct ifnet *);
static void alc_start_locked(struct ifnet *);
@@ -230,10 +261,21 @@ static int
alc_miibus_readreg(device_t dev, int phy, int reg)
{
struct alc_softc *sc;
- uint32_t v;
- int i;
+ int v;
sc = device_get_softc(dev);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ v = alc_mii_readreg_816x(sc, phy, reg);
+ else
+ v = alc_mii_readreg_813x(sc, phy, reg);
+ return (v);
+}
+
+static uint32_t
+alc_mii_readreg_813x(struct alc_softc *sc, int phy, int reg)
+{
+ uint32_t v;
+ int i;
/*
* For AR8132 fast ethernet controller, do not report 1000baseT
@@ -262,14 +304,52 @@ alc_miibus_readreg(device_t dev, int phy, int reg)
return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
}
+static uint32_t
+alc_mii_readreg_816x(struct alc_softc *sc, int phy, int reg)
+{
+ uint32_t clk, v;
+ int i;
+
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
+ MDIO_SUP_PREAMBLE | clk | MDIO_REG_ADDR(reg));
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ device_printf(sc->alc_dev, "phy read timeout : %d\n", reg);
+ return (0);
+ }
+
+ return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
+}
+
static int
alc_miibus_writereg(device_t dev, int phy, int reg, int val)
{
struct alc_softc *sc;
- uint32_t v;
- int i;
+ int v;
sc = device_get_softc(dev);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ v = alc_mii_writereg_816x(sc, phy, reg, val);
+ else
+ v = alc_mii_writereg_813x(sc, phy, reg, val);
+ return (v);
+}
+
+static uint32_t
+alc_mii_writereg_813x(struct alc_softc *sc, int phy, int reg, int val)
+{
+ uint32_t v;
+ int i;
CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
(val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT |
@@ -287,6 +367,32 @@ alc_miibus_writereg(device_t dev, int phy, int reg, int val)
return (0);
}
+static uint32_t
+alc_mii_writereg_816x(struct alc_softc *sc, int phy, int reg, int val)
+{
+ uint32_t clk, v;
+ int i;
+
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
+ ((val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT) | MDIO_REG_ADDR(reg) |
+ MDIO_SUP_PREAMBLE | clk);
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0)
+ device_printf(sc->alc_dev, "phy write timeout : %d\n", reg);
+
+ return (0);
+}
+
static void
alc_miibus_statchg(device_t dev)
{
@@ -319,7 +425,6 @@ alc_miibus_statchg(device_t dev)
break;
}
}
- alc_stop_queue(sc);
/* Stop Rx/Tx MACs. */
alc_stop_mac(sc);
@@ -331,7 +436,159 @@ alc_miibus_statchg(device_t dev)
reg = CSR_READ_4(sc, ALC_MAC_CFG);
reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
- alc_aspm(sc, IFM_SUBTYPE(mii->mii_media_active));
+ }
+ alc_aspm(sc, 0, IFM_SUBTYPE(mii->mii_media_active));
+ alc_dsp_fixup(sc, IFM_SUBTYPE(mii->mii_media_active));
+}
+
+static uint32_t
+alc_miidbg_readreg(struct alc_softc *sc, int reg)
+{
+
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_ADDR,
+ reg);
+ return (alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA));
+}
+
+static uint32_t
+alc_miidbg_writereg(struct alc_softc *sc, int reg, int val)
+{
+
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_ADDR,
+ reg);
+ return (alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, val));
+}
+
+static uint32_t
+alc_miiext_readreg(struct alc_softc *sc, int devaddr, int reg)
+{
+ uint32_t clk, v;
+ int i;
+
+ CSR_WRITE_4(sc, ALC_EXT_MDIO, EXT_MDIO_REG(reg) |
+ EXT_MDIO_DEVADDR(devaddr));
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
+ MDIO_SUP_PREAMBLE | clk | MDIO_MODE_EXT);
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ device_printf(sc->alc_dev, "phy ext read timeout : %d, %d\n",
+ devaddr, reg);
+ return (0);
+ }
+
+ return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
+}
+
+static uint32_t
+alc_miiext_writereg(struct alc_softc *sc, int devaddr, int reg, int val)
+{
+ uint32_t clk, v;
+ int i;
+
+ CSR_WRITE_4(sc, ALC_EXT_MDIO, EXT_MDIO_REG(reg) |
+ EXT_MDIO_DEVADDR(devaddr));
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
+ ((val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT) |
+ MDIO_SUP_PREAMBLE | clk | MDIO_MODE_EXT);
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0)
+ device_printf(sc->alc_dev, "phy ext write timeout : %d, %d\n",
+ devaddr, reg);
+
+ return (0);
+}
+
+static void
+alc_dsp_fixup(struct alc_softc *sc, int media)
+{
+ uint16_t agc, len, val;
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ return;
+ if (AR816X_REV(sc->alc_rev) >= AR816X_REV_C0)
+ return;
+
+ /*
+ * Vendor PHY magic.
+ * 1000BT/AZ, wrong cable length
+ */
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0) {
+ len = alc_miiext_readreg(sc, MII_EXT_PCS, MII_EXT_CLDCTL6);
+ len = (len >> EXT_CLDCTL6_CAB_LEN_SHIFT) &
+ EXT_CLDCTL6_CAB_LEN_MASK;
+ agc = alc_miidbg_readreg(sc, MII_DBG_AGC);
+ agc = (agc >> DBG_AGC_2_VGA_SHIFT) & DBG_AGC_2_VGA_MASK;
+ if ((media == IFM_1000_T && len > EXT_CLDCTL6_CAB_LEN_SHORT1G &&
+ agc > DBG_AGC_LONG1G_LIMT) ||
+ (media == IFM_100_TX && len > DBG_AGC_LONG100M_LIMT &&
+ agc > DBG_AGC_LONG1G_LIMT)) {
+ alc_miidbg_writereg(sc, MII_DBG_AZ_ANADECT,
+ DBG_AZ_ANADECT_LONG);
+ val = alc_miiext_readreg(sc, MII_EXT_ANEG,
+ MII_EXT_ANEG_AFE);
+ val |= ANEG_AFEE_10BT_100M_TH;
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE,
+ val);
+ } else {
+ alc_miidbg_writereg(sc, MII_DBG_AZ_ANADECT,
+ DBG_AZ_ANADECT_DEFAULT);
+ val = alc_miiext_readreg(sc, MII_EXT_ANEG,
+ MII_EXT_ANEG_AFE);
+ val &= ~ANEG_AFEE_10BT_100M_TH;
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE,
+ val);
+ }
+ if ((sc->alc_flags & ALC_FLAG_LINK_WAR) != 0 &&
+ AR816X_REV(sc->alc_rev) == AR816X_REV_B0) {
+ if (media == IFM_1000_T) {
+ /*
+ * Giga link threshold, raise the tolerance of
+ * noise 50%.
+ */
+ val = alc_miidbg_readreg(sc, MII_DBG_MSE20DB);
+ val &= ~DBG_MSE20DB_TH_MASK;
+ val |= (DBG_MSE20DB_TH_HI <<
+ DBG_MSE20DB_TH_SHIFT);
+ alc_miidbg_writereg(sc, MII_DBG_MSE20DB, val);
+ } else if (media == IFM_100_TX)
+ alc_miidbg_writereg(sc, MII_DBG_MSE16DB,
+ DBG_MSE16DB_UP);
+ }
+ } else {
+ val = alc_miiext_readreg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE);
+ val &= ~ANEG_AFEE_10BT_100M_TH;
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE, val);
+ if ((sc->alc_flags & ALC_FLAG_LINK_WAR) != 0 &&
+ AR816X_REV(sc->alc_rev) == AR816X_REV_B0) {
+ alc_miidbg_writereg(sc, MII_DBG_MSE16DB,
+ DBG_MSE16DB_DOWN);
+ val = alc_miidbg_readreg(sc, MII_DBG_MSE20DB);
+ val &= ~DBG_MSE20DB_TH_MASK;
+ val |= (DBG_MSE20DB_TH_DEFAULT << DBG_MSE20DB_TH_SHIFT);
+ alc_miidbg_writereg(sc, MII_DBG_MSE20DB, val);
+ }
}
}
@@ -359,17 +616,29 @@ static int
alc_mediachange(struct ifnet *ifp)
{
struct alc_softc *sc;
- struct mii_data *mii;
- struct mii_softc *miisc;
int error;
sc = ifp->if_softc;
ALC_LOCK(sc);
+ error = alc_mediachange_locked(sc);
+ ALC_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+alc_mediachange_locked(struct alc_softc *sc)
+{
+ struct mii_data *mii;
+ struct mii_softc *miisc;
+ int error;
+
+ ALC_LOCK_ASSERT(sc);
+
mii = device_get_softc(sc->alc_miibus);
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
PHY_RESET(miisc);
error = mii_mediachg(mii);
- ALC_UNLOCK(sc);
return (error);
}
@@ -407,7 +676,17 @@ alc_probe(device_t dev)
static void
alc_get_macaddr(struct alc_softc *sc)
{
- uint32_t ea[2], opt;
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ alc_get_macaddr_816x(sc);
+ else
+ alc_get_macaddr_813x(sc);
+}
+
+static void
+alc_get_macaddr_813x(struct alc_softc *sc)
+{
+ uint32_t opt;
uint16_t val;
int eeprom, i;
@@ -502,6 +781,73 @@ alc_get_macaddr(struct alc_softc *sc)
}
}
+ alc_get_macaddr_par(sc);
+}
+
+static void
+alc_get_macaddr_816x(struct alc_softc *sc)
+{
+ uint32_t reg;
+ int i, reloaded;
+
+ reloaded = 0;
+ /* Try to reload station address via TWSI. */
+ for (i = 100; i > 0; i--) {
+ reg = CSR_READ_4(sc, ALC_SLD);
+ if ((reg & (SLD_PROGRESS | SLD_START)) == 0)
+ break;
+ DELAY(1000);
+ }
+ if (i != 0) {
+ CSR_WRITE_4(sc, ALC_SLD, reg | SLD_START);
+ for (i = 100; i > 0; i--) {
+ DELAY(1000);
+ reg = CSR_READ_4(sc, ALC_SLD);
+ if ((reg & SLD_START) == 0)
+ break;
+ }
+ if (i != 0)
+ reloaded++;
+ else if (bootverbose)
+ device_printf(sc->alc_dev,
+ "reloading station address via TWSI timed out!\n");
+ }
+
+ /* Try to reload station address from EEPROM or FLASH. */
+ if (reloaded == 0) {
+ reg = CSR_READ_4(sc, ALC_EEPROM_LD);
+ if ((reg & (EEPROM_LD_EEPROM_EXIST |
+ EEPROM_LD_FLASH_EXIST)) != 0) {
+ for (i = 100; i > 0; i--) {
+ reg = CSR_READ_4(sc, ALC_EEPROM_LD);
+ if ((reg & (EEPROM_LD_PROGRESS |
+ EEPROM_LD_START)) == 0)
+ break;
+ DELAY(1000);
+ }
+ if (i != 0) {
+ CSR_WRITE_4(sc, ALC_EEPROM_LD, reg |
+ EEPROM_LD_START);
+ for (i = 100; i > 0; i--) {
+ DELAY(1000);
+ reg = CSR_READ_4(sc, ALC_EEPROM_LD);
+ if ((reg & EEPROM_LD_START) == 0)
+ break;
+ }
+ } else if (bootverbose)
+ device_printf(sc->alc_dev,
+ "reloading EEPROM/FLASH timed out!\n");
+ }
+ }
+
+ alc_get_macaddr_par(sc);
+}
+
+static void
+alc_get_macaddr_par(struct alc_softc *sc)
+{
+ uint32_t ea[2];
+
ea[0] = CSR_READ_4(sc, ALC_PAR0);
ea[1] = CSR_READ_4(sc, ALC_PAR1);
sc->alc_eaddr[0] = (ea[1] >> 8) & 0xFF;
@@ -517,19 +863,31 @@ alc_disable_l0s_l1(struct alc_softc *sc)
{
uint32_t pmcfg;
- /* Another magic from vendor. */
- pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
- pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_CLK_SWH_L1 |
- PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB | PM_CFG_MAC_ASPM_CHK |
- PM_CFG_SERDES_PD_EX_L1);
- pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB | PM_CFG_SERDES_PLL_L1_ENB |
- PM_CFG_SERDES_L1_ENB;
- CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ /* Another magic from vendor. */
+ pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
+ pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_CLK_SWH_L1 |
+ PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB |
+ PM_CFG_MAC_ASPM_CHK | PM_CFG_SERDES_PD_EX_L1);
+ pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB |
+ PM_CFG_SERDES_PLL_L1_ENB | PM_CFG_SERDES_L1_ENB;
+ CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+ }
}
static void
alc_phy_reset(struct alc_softc *sc)
{
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ alc_phy_reset_816x(sc);
+ else
+ alc_phy_reset_813x(sc);
+}
+
+static void
+alc_phy_reset_813x(struct alc_softc *sc)
+{
uint16_t data;
/* Reset magic from Linux. */
@@ -642,12 +1000,101 @@ alc_phy_reset(struct alc_softc *sc)
}
static void
+alc_phy_reset_816x(struct alc_softc *sc)
+{
+ uint32_t val;
+
+ val = CSR_READ_4(sc, ALC_GPHY_CFG);
+ val &= ~(GPHY_CFG_EXT_RESET | GPHY_CFG_LED_MODE |
+ GPHY_CFG_GATE_25M_ENB | GPHY_CFG_PHY_IDDQ | GPHY_CFG_PHY_PLL_ON |
+ GPHY_CFG_PWDOWN_HW | GPHY_CFG_100AB_ENB);
+ val |= GPHY_CFG_SEL_ANA_RESET;
+#ifdef notyet
+ val |= GPHY_CFG_HIB_PULSE | GPHY_CFG_HIB_EN | GPHY_CFG_SEL_ANA_RESET;
+#else
+ /* Disable PHY hibernation. */
+ val &= ~(GPHY_CFG_HIB_PULSE | GPHY_CFG_HIB_EN);
+#endif
+ CSR_WRITE_4(sc, ALC_GPHY_CFG, val);
+ DELAY(10);
+ CSR_WRITE_4(sc, ALC_GPHY_CFG, val | GPHY_CFG_EXT_RESET);
+ DELAY(800);
+
+ /* Vendor PHY magic. */
+#ifdef notyet
+ alc_miidbg_writereg(sc, MII_DBG_LEGCYPS, DBG_LEGCYPS_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_SYSMODCTL, DBG_SYSMODCTL_DEFAULT);
+ alc_miiext_writereg(sc, MII_EXT_PCS, MII_EXT_VDRVBIAS,
+ EXT_VDRVBIAS_DEFAULT);
+#else
+ /* Disable PHY hibernation. */
+ alc_miidbg_writereg(sc, MII_DBG_LEGCYPS,
+ DBG_LEGCYPS_DEFAULT & ~DBG_LEGCYPS_ENB);
+ alc_miidbg_writereg(sc, MII_DBG_HIBNEG,
+ DBG_HIBNEG_DEFAULT & ~(DBG_HIBNEG_PSHIB_EN | DBG_HIBNEG_HIB_PULSE));
+ alc_miidbg_writereg(sc, MII_DBG_GREENCFG, DBG_GREENCFG_DEFAULT);
+#endif
+
+ /* XXX Disable EEE. */
+ val = CSR_READ_4(sc, ALC_LPI_CTL);
+ val &= ~LPI_CTL_ENB;
+ CSR_WRITE_4(sc, ALC_LPI_CTL, val);
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_LOCAL_EEEADV, 0);
+
+ /* PHY power saving. */
+ alc_miidbg_writereg(sc, MII_DBG_TST10BTCFG, DBG_TST10BTCFG_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_SRDSYSMOD, DBG_SRDSYSMOD_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_TST100BTCFG, DBG_TST100BTCFG_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_ANACTL, DBG_ANACTL_DEFAULT);
+ val = alc_miidbg_readreg(sc, MII_DBG_GREENCFG2);
+ val &= ~DBG_GREENCFG2_GATE_DFSE_EN;
+ alc_miidbg_writereg(sc, MII_DBG_GREENCFG2, val);
+
+ /* RTL8139C, 120m issue. */
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_NLP78,
+ ANEG_NLP78_120M_DEFAULT);
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_S3DIG10,
+ ANEG_S3DIG10_DEFAULT);
+
+ if ((sc->alc_flags & ALC_FLAG_LINK_WAR) != 0) {
+ /* Turn off half amplitude. */
+ val = alc_miiext_readreg(sc, MII_EXT_PCS, MII_EXT_CLDCTL3);
+ val |= EXT_CLDCTL3_BP_CABLE1TH_DET_GT;
+ alc_miiext_writereg(sc, MII_EXT_PCS, MII_EXT_CLDCTL3, val);
+ /* Turn off Green feature. */
+ val = alc_miidbg_readreg(sc, MII_DBG_GREENCFG2);
+ val |= DBG_GREENCFG2_BP_GREEN;
+ alc_miidbg_writereg(sc, MII_DBG_GREENCFG2, val);
+ /* Turn off half bias. */
+ val = alc_miiext_readreg(sc, MII_EXT_PCS, MII_EXT_CLDCTL5);
+ val |= EXT_CLDCTL5_BP_VD_HLFBIAS;
+ alc_miiext_writereg(sc, MII_EXT_PCS, MII_EXT_CLDCTL5, val);
+ }
+}
+
+static void
alc_phy_down(struct alc_softc *sc)
{
+ uint32_t gphy;
switch (sc->alc_ident->deviceid) {
+ case DEVICEID_ATHEROS_AR8161:
+ case DEVICEID_ATHEROS_E2200:
+ case DEVICEID_ATHEROS_AR8162:
+ case DEVICEID_ATHEROS_AR8171:
+ case DEVICEID_ATHEROS_AR8172:
+ gphy = CSR_READ_4(sc, ALC_GPHY_CFG);
+ gphy &= ~(GPHY_CFG_EXT_RESET | GPHY_CFG_LED_MODE |
+ GPHY_CFG_100AB_ENB | GPHY_CFG_PHY_PLL_ON);
+ gphy |= GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
+ GPHY_CFG_SEL_ANA_RESET;
+ gphy |= GPHY_CFG_PHY_IDDQ | GPHY_CFG_PWDOWN_HW;
+ CSR_WRITE_4(sc, ALC_GPHY_CFG, gphy);
+ break;
case DEVICEID_ATHEROS_AR8151:
case DEVICEID_ATHEROS_AR8151_V2:
+ case DEVICEID_ATHEROS_AR8152_B:
+ case DEVICEID_ATHEROS_AR8152_B2:
/*
* GPHY power down caused more problems on AR8151 v2.0.
* When driver is reloaded after GPHY power down,
@@ -673,12 +1120,23 @@ alc_phy_down(struct alc_softc *sc)
}
static void
-alc_aspm(struct alc_softc *sc, int media)
+alc_aspm(struct alc_softc *sc, int init, int media)
+{
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ alc_aspm_816x(sc, init);
+ else
+ alc_aspm_813x(sc, media);
+}
+
+static void
+alc_aspm_813x(struct alc_softc *sc, int media)
{
uint32_t pmcfg;
uint16_t linkcfg;
- ALC_LOCK_ASSERT(sc);
+ if ((sc->alc_flags & ALC_FLAG_LINK) == 0)
+ return;
pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
if ((sc->alc_flags & (ALC_FLAG_APS | ALC_FLAG_PCIE)) ==
@@ -759,71 +1217,61 @@ alc_aspm(struct alc_softc *sc, int media)
CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
}
-static int
-alc_attach(device_t dev)
+static void
+alc_aspm_816x(struct alc_softc *sc, int init)
{
- struct alc_softc *sc;
- struct ifnet *ifp;
- char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
- uint16_t burst;
- int base, error, i, msic, msixc, state;
- uint32_t cap, ctl, val;
-
- error = 0;
- sc = device_get_softc(dev);
- sc->alc_dev = dev;
-
- mtx_init(&sc->alc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF);
- callout_init_mtx(&sc->alc_tick_ch, &sc->alc_mtx, 0);
- TASK_INIT(&sc->alc_int_task, 0, alc_int_task, sc);
- sc->alc_ident = alc_find_ident(dev);
+ uint32_t pmcfg;
- /* Map the device. */
- pci_enable_busmaster(dev);
- sc->alc_res_spec = alc_res_spec_mem;
- sc->alc_irq_spec = alc_irq_spec_legacy;
- error = bus_alloc_resources(dev, sc->alc_res_spec, sc->alc_res);
- if (error != 0) {
- device_printf(dev, "cannot allocate memory resources.\n");
- goto fail;
+ pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
+ pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_816X_MASK;
+ pmcfg |= PM_CFG_L1_ENTRY_TIMER_816X_DEFAULT;
+ pmcfg &= ~PM_CFG_PM_REQ_TIMER_MASK;
+ pmcfg |= PM_CFG_PM_REQ_TIMER_816X_DEFAULT;
+ pmcfg &= ~PM_CFG_LCKDET_TIMER_MASK;
+ pmcfg |= PM_CFG_LCKDET_TIMER_DEFAULT;
+ pmcfg |= PM_CFG_SERDES_PD_EX_L1 | PM_CFG_CLK_SWH_L1 | PM_CFG_PCIE_RECV;
+ pmcfg &= ~(PM_CFG_RX_L1_AFTER_L0S | PM_CFG_TX_L1_AFTER_L0S |
+ PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB |
+ PM_CFG_SERDES_L1_ENB | PM_CFG_SERDES_PLL_L1_ENB |
+ PM_CFG_SERDES_BUDS_RX_L1_ENB | PM_CFG_SA_DLY_ENB |
+ PM_CFG_MAC_ASPM_CHK | PM_CFG_HOTRST);
+ if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1 &&
+ (sc->alc_rev & 0x01) != 0)
+ pmcfg |= PM_CFG_SERDES_L1_ENB | PM_CFG_SERDES_PLL_L1_ENB;
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0) {
+ /* Link up, enable both L0s, L1s. */
+ pmcfg |= PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB |
+ PM_CFG_MAC_ASPM_CHK;
+ } else {
+ if (init != 0)
+ pmcfg |= PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB |
+ PM_CFG_MAC_ASPM_CHK;
+ else if ((sc->alc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ pmcfg |= PM_CFG_ASPM_L1_ENB | PM_CFG_MAC_ASPM_CHK;
}
+ CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+}
- /* Set PHY address. */
- sc->alc_phyaddr = ALC_PHY_ADDR;
+static void
+alc_init_pcie(struct alc_softc *sc)
+{
+ const char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
+ uint32_t cap, ctl, val;
+ int state;
- /* Initialize DMA parameters. */
- sc->alc_dma_rd_burst = 0;
- sc->alc_dma_wr_burst = 0;
- sc->alc_rcb = DMA_CFG_RCB_64;
- if (pci_find_cap(dev, PCIY_EXPRESS, &base) == 0) {
- sc->alc_flags |= ALC_FLAG_PCIE;
- sc->alc_expcap = base;
- burst = CSR_READ_2(sc, base + PCIER_DEVICE_CTL);
- sc->alc_dma_rd_burst =
- (burst & PCIEM_CTL_MAX_READ_REQUEST) >> 12;
- sc->alc_dma_wr_burst = (burst & PCIEM_CTL_MAX_PAYLOAD) >> 5;
- if (bootverbose) {
- device_printf(dev, "Read request size : %u bytes.\n",
- alc_dma_burst[sc->alc_dma_rd_burst]);
- device_printf(dev, "TLP payload size : %u bytes.\n",
- alc_dma_burst[sc->alc_dma_wr_burst]);
- }
- if (alc_dma_burst[sc->alc_dma_rd_burst] > 1024)
- sc->alc_dma_rd_burst = 3;
- if (alc_dma_burst[sc->alc_dma_wr_burst] > 1024)
- sc->alc_dma_wr_burst = 3;
- /* Clear data link and flow-control protocol error. */
- val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);
- val &= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);
- CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
+ /* Clear data link and flow-control protocol error. */
+ val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);
+ val &= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);
+ CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC,
CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
PCIE_PHYMISC_FORCE_RCV_DET);
if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B &&
- pci_get_revid(dev) == ATHEROS_AR8152_B_V10) {
+ sc->alc_rev == ATHEROS_AR8152_B_V10) {
val = CSR_READ_4(sc, ALC_PCIE_PHYMISC2);
val &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK |
PCIE_PHYMISC2_SERDES_TH_MASK);
@@ -832,13 +1280,13 @@ alc_attach(device_t dev)
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC2, val);
}
/* Disable ASPM L0S and L1. */
- cap = CSR_READ_2(sc, base + PCIER_LINK_CAP);
+ cap = CSR_READ_2(sc, sc->alc_expcap + PCIER_LINK_CAP);
if ((cap & PCIEM_LINK_CAP_ASPM) != 0) {
- ctl = CSR_READ_2(sc, base + PCIER_LINK_CTL);
+ ctl = CSR_READ_2(sc, sc->alc_expcap + PCIER_LINK_CTL);
if ((ctl & PCIEM_LINK_CTL_RCB) != 0)
sc->alc_rcb = DMA_CFG_RCB_128;
if (bootverbose)
- device_printf(dev, "RCB %u bytes\n",
+ device_printf(sc->alc_dev, "RCB %u bytes\n",
sc->alc_rcb == DMA_CFG_RCB_64 ? 64 : 128);
state = ctl & PCIEM_LINK_CTL_ASPMC;
if (state & PCIEM_LINK_CTL_ASPMC_L0S)
@@ -855,13 +1303,91 @@ alc_attach(device_t dev)
device_printf(sc->alc_dev,
"no ASPM support\n");
}
+ } else {
+ val = CSR_READ_4(sc, ALC_PDLL_TRNS1);
+ val &= ~PDLL_TRNS1_D3PLLOFF_ENB;
+ CSR_WRITE_4(sc, ALC_PDLL_TRNS1, val);
+ val = CSR_READ_4(sc, ALC_MASTER_CFG);
+ if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1 &&
+ (sc->alc_rev & 0x01) != 0) {
+ if ((val & MASTER_WAKEN_25M) == 0 ||
+ (val & MASTER_CLK_SEL_DIS) == 0) {
+ val |= MASTER_WAKEN_25M | MASTER_CLK_SEL_DIS;
+ CSR_WRITE_4(sc, ALC_MASTER_CFG, val);
+ }
+ } else {
+ if ((val & MASTER_WAKEN_25M) == 0 ||
+ (val & MASTER_CLK_SEL_DIS) != 0) {
+ val |= MASTER_WAKEN_25M;
+ val &= ~MASTER_CLK_SEL_DIS;
+ CSR_WRITE_4(sc, ALC_MASTER_CFG, val);
+ }
+ }
}
+ alc_aspm(sc, 1, IFM_UNKNOWN);
+}
- /* Reset PHY. */
- alc_phy_reset(sc);
+static void
+alc_config_msi(struct alc_softc *sc)
+{
+ uint32_t ctl, mod;
- /* Reset the ethernet controller. */
- alc_reset(sc);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ /*
+ * It seems interrupt moderation is controlled by
+ * ALC_MSI_RETRANS_TIMER register if MSI/MSIX is active.
+ * Driver uses RX interrupt moderation parameter to
+ * program ALC_MSI_RETRANS_TIMER register.
+ */
+ ctl = CSR_READ_4(sc, ALC_MSI_RETRANS_TIMER);
+ ctl &= ~MSI_RETRANS_TIMER_MASK;
+ ctl &= ~MSI_RETRANS_MASK_SEL_LINE;
+ mod = ALC_USECS(sc->alc_int_rx_mod);
+ if (mod == 0)
+ mod = 1;
+ ctl |= mod;
+ if ((sc->alc_flags & ALC_FLAG_MSIX) != 0)
+ CSR_WRITE_4(sc, ALC_MSI_RETRANS_TIMER, ctl |
+ MSI_RETRANS_MASK_SEL_STD);
+ else if ((sc->alc_flags & ALC_FLAG_MSI) != 0)
+ CSR_WRITE_4(sc, ALC_MSI_RETRANS_TIMER, ctl |
+ MSI_RETRANS_MASK_SEL_LINE);
+ else
+ CSR_WRITE_4(sc, ALC_MSI_RETRANS_TIMER, 0);
+ }
+}
+
+static int
+alc_attach(device_t dev)
+{
+ struct alc_softc *sc;
+ struct ifnet *ifp;
+ int base, error, i, msic, msixc;
+ uint16_t burst;
+
+ error = 0;
+ sc = device_get_softc(dev);
+ sc->alc_dev = dev;
+ sc->alc_rev = pci_get_revid(dev);
+
+ mtx_init(&sc->alc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+ callout_init_mtx(&sc->alc_tick_ch, &sc->alc_mtx, 0);
+ TASK_INIT(&sc->alc_int_task, 0, alc_int_task, sc);
+ sc->alc_ident = alc_find_ident(dev);
+
+ /* Map the device. */
+ pci_enable_busmaster(dev);
+ sc->alc_res_spec = alc_res_spec_mem;
+ sc->alc_irq_spec = alc_irq_spec_legacy;
+ error = bus_alloc_resources(dev, sc->alc_res_spec, sc->alc_res);
+ if (error != 0) {
+ device_printf(dev, "cannot allocate memory resources.\n");
+ goto fail;
+ }
+
+ /* Set PHY address. */
+ sc->alc_phyaddr = ALC_PHY_ADDR;
/*
* One odd thing is AR8132 uses the same PHY hardware(F1
@@ -871,6 +1397,19 @@ alc_attach(device_t dev)
* shows the same PHY model/revision number of AR8131.
*/
switch (sc->alc_ident->deviceid) {
+ case DEVICEID_ATHEROS_AR8161:
+ if (pci_get_subvendor(dev) == VENDORID_ATHEROS &&
+ pci_get_subdevice(dev) == 0x0091 && sc->alc_rev == 0)
+ sc->alc_flags |= ALC_FLAG_LINK_WAR;
+ /* FALLTHROUGH */
+ case DEVICEID_ATHEROS_E2200:
+ case DEVICEID_ATHEROS_AR8171:
+ sc->alc_flags |= ALC_FLAG_AR816X_FAMILY;
+ break;
+ case DEVICEID_ATHEROS_AR8162:
+ case DEVICEID_ATHEROS_AR8172:
+ sc->alc_flags |= ALC_FLAG_FASTETHER | ALC_FLAG_AR816X_FAMILY;
+ break;
case DEVICEID_ATHEROS_AR8152_B:
case DEVICEID_ATHEROS_AR8152_B2:
sc->alc_flags |= ALC_FLAG_APS;
@@ -885,7 +1424,7 @@ alc_attach(device_t dev)
default:
break;
}
- sc->alc_flags |= ALC_FLAG_ASPM_MON | ALC_FLAG_JUMBO;
+ sc->alc_flags |= ALC_FLAG_JUMBO;
/*
* It seems that AR813x/AR815x has silicon bug for SMB. In
@@ -898,7 +1437,6 @@ alc_attach(device_t dev)
* Don't use Tx CMB. It is known to have silicon bug.
*/
sc->alc_flags |= ALC_FLAG_CMB_BUG;
- sc->alc_rev = pci_get_revid(dev);
sc->alc_chip_rev = CSR_READ_4(sc, ALC_MASTER_CFG) >>
MASTER_CHIP_REV_SHIFT;
if (bootverbose) {
@@ -906,11 +1444,45 @@ alc_attach(device_t dev)
sc->alc_rev);
device_printf(dev, "Chip id/revision : 0x%04x\n",
sc->alc_chip_rev);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ device_printf(dev, "AR816x revision : 0x%x\n",
+ AR816X_REV(sc->alc_rev));
}
device_printf(dev, "%u Tx FIFO, %u Rx FIFO\n",
CSR_READ_4(sc, ALC_SRAM_TX_FIFO_LEN) * 8,
CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN) * 8);
+ /* Initialize DMA parameters. */
+ sc->alc_dma_rd_burst = 0;
+ sc->alc_dma_wr_burst = 0;
+ sc->alc_rcb = DMA_CFG_RCB_64;
+ if (pci_find_cap(dev, PCIY_EXPRESS, &base) == 0) {
+ sc->alc_flags |= ALC_FLAG_PCIE;
+ sc->alc_expcap = base;
+ burst = CSR_READ_2(sc, base + PCIER_DEVICE_CTL);
+ sc->alc_dma_rd_burst =
+ (burst & PCIEM_CTL_MAX_READ_REQUEST) >> 12;
+ sc->alc_dma_wr_burst = (burst & PCIEM_CTL_MAX_PAYLOAD) >> 5;
+ if (bootverbose) {
+ device_printf(dev, "Read request size : %u bytes.\n",
+ alc_dma_burst[sc->alc_dma_rd_burst]);
+ device_printf(dev, "TLP payload size : %u bytes.\n",
+ alc_dma_burst[sc->alc_dma_wr_burst]);
+ }
+ if (alc_dma_burst[sc->alc_dma_rd_burst] > 1024)
+ sc->alc_dma_rd_burst = 3;
+ if (alc_dma_burst[sc->alc_dma_wr_burst] > 1024)
+ sc->alc_dma_wr_burst = 3;
+ alc_init_pcie(sc);
+ }
+
+ /* Reset PHY. */
+ alc_phy_reset(sc);
+
+ /* Reset the ethernet controller. */
+ alc_stop_mac(sc);
+ alc_reset(sc);
+
/* Allocate IRQ resources. */
msixc = pci_msix_count(dev);
msic = pci_msi_count(dev);
@@ -918,11 +1490,20 @@ alc_attach(device_t dev)
device_printf(dev, "MSIX count : %d\n", msixc);
device_printf(dev, "MSI count : %d\n", msic);
}
- /* Prefer MSIX over MSI. */
+ if (msixc > 1)
+ msixc = 1;
+ if (msic > 1)
+ msic = 1;
+ /*
+ * Prefer MSIX over MSI.
+ * AR816x controller has a silicon bug that MSI interrupt
+ * does not assert if PCIM_CMD_INTxDIS bit of command
+ * register is set. pci(4) was taught to handle that case.
+ */
if (msix_disable == 0 || msi_disable == 0) {
- if (msix_disable == 0 && msixc == ALC_MSIX_MESSAGES &&
+ if (msix_disable == 0 && msixc > 0 &&
pci_alloc_msix(dev, &msixc) == 0) {
- if (msic == ALC_MSIX_MESSAGES) {
+ if (msic == 1) {
device_printf(dev,
"Using %d MSIX message(s).\n", msixc);
sc->alc_flags |= ALC_FLAG_MSIX;
@@ -931,9 +1512,8 @@ alc_attach(device_t dev)
pci_release_msi(dev);
}
if (msi_disable == 0 && (sc->alc_flags & ALC_FLAG_MSIX) == 0 &&
- msic == ALC_MSI_MESSAGES &&
- pci_alloc_msi(dev, &msic) == 0) {
- if (msic == ALC_MSI_MESSAGES) {
+ msic > 0 && pci_alloc_msi(dev, &msic) == 0) {
+ if (msic == 1) {
device_printf(dev,
"Using %d MSI message(s).\n", msic);
sc->alc_flags |= ALC_FLAG_MSI;
@@ -1007,9 +1587,13 @@ alc_attach(device_t dev)
* sample boards. To safety, don't enable Tx checksum offloading
* by default but give chance to users to toggle it if they know
* their controllers work without problems.
+ * Fortunately, Tx checksum offloading for AR816x family
+ * seems to work.
*/
- ifp->if_capenable &= ~IFCAP_TXCSUM;
- ifp->if_hwassist &= ~ALC_CSUM_FEATURES;
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ ifp->if_capenable &= ~IFCAP_TXCSUM;
+ ifp->if_hwassist &= ~ALC_CSUM_FEATURES;
+ }
/* Tell the upper layer(s) we support long frames. */
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
@@ -1026,6 +1610,7 @@ alc_attach(device_t dev)
taskqueue_start_threads(&sc->alc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(sc->alc_dev));
+ alc_config_msi(sc);
if ((sc->alc_flags & ALC_FLAG_MSIX) != 0)
msic = ALC_MSIX_MESSAGES;
else if ((sc->alc_flags & ALC_FLAG_MSI) != 0)
@@ -1287,8 +1872,6 @@ alc_sysctl_node(struct alc_softc *sc)
&stats->tx_late_colls, "Late collisions");
ALC_SYSCTL_STAT_ADD32(ctx, child, "excess_colls",
&stats->tx_excess_colls, "Excessive collisions");
- ALC_SYSCTL_STAT_ADD32(ctx, child, "abort",
- &stats->tx_abort, "Aborted frames due to Excessive collisions");
ALC_SYSCTL_STAT_ADD32(ctx, child, "underruns",
&stats->tx_underrun, "FIFO underruns");
ALC_SYSCTL_STAT_ADD32(ctx, child, "desc_underruns",
@@ -1600,7 +2183,7 @@ again:
/*
* Create Tx buffer parent tag.
- * AR813x/AR815x allows 64bit DMA addressing of Tx/Rx buffers
+ * AR81[3567]x allows 64bit DMA addressing of Tx/Rx buffers
* so it needs separate parent DMA tag as parent DMA address
* space could be restricted to be within 32bit address space
* by 4GB boundary crossing.
@@ -1902,6 +2485,16 @@ alc_setlinkspeed(struct alc_softc *sc)
static void
alc_setwol(struct alc_softc *sc)
{
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ alc_setwol_816x(sc);
+ else
+ alc_setwol_813x(sc);
+}
+
+static void
+alc_setwol_813x(struct alc_softc *sc)
+{
struct ifnet *ifp;
uint32_t reg, pmcs;
uint16_t pmstat;
@@ -1962,6 +2555,72 @@ alc_setwol(struct alc_softc *sc)
sc->alc_pmcap + PCIR_POWER_STATUS, pmstat, 2);
}
+static void
+alc_setwol_816x(struct alc_softc *sc)
+{
+ struct ifnet *ifp;
+ uint32_t gphy, mac, master, pmcs, reg;
+ uint16_t pmstat;
+
+ ALC_LOCK_ASSERT(sc);
+
+ ifp = sc->alc_ifp;
+ master = CSR_READ_4(sc, ALC_MASTER_CFG);
+ master &= ~MASTER_CLK_SEL_DIS;
+ gphy = CSR_READ_4(sc, ALC_GPHY_CFG);
+ gphy &= ~(GPHY_CFG_EXT_RESET | GPHY_CFG_LED_MODE | GPHY_CFG_100AB_ENB |
+ GPHY_CFG_PHY_PLL_ON);
+ gphy |= GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE | GPHY_CFG_SEL_ANA_RESET;
+ if ((sc->alc_flags & ALC_FLAG_PM) == 0) {
+ CSR_WRITE_4(sc, ALC_WOL_CFG, 0);
+ gphy |= GPHY_CFG_PHY_IDDQ | GPHY_CFG_PWDOWN_HW;
+ mac = CSR_READ_4(sc, ALC_MAC_CFG);
+ } else {
+ if ((ifp->if_capenable & IFCAP_WOL) != 0) {
+ gphy |= GPHY_CFG_EXT_RESET;
+ if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0)
+ alc_setlinkspeed(sc);
+ }
+ pmcs = 0;
+ if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
+ pmcs |= WOL_CFG_MAGIC | WOL_CFG_MAGIC_ENB;
+ CSR_WRITE_4(sc, ALC_WOL_CFG, pmcs);
+ mac = CSR_READ_4(sc, ALC_MAC_CFG);
+ mac &= ~(MAC_CFG_DBG | MAC_CFG_PROMISC | MAC_CFG_ALLMULTI |
+ MAC_CFG_BCAST);
+ if ((ifp->if_capenable & IFCAP_WOL_MCAST) != 0)
+ mac |= MAC_CFG_ALLMULTI | MAC_CFG_BCAST;
+ if ((ifp->if_capenable & IFCAP_WOL) != 0)
+ mac |= MAC_CFG_RX_ENB;
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_S3DIG10,
+ ANEG_S3DIG10_SL);
+ }
+
+ /* Enable OSC. */
+ reg = CSR_READ_4(sc, ALC_MISC);
+ reg &= ~MISC_INTNLOSC_OPEN;
+ CSR_WRITE_4(sc, ALC_MISC, reg);
+ reg |= MISC_INTNLOSC_OPEN;
+ CSR_WRITE_4(sc, ALC_MISC, reg);
+ CSR_WRITE_4(sc, ALC_MASTER_CFG, master);
+ CSR_WRITE_4(sc, ALC_MAC_CFG, mac);
+ CSR_WRITE_4(sc, ALC_GPHY_CFG, gphy);
+ reg = CSR_READ_4(sc, ALC_PDLL_TRNS1);
+ reg |= PDLL_TRNS1_D3PLLOFF_ENB;
+ CSR_WRITE_4(sc, ALC_PDLL_TRNS1, reg);
+
+ if ((sc->alc_flags & ALC_FLAG_PM) != 0) {
+ /* Request PME. */
+ pmstat = pci_read_config(sc->alc_dev,
+ sc->alc_pmcap + PCIR_POWER_STATUS, 2);
+ pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
+ if ((ifp->if_capenable & IFCAP_WOL) != 0)
+ pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
+ pci_write_config(sc->alc_dev,
+ sc->alc_pmcap + PCIR_POWER_STATUS, pmstat, 2);
+ }
+}
+
static int
alc_suspend(device_t dev)
{
@@ -2032,7 +2691,7 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
ip_off = poff = 0;
if ((m->m_pkthdr.csum_flags & (ALC_CSUM_FEATURES | CSUM_TSO)) != 0) {
/*
- * AR813x/AR815x requires offset of TCP/UDP header in its
+ * AR81[3567]x requires offset of TCP/UDP header in its
* Tx descriptor to perform Tx checksum offloading. TSO
* also requires TCP header offset and modification of
* IP/TCP header. This kind of operation takes many CPU
@@ -2170,7 +2829,7 @@ alc_encap(struct alc_softc *sc, struct mbuf **m_head)
cflags |= (poff << TD_TCPHDR_OFFSET_SHIFT) &
TD_TCPHDR_OFFSET_MASK;
/*
- * AR813x/AR815x requires the first buffer should
+ * AR81[3567]x requires the first buffer should
* only hold IP/TCP header data. Payload should
* be handled in other descriptors.
*/
@@ -2301,10 +2960,14 @@ alc_start_locked(struct ifnet *ifp)
bus_dmamap_sync(sc->alc_cdata.alc_tx_ring_tag,
sc->alc_cdata.alc_tx_ring_map, BUS_DMASYNC_PREWRITE);
/* Kick. Assume we're using normal Tx priority queue. */
- CSR_WRITE_4(sc, ALC_MBOX_TD_PROD_IDX,
- (sc->alc_cdata.alc_tx_prod <<
- MBOX_TD_PROD_LO_IDX_SHIFT) &
- MBOX_TD_PROD_LO_IDX_MASK);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ CSR_WRITE_2(sc, ALC_MBOX_TD_PRI0_PROD_IDX,
+ (uint16_t)sc->alc_cdata.alc_tx_prod);
+ else
+ CSR_WRITE_4(sc, ALC_MBOX_TD_PROD_IDX,
+ (sc->alc_cdata.alc_tx_prod <<
+ MBOX_TD_PROD_LO_IDX_SHIFT) &
+ MBOX_TD_PROD_LO_IDX_MASK);
/* Set a timeout in case the chip goes out to lunch. */
sc->alc_watchdog_timer = ALC_TX_TIMEOUT;
}
@@ -2358,7 +3021,7 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
else if (ifp->if_mtu != ifr->ifr_mtu) {
ALC_LOCK(sc);
ifp->if_mtu = ifr->ifr_mtu;
- /* AR813x/AR815x has 13 bits MSS field. */
+ /* AR81[3567]x has 13 bits MSS field. */
if (ifp->if_mtu > ALC_TSO_MTU &&
(ifp->if_capenable & IFCAP_TSO4) != 0) {
ifp->if_capenable &= ~IFCAP_TSO4;
@@ -2409,7 +3072,7 @@ alc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
(ifp->if_capabilities & IFCAP_TSO4) != 0) {
ifp->if_capenable ^= IFCAP_TSO4;
if ((ifp->if_capenable & IFCAP_TSO4) != 0) {
- /* AR813x/AR815x has 13 bits MSS field. */
+ /* AR81[3567]x has 13 bits MSS field. */
if (ifp->if_mtu > ALC_TSO_MTU) {
ifp->if_capenable &= ~IFCAP_TSO4;
ifp->if_hwassist &= ~CSUM_TSO;
@@ -2461,7 +3124,8 @@ alc_mac_config(struct alc_softc *sc)
reg = CSR_READ_4(sc, ALC_MAC_CFG);
reg &= ~(MAC_CFG_FULL_DUPLEX | MAC_CFG_TX_FC | MAC_CFG_RX_FC |
MAC_CFG_SPEED_MASK);
- if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151 ||
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0 ||
+ sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151 ||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2 ||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2)
reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
@@ -2599,7 +3263,6 @@ alc_stats_update(struct alc_softc *sc)
stat->tx_multi_colls += smb->tx_multi_colls;
stat->tx_late_colls += smb->tx_late_colls;
stat->tx_excess_colls += smb->tx_excess_colls;
- stat->tx_abort += smb->tx_abort;
stat->tx_underrun += smb->tx_underrun;
stat->tx_desc_underrun += smb->tx_desc_underrun;
stat->tx_lenerrs += smb->tx_lenerrs;
@@ -2612,17 +3275,10 @@ alc_stats_update(struct alc_softc *sc)
if_inc_counter(ifp, IFCOUNTER_COLLISIONS, smb->tx_single_colls +
smb->tx_multi_colls * 2 + smb->tx_late_colls +
- smb->tx_abort * HDPX_CFG_RETRY_DEFAULT);
+ smb->tx_excess_colls * HDPX_CFG_RETRY_DEFAULT);
- /*
- * XXX
- * tx_pkts_truncated counter looks suspicious. It constantly
- * increments with no sign of Tx errors. This may indicate
- * the counter name is not correct one so I've removed the
- * counter in output errors.
- */
- if_inc_counter(ifp, IFCOUNTER_OERRORS,
- smb->tx_abort + smb->tx_late_colls + smb->tx_underrun);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, smb->tx_late_colls +
+ smb->tx_excess_colls + smb->tx_underrun + smb->tx_pkts_truncated);
if_inc_counter(ifp, IFCOUNTER_IPACKETS, smb->rx_frames);
@@ -2751,11 +3407,16 @@ alc_txeof(struct alc_softc *sc)
bus_dmamap_sync(sc->alc_cdata.alc_cmb_tag,
sc->alc_cdata.alc_cmb_map, BUS_DMASYNC_POSTREAD);
prod = sc->alc_rdata.alc_cmb->cons;
- } else
- prod = CSR_READ_4(sc, ALC_MBOX_TD_CONS_IDX);
- /* Assume we're using normal Tx priority queue. */
- prod = (prod & MBOX_TD_CONS_LO_IDX_MASK) >>
- MBOX_TD_CONS_LO_IDX_SHIFT;
+ } else {
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ prod = CSR_READ_2(sc, ALC_MBOX_TD_PRI0_CONS_IDX);
+ else {
+ prod = CSR_READ_4(sc, ALC_MBOX_TD_CONS_IDX);
+ /* Assume we're using normal Tx priority queue. */
+ prod = (prod & MBOX_TD_CONS_LO_IDX_MASK) >>
+ MBOX_TD_CONS_LO_IDX_SHIFT;
+ }
+ }
cons = sc->alc_cdata.alc_tx_cons;
/*
* Go through our Tx list and free mbufs for those
@@ -2891,8 +3552,12 @@ alc_rxintr(struct alc_softc *sc, int count)
* it still seems that pre-fetching needs more
* experimentation.
*/
- CSR_WRITE_4(sc, ALC_MBOX_RD0_PROD_IDX,
- sc->alc_cdata.alc_rx_cons);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ CSR_WRITE_2(sc, ALC_MBOX_RD0_PROD_IDX,
+ (uint16_t)sc->alc_cdata.alc_rx_cons);
+ else
+ CSR_WRITE_4(sc, ALC_MBOX_RD0_PROD_IDX,
+ sc->alc_cdata.alc_rx_cons);
}
return (count > 0 ? 0 : EAGAIN);
@@ -3084,14 +3749,78 @@ alc_tick(void *arg)
}
static void
-alc_reset(struct alc_softc *sc)
+alc_osc_reset(struct alc_softc *sc)
{
uint32_t reg;
+
+ reg = CSR_READ_4(sc, ALC_MISC3);
+ reg &= ~MISC3_25M_BY_SW;
+ reg |= MISC3_25M_NOTO_INTNL;
+ CSR_WRITE_4(sc, ALC_MISC3, reg);
+
+ reg = CSR_READ_4(sc, ALC_MISC);
+ if (AR816X_REV(sc->alc_rev) >= AR816X_REV_B0) {
+ /*
+ * Restore over-current protection default value.
+ * This value could be reset by MAC reset.
+ */
+ reg &= ~MISC_PSW_OCP_MASK;
+ reg |= (MISC_PSW_OCP_DEFAULT << MISC_PSW_OCP_SHIFT);
+ reg &= ~MISC_INTNLOSC_OPEN;
+ CSR_WRITE_4(sc, ALC_MISC, reg);
+ CSR_WRITE_4(sc, ALC_MISC, reg | MISC_INTNLOSC_OPEN);
+ reg = CSR_READ_4(sc, ALC_MISC2);
+ reg &= ~MISC2_CALB_START;
+ CSR_WRITE_4(sc, ALC_MISC2, reg);
+ CSR_WRITE_4(sc, ALC_MISC2, reg | MISC2_CALB_START);
+
+ } else {
+ reg &= ~MISC_INTNLOSC_OPEN;
+ /* Disable isolate for revision A devices. */
+ if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1)
+ reg &= ~MISC_ISO_ENB;
+ CSR_WRITE_4(sc, ALC_MISC, reg | MISC_INTNLOSC_OPEN);
+ CSR_WRITE_4(sc, ALC_MISC, reg);
+ }
+
+ DELAY(20);
+}
+
+static void
+alc_reset(struct alc_softc *sc)
+{
+ uint32_t pmcfg, reg;
int i;
- reg = CSR_READ_4(sc, ALC_MASTER_CFG) & 0xFFFF;
+ pmcfg = 0;
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ /* Reset workaround. */
+ CSR_WRITE_4(sc, ALC_MBOX_RD0_PROD_IDX, 1);
+ if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1 &&
+ (sc->alc_rev & 0x01) != 0) {
+ /* Disable L0s/L1s before reset. */
+ pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
+ if ((pmcfg & (PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB))
+ != 0) {
+ pmcfg &= ~(PM_CFG_ASPM_L0S_ENB |
+ PM_CFG_ASPM_L1_ENB);
+ CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+ }
+ }
+ }
+ reg = CSR_READ_4(sc, ALC_MASTER_CFG);
reg |= MASTER_OOB_DIS_OFF | MASTER_RESET;
CSR_WRITE_4(sc, ALC_MASTER_CFG, reg);
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ for (i = ALC_RESET_TIMEOUT; i > 0; i--) {
+ DELAY(10);
+ if (CSR_READ_4(sc, ALC_MBOX_RD0_PROD_IDX) == 0)
+ break;
+ }
+ if (i == 0)
+ device_printf(sc->alc_dev, "MAC reset timeout!\n");
+ }
for (i = ALC_RESET_TIMEOUT; i > 0; i--) {
DELAY(10);
if ((CSR_READ_4(sc, ALC_MASTER_CFG) & MASTER_RESET) == 0)
@@ -3101,13 +3830,45 @@ alc_reset(struct alc_softc *sc)
device_printf(sc->alc_dev, "master reset timeout!\n");
for (i = ALC_RESET_TIMEOUT; i > 0; i--) {
- if ((reg = CSR_READ_4(sc, ALC_IDLE_STATUS)) == 0)
+ reg = CSR_READ_4(sc, ALC_IDLE_STATUS);
+ if ((reg & (IDLE_STATUS_RXMAC | IDLE_STATUS_TXMAC |
+ IDLE_STATUS_RXQ | IDLE_STATUS_TXQ)) == 0)
break;
DELAY(10);
}
-
if (i == 0)
device_printf(sc->alc_dev, "reset timeout(0x%08x)!\n", reg);
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1 &&
+ (sc->alc_rev & 0x01) != 0) {
+ reg = CSR_READ_4(sc, ALC_MASTER_CFG);
+ reg |= MASTER_CLK_SEL_DIS;
+ CSR_WRITE_4(sc, ALC_MASTER_CFG, reg);
+ /* Restore L0s/L1s config. */
+ if ((pmcfg & (PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB))
+ != 0)
+ CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+ }
+
+ alc_osc_reset(sc);
+ reg = CSR_READ_4(sc, ALC_MISC3);
+ reg &= ~MISC3_25M_BY_SW;
+ reg |= MISC3_25M_NOTO_INTNL;
+ CSR_WRITE_4(sc, ALC_MISC3, reg);
+ reg = CSR_READ_4(sc, ALC_MISC);
+ reg &= ~MISC_INTNLOSC_OPEN;
+ if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1)
+ reg &= ~MISC_ISO_ENB;
+ CSR_WRITE_4(sc, ALC_MISC, reg);
+ DELAY(20);
+ }
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0 ||
+ sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B ||
+ sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2)
+ CSR_WRITE_4(sc, ALC_SERDES_LOCK,
+ CSR_READ_4(sc, ALC_SERDES_LOCK) | SERDES_MAC_CLK_SLOWDOWN |
+ SERDES_PHY_CLK_SLOWDOWN);
}
static void
@@ -3158,7 +3919,16 @@ alc_init_locked(struct alc_softc *sc)
alc_init_smb(sc);
/* Enable all clocks. */
- CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, 0);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, CLK_GATING_DMAW_ENB |
+ CLK_GATING_DMAR_ENB | CLK_GATING_TXQ_ENB |
+ CLK_GATING_RXQ_ENB | CLK_GATING_TXMAC_ENB |
+ CLK_GATING_RXMAC_ENB);
+ if (AR816X_REV(sc->alc_rev) >= AR816X_REV_B0)
+ CSR_WRITE_4(sc, ALC_IDLE_DECISN_TIMER,
+ IDLE_DECISN_TIMER_DEFAULT_1MS);
+ } else
+ CSR_WRITE_4(sc, ALC_CLK_GATING_CFG, 0);
/* Reprogram the station address. */
bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN);
@@ -3184,10 +3954,12 @@ alc_init_locked(struct alc_softc *sc)
paddr = sc->alc_rdata.alc_rx_ring_paddr;
CSR_WRITE_4(sc, ALC_RX_BASE_ADDR_HI, ALC_ADDR_HI(paddr));
CSR_WRITE_4(sc, ALC_RD0_HEAD_ADDR_LO, ALC_ADDR_LO(paddr));
- /* We use one Rx ring. */
- CSR_WRITE_4(sc, ALC_RD1_HEAD_ADDR_LO, 0);
- CSR_WRITE_4(sc, ALC_RD2_HEAD_ADDR_LO, 0);
- CSR_WRITE_4(sc, ALC_RD3_HEAD_ADDR_LO, 0);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ /* We use one Rx ring. */
+ CSR_WRITE_4(sc, ALC_RD1_HEAD_ADDR_LO, 0);
+ CSR_WRITE_4(sc, ALC_RD2_HEAD_ADDR_LO, 0);
+ CSR_WRITE_4(sc, ALC_RD3_HEAD_ADDR_LO, 0);
+ }
/* Set Rx descriptor counter. */
CSR_WRITE_4(sc, ALC_RD_RING_CNT,
(ALC_RX_RING_CNT << RD_RING_CNT_SHIFT) & RD_RING_CNT_MASK);
@@ -3212,10 +3984,12 @@ alc_init_locked(struct alc_softc *sc)
paddr = sc->alc_rdata.alc_rr_ring_paddr;
/* Set Rx return descriptor base addresses. */
CSR_WRITE_4(sc, ALC_RRD0_HEAD_ADDR_LO, ALC_ADDR_LO(paddr));
- /* We use one Rx return ring. */
- CSR_WRITE_4(sc, ALC_RRD1_HEAD_ADDR_LO, 0);
- CSR_WRITE_4(sc, ALC_RRD2_HEAD_ADDR_LO, 0);
- CSR_WRITE_4(sc, ALC_RRD3_HEAD_ADDR_LO, 0);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ /* We use one Rx return ring. */
+ CSR_WRITE_4(sc, ALC_RRD1_HEAD_ADDR_LO, 0);
+ CSR_WRITE_4(sc, ALC_RRD2_HEAD_ADDR_LO, 0);
+ CSR_WRITE_4(sc, ALC_RRD3_HEAD_ADDR_LO, 0);
+ }
/* Set Rx return descriptor counter. */
CSR_WRITE_4(sc, ALC_RRD_RING_CNT,
(ALC_RR_RING_CNT << RRD_RING_CNT_SHIFT) & RRD_RING_CNT_MASK);
@@ -3242,16 +4016,20 @@ alc_init_locked(struct alc_softc *sc)
/* Configure interrupt moderation timer. */
reg = ALC_USECS(sc->alc_int_rx_mod) << IM_TIMER_RX_SHIFT;
- reg |= ALC_USECS(sc->alc_int_tx_mod) << IM_TIMER_TX_SHIFT;
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0)
+ reg |= ALC_USECS(sc->alc_int_tx_mod) << IM_TIMER_TX_SHIFT;
CSR_WRITE_4(sc, ALC_IM_TIMER, reg);
/*
* We don't want to automatic interrupt clear as task queue
* for the interrupt should know interrupt status.
*/
- reg = MASTER_SA_TIMER_ENB;
+ reg = CSR_READ_4(sc, ALC_MASTER_CFG);
+ reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
+ reg |= MASTER_SA_TIMER_ENB;
if (ALC_USECS(sc->alc_int_rx_mod) != 0)
reg |= MASTER_IM_RX_TIMER_ENB;
- if (ALC_USECS(sc->alc_int_tx_mod) != 0)
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0 &&
+ ALC_USECS(sc->alc_int_tx_mod) != 0)
reg |= MASTER_IM_TX_TIMER_ENB;
CSR_WRITE_4(sc, ALC_MASTER_CFG, reg);
/*
@@ -3260,11 +4038,17 @@ alc_init_locked(struct alc_softc *sc)
*/
CSR_WRITE_4(sc, ALC_INTR_RETRIG_TIMER, ALC_USECS(0));
/* Configure CMB. */
- if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0) {
- CSR_WRITE_4(sc, ALC_CMB_TD_THRESH, 4);
- CSR_WRITE_4(sc, ALC_CMB_TX_TIMER, ALC_USECS(5000));
- } else
- CSR_WRITE_4(sc, ALC_CMB_TX_TIMER, ALC_USECS(0));
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ CSR_WRITE_4(sc, ALC_CMB_TD_THRESH, ALC_TX_RING_CNT / 3);
+ CSR_WRITE_4(sc, ALC_CMB_TX_TIMER,
+ ALC_USECS(sc->alc_int_tx_mod));
+ } else {
+ if ((sc->alc_flags & ALC_FLAG_CMB_BUG) == 0) {
+ CSR_WRITE_4(sc, ALC_CMB_TD_THRESH, 4);
+ CSR_WRITE_4(sc, ALC_CMB_TX_TIMER, ALC_USECS(5000));
+ } else
+ CSR_WRITE_4(sc, ALC_CMB_TX_TIMER, ALC_USECS(0));
+ }
/*
* Hardware can be configured to issue SMB interrupt based
* on programmed interval. Since there is a callout that is
@@ -3291,33 +4075,42 @@ alc_init_locked(struct alc_softc *sc)
*/
CSR_WRITE_4(sc, ALC_FRAME_SIZE, sc->alc_ident->max_framelen);
- /* Disable header split(?) */
- CSR_WRITE_4(sc, ALC_HDS_CFG, 0);
-
- /* Configure IPG/IFG parameters. */
- CSR_WRITE_4(sc, ALC_IPG_IFG_CFG,
- ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) & IPG_IFG_IPGT_MASK) |
- ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) & IPG_IFG_MIFG_MASK) |
- ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) & IPG_IFG_IPG1_MASK) |
- ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) & IPG_IFG_IPG2_MASK));
- /* Set parameters for half-duplex media. */
- CSR_WRITE_4(sc, ALC_HDPX_CFG,
- ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) &
- HDPX_CFG_LCOL_MASK) |
- ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) &
- HDPX_CFG_RETRY_MASK) | HDPX_CFG_EXC_DEF_EN |
- ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) &
- HDPX_CFG_ABEBT_MASK) |
- ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) &
- HDPX_CFG_JAMIPG_MASK));
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ /* Disable header split(?) */
+ CSR_WRITE_4(sc, ALC_HDS_CFG, 0);
+
+ /* Configure IPG/IFG parameters. */
+ CSR_WRITE_4(sc, ALC_IPG_IFG_CFG,
+ ((IPG_IFG_IPGT_DEFAULT << IPG_IFG_IPGT_SHIFT) &
+ IPG_IFG_IPGT_MASK) |
+ ((IPG_IFG_MIFG_DEFAULT << IPG_IFG_MIFG_SHIFT) &
+ IPG_IFG_MIFG_MASK) |
+ ((IPG_IFG_IPG1_DEFAULT << IPG_IFG_IPG1_SHIFT) &
+ IPG_IFG_IPG1_MASK) |
+ ((IPG_IFG_IPG2_DEFAULT << IPG_IFG_IPG2_SHIFT) &
+ IPG_IFG_IPG2_MASK));
+ /* Set parameters for half-duplex media. */
+ CSR_WRITE_4(sc, ALC_HDPX_CFG,
+ ((HDPX_CFG_LCOL_DEFAULT << HDPX_CFG_LCOL_SHIFT) &
+ HDPX_CFG_LCOL_MASK) |
+ ((HDPX_CFG_RETRY_DEFAULT << HDPX_CFG_RETRY_SHIFT) &
+ HDPX_CFG_RETRY_MASK) | HDPX_CFG_EXC_DEF_EN |
+ ((HDPX_CFG_ABEBT_DEFAULT << HDPX_CFG_ABEBT_SHIFT) &
+ HDPX_CFG_ABEBT_MASK) |
+ ((HDPX_CFG_JAMIPG_DEFAULT << HDPX_CFG_JAMIPG_SHIFT) &
+ HDPX_CFG_JAMIPG_MASK));
+ }
+
/*
* Set TSO/checksum offload threshold. For frames that is
* larger than this threshold, hardware wouldn't do
* TSO/checksum offloading.
*/
- CSR_WRITE_4(sc, ALC_TSO_OFFLOAD_THRESH,
- (sc->alc_ident->max_framelen >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
- TSO_OFFLOAD_THRESH_MASK);
+ reg = (sc->alc_ident->max_framelen >> TSO_OFFLOAD_THRESH_UNIT_SHIFT) &
+ TSO_OFFLOAD_THRESH_MASK;
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ reg |= TSO_OFFLOAD_ERRLGPKT_DROP_ENB;
+ CSR_WRITE_4(sc, ALC_TSO_OFFLOAD_THRESH, reg);
/* Configure TxQ. */
reg = (alc_dma_burst[sc->alc_dma_rd_burst] <<
TXQ_CFG_TX_FIFO_BURST_SHIFT) & TXQ_CFG_TX_FIFO_BURST_MASK;
@@ -3326,21 +4119,50 @@ alc_init_locked(struct alc_softc *sc)
reg >>= 1;
reg |= (TXQ_CFG_TD_BURST_DEFAULT << TXQ_CFG_TD_BURST_SHIFT) &
TXQ_CFG_TD_BURST_MASK;
+ reg |= TXQ_CFG_IP_OPTION_ENB | TXQ_CFG_8023_ENB;
CSR_WRITE_4(sc, ALC_TXQ_CFG, reg | TXQ_CFG_ENHANCED_MODE);
-
- /* Configure Rx free descriptor pre-fetching. */
- CSR_WRITE_4(sc, ALC_RX_RD_FREE_THRESH,
- ((RX_RD_FREE_THRESH_HI_DEFAULT << RX_RD_FREE_THRESH_HI_SHIFT) &
- RX_RD_FREE_THRESH_HI_MASK) |
- ((RX_RD_FREE_THRESH_LO_DEFAULT << RX_RD_FREE_THRESH_LO_SHIFT) &
- RX_RD_FREE_THRESH_LO_MASK));
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ reg = (TXQ_CFG_TD_BURST_DEFAULT << HQTD_CFG_Q1_BURST_SHIFT |
+ TXQ_CFG_TD_BURST_DEFAULT << HQTD_CFG_Q2_BURST_SHIFT |
+ TXQ_CFG_TD_BURST_DEFAULT << HQTD_CFG_Q3_BURST_SHIFT |
+ HQTD_CFG_BURST_ENB);
+ CSR_WRITE_4(sc, ALC_HQTD_CFG, reg);
+ reg = WRR_PRI_RESTRICT_NONE;
+ reg |= (WRR_PRI_DEFAULT << WRR_PRI0_SHIFT |
+ WRR_PRI_DEFAULT << WRR_PRI1_SHIFT |
+ WRR_PRI_DEFAULT << WRR_PRI2_SHIFT |
+ WRR_PRI_DEFAULT << WRR_PRI3_SHIFT);
+ CSR_WRITE_4(sc, ALC_WRR, reg);
+ } else {
+ /* Configure Rx free descriptor pre-fetching. */
+ CSR_WRITE_4(sc, ALC_RX_RD_FREE_THRESH,
+ ((RX_RD_FREE_THRESH_HI_DEFAULT <<
+ RX_RD_FREE_THRESH_HI_SHIFT) & RX_RD_FREE_THRESH_HI_MASK) |
+ ((RX_RD_FREE_THRESH_LO_DEFAULT <<
+ RX_RD_FREE_THRESH_LO_SHIFT) & RX_RD_FREE_THRESH_LO_MASK));
+ }
/*
* Configure flow control parameters.
* XON : 80% of Rx FIFO
* XOFF : 30% of Rx FIFO
*/
- if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8131 ||
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
+ reg &= SRAM_RX_FIFO_LEN_MASK;
+ reg *= 8;
+ if (reg > 8 * 1024)
+ reg -= RX_FIFO_PAUSE_816X_RSVD;
+ else
+ reg -= RX_BUF_SIZE_MAX;
+ reg /= 8;
+ CSR_WRITE_4(sc, ALC_RX_FIFO_PAUSE_THRESH,
+ ((reg << RX_FIFO_PAUSE_THRESH_LO_SHIFT) &
+ RX_FIFO_PAUSE_THRESH_LO_MASK) |
+ (((RX_FIFO_PAUSE_816X_RSVD / 8) <<
+ RX_FIFO_PAUSE_THRESH_HI_SHIFT) &
+ RX_FIFO_PAUSE_THRESH_HI_MASK));
+ } else if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8131 ||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8132) {
reg = CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN);
rxf_hi = (reg * 8) / 10;
@@ -3352,21 +4174,22 @@ alc_init_locked(struct alc_softc *sc)
RX_FIFO_PAUSE_THRESH_HI_MASK));
}
- if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B ||
- sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2)
- CSR_WRITE_4(sc, ALC_SERDES_LOCK,
- CSR_READ_4(sc, ALC_SERDES_LOCK) | SERDES_MAC_CLK_SLOWDOWN |
- SERDES_PHY_CLK_SLOWDOWN);
-
- /* Disable RSS until I understand L1C/L2C's RSS logic. */
- CSR_WRITE_4(sc, ALC_RSS_IDT_TABLE0, 0);
- CSR_WRITE_4(sc, ALC_RSS_CPU, 0);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ /* Disable RSS until I understand L1C/L2C's RSS logic. */
+ CSR_WRITE_4(sc, ALC_RSS_IDT_TABLE0, 0);
+ CSR_WRITE_4(sc, ALC_RSS_CPU, 0);
+ }
/* Configure RxQ. */
reg = (RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) &
RXQ_CFG_RD_BURST_MASK;
reg |= RXQ_CFG_RSS_MODE_DIS;
- if ((sc->alc_flags & ALC_FLAG_ASPM_MON) != 0)
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ reg |= (RXQ_CFG_816X_IDT_TBL_SIZE_DEFAULT <<
+ RXQ_CFG_816X_IDT_TBL_SIZE_SHIFT) &
+ RXQ_CFG_816X_IDT_TBL_SIZE_MASK;
+ if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0 &&
+ sc->alc_ident->deviceid != DEVICEID_ATHEROS_AR8151_V2)
reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);
@@ -3387,6 +4210,19 @@ alc_init_locked(struct alc_softc *sc)
DMA_CFG_RD_DELAY_CNT_MASK;
reg |= (DMA_CFG_WR_DELAY_CNT_DEFAULT << DMA_CFG_WR_DELAY_CNT_SHIFT) &
DMA_CFG_WR_DELAY_CNT_MASK;
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ switch (AR816X_REV(sc->alc_rev)) {
+ case AR816X_REV_A0:
+ case AR816X_REV_A1:
+ reg |= DMA_CFG_RD_CHNL_SEL_1;
+ break;
+ case AR816X_REV_B0:
+ /* FALLTHROUGH */
+ default:
+ reg |= DMA_CFG_RD_CHNL_SEL_3;
+ break;
+ }
+ }
CSR_WRITE_4(sc, ALC_DMA_CFG, reg);
/*
@@ -3405,7 +4241,8 @@ alc_init_locked(struct alc_softc *sc)
reg = MAC_CFG_TX_CRC_ENB | MAC_CFG_TX_AUTO_PAD | MAC_CFG_FULL_DUPLEX |
((MAC_CFG_PREAMBLE_DEFAULT << MAC_CFG_PREAMBLE_SHIFT) &
MAC_CFG_PREAMBLE_MASK);
- if (sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151 ||
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0 ||
+ sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151 ||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8151_V2 ||
sc->alc_ident->deviceid == DEVICEID_ATHEROS_AR8152_B2)
reg |= MAC_CFG_HASH_ALG_CRC32 | MAC_CFG_SPEED_MODE_SW;
@@ -3424,14 +4261,14 @@ alc_init_locked(struct alc_softc *sc)
CSR_WRITE_4(sc, ALC_INTR_STATUS, 0xFFFFFFFF);
CSR_WRITE_4(sc, ALC_INTR_STATUS, 0);
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
sc->alc_flags &= ~ALC_FLAG_LINK;
/* Switch to the current media. */
- mii_mediachg(mii);
+ alc_mediachange_locked(sc);
callout_reset(&sc->alc_tick_ch, hz, alc_tick, sc);
-
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
@@ -3456,7 +4293,6 @@ alc_stop(struct alc_softc *sc)
/* Disable interrupts. */
CSR_WRITE_4(sc, ALC_INTR_MASK, 0);
CSR_WRITE_4(sc, ALC_INTR_STATUS, 0xFFFFFFFF);
- alc_stop_queue(sc);
/* Disable DMA. */
reg = CSR_READ_4(sc, ALC_DMA_CFG);
reg &= ~(DMA_CFG_CMB_ENB | DMA_CFG_SMB_ENB);
@@ -3467,7 +4303,8 @@ alc_stop(struct alc_softc *sc)
alc_stop_mac(sc);
/* Disable interrupts which might be touched in taskq handler. */
CSR_WRITE_4(sc, ALC_INTR_STATUS, 0xFFFFFFFF);
-
+ /* Disable L0s/L1s */
+ alc_aspm(sc, 0, IFM_UNKNOWN);
/* Reclaim Rx buffers that have been processed. */
if (sc->alc_cdata.alc_rxhead != NULL)
m_freem(sc->alc_cdata.alc_rxhead);
@@ -3505,8 +4342,7 @@ alc_stop_mac(struct alc_softc *sc)
uint32_t reg;
int i;
- ALC_LOCK_ASSERT(sc);
-
+ alc_stop_queue(sc);
/* Disable Rx/Tx MAC. */
reg = CSR_READ_4(sc, ALC_MAC_CFG);
if ((reg & (MAC_CFG_TX_ENB | MAC_CFG_RX_ENB)) != 0) {
@@ -3515,7 +4351,7 @@ alc_stop_mac(struct alc_softc *sc)
}
for (i = ALC_TIMEOUT; i > 0; i--) {
reg = CSR_READ_4(sc, ALC_IDLE_STATUS);
- if (reg == 0)
+ if ((reg & (IDLE_STATUS_RXMAC | IDLE_STATUS_TXMAC)) == 0)
break;
DELAY(10);
}
@@ -3540,8 +4376,11 @@ alc_start_queue(struct alc_softc *sc)
/* Enable RxQ. */
cfg = CSR_READ_4(sc, ALC_RXQ_CFG);
- cfg &= ~RXQ_CFG_ENB;
- cfg |= qcfg[1];
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ cfg &= ~RXQ_CFG_ENB;
+ cfg |= qcfg[1];
+ } else
+ cfg |= RXQ_CFG_QUEUE0_ENB;
CSR_WRITE_4(sc, ALC_RXQ_CFG, cfg);
/* Enable TxQ. */
cfg = CSR_READ_4(sc, ALC_TXQ_CFG);
@@ -3559,9 +4398,16 @@ alc_stop_queue(struct alc_softc *sc)
/* Disable RxQ. */
reg = CSR_READ_4(sc, ALC_RXQ_CFG);
- if ((reg & RXQ_CFG_ENB) != 0) {
- reg &= ~RXQ_CFG_ENB;
- CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ if ((reg & RXQ_CFG_ENB) != 0) {
+ reg &= ~RXQ_CFG_ENB;
+ CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);
+ }
+ } else {
+ if ((reg & RXQ_CFG_QUEUE0_ENB) != 0) {
+ reg &= ~RXQ_CFG_QUEUE0_ENB;
+ CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);
+ }
}
/* Disable TxQ. */
reg = CSR_READ_4(sc, ALC_TXQ_CFG);
@@ -3569,6 +4415,7 @@ alc_stop_queue(struct alc_softc *sc)
reg &= ~TXQ_CFG_ENB;
CSR_WRITE_4(sc, ALC_TXQ_CFG, reg);
}
+ DELAY(40);
for (i = ALC_TIMEOUT; i > 0; i--) {
reg = CSR_READ_4(sc, ALC_IDLE_STATUS);
if ((reg & (IDLE_STATUS_RXQ | IDLE_STATUS_TXQ)) == 0)
diff --git a/sys/dev/alc/if_alcreg.h b/sys/dev/alc/if_alcreg.h
index 3011abf..1ad75a3 100644
--- a/sys/dev/alc/if_alcreg.h
+++ b/sys/dev/alc/if_alcreg.h
@@ -44,10 +44,26 @@
#define DEVICEID_ATHEROS_AR8151_V2 0x1083 /* L1D V2.0 */
#define DEVICEID_ATHEROS_AR8152_B 0x2060 /* L2C V1.1 */
#define DEVICEID_ATHEROS_AR8152_B2 0x2062 /* L2C V2.0 */
+#define DEVICEID_ATHEROS_AR8161 0x1091
+#define DEVICEID_ATHEROS_E2200 0xE091
+#define DEVICEID_ATHEROS_AR8162 0x1090
+#define DEVICEID_ATHEROS_AR8171 0x10A1
+#define DEVICEID_ATHEROS_AR8172 0x10A0
#define ATHEROS_AR8152_B_V10 0xC0
#define ATHEROS_AR8152_B_V11 0xC1
+/*
+ * Atheros AR816x/AR817x revisions
+ */
+#define AR816X_REV_A0 0
+#define AR816X_REV_A1 1
+#define AR816X_REV_B0 2
+#define AR816X_REV_C0 3
+
+#define AR816X_REV_SHIFT 3
+#define AR816X_REV(x) ((x) >> AR816X_REV_SHIFT)
+
/* 0x0000 - 0x02FF : PCIe configuration space */
#define ALC_PEX_UNC_ERR_SEV 0x10C
@@ -63,11 +79,34 @@
#define PEX_UNC_ERR_SEV_ECRC 0x00080000
#define PEX_UNC_ERR_SEV_UR 0x00100000
+#define ALC_EEPROM_LD 0x204 /* AR816x */
+#define EEPROM_LD_START 0x00000001
+#define EEPROM_LD_IDLE 0x00000010
+#define EEPROM_LD_DONE 0x00000000
+#define EEPROM_LD_PROGRESS 0x00000020
+#define EEPROM_LD_EXIST 0x00000100
+#define EEPROM_LD_EEPROM_EXIST 0x00000200
+#define EEPROM_LD_FLASH_EXIST 0x00000400
+#define EEPROM_LD_FLASH_END_ADDR_MASK 0x03FF0000
+#define EEPROM_LD_FLASH_END_ADDR_SHIFT 16
+
#define ALC_TWSI_CFG 0x218
#define TWSI_CFG_SW_LD_START 0x00000800
#define TWSI_CFG_HW_LD_START 0x00001000
#define TWSI_CFG_LD_EXIST 0x00400000
+#define ALC_SLD 0x218 /* AR816x */
+#define SLD_START 0x00000800
+#define SLD_PROGRESS 0x00001000
+#define SLD_IDLE 0x00002000
+#define SLD_SLVADDR_MASK 0x007F0000
+#define SLD_EXIST 0x00800000
+#define SLD_FREQ_MASK 0x03000000
+#define SLD_FREQ_100K 0x00000000
+#define SLD_FREQ_200K 0x01000000
+#define SLD_FREQ_300K 0x02000000
+#define SLD_FREQ_400K 0x03000000
+
#define ALC_PCIE_PHYMISC 0x1000
#define PCIE_PHYMISC_FORCE_RCV_DET 0x00000004
@@ -77,6 +116,9 @@
#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16
#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18
+#define ALC_PDLL_TRNS1 0x1104
+#define PDLL_TRNS1_D3PLLOFF_ENB 0x00000800
+
#define ALC_TWSI_DEBUG 0x1108
#define TWSI_DEBUG_DEV_EXIST 0x20000000
@@ -103,11 +145,14 @@
#define PM_CFG_SERDES_PD_EX_L1 0x00000040
#define PM_CFG_SERDES_BUDS_RX_L1_ENB 0x00000080
#define PM_CFG_L0S_ENTRY_TIMER_MASK 0x00000F00
+#define PM_CFG_RX_L1_AFTER_L0S 0x00000800
#define PM_CFG_ASPM_L0S_ENB 0x00001000
#define PM_CFG_CLK_SWH_L1 0x00002000
#define PM_CFG_CLK_PWM_VER1_1 0x00004000
#define PM_CFG_PCIE_RECV 0x00008000
#define PM_CFG_L1_ENTRY_TIMER_MASK 0x000F0000
+#define PM_CFG_L1_ENTRY_TIMER_816X_MASK 0x00070000
+#define PM_CFG_TX_L1_AFTER_L0S 0x00080000
#define PM_CFG_PM_REQ_TIMER_MASK 0x00F00000
#define PM_CFG_LCKDET_TIMER_MASK 0x0F000000
#define PM_CFG_EN_BUFS_RX_L0S 0x10000000
@@ -121,8 +166,10 @@
#define PM_CFG_L0S_ENTRY_TIMER_DEFAULT 6
#define PM_CFG_L1_ENTRY_TIMER_DEFAULT 1
+#define PM_CFG_L1_ENTRY_TIMER_816X_DEFAULT 4
#define PM_CFG_LCKDET_TIMER_DEFAULT 12
#define PM_CFG_PM_REQ_TIMER_DEFAULT 12
+#define PM_CFG_PM_REQ_TIMER_816X_DEFAULT 15
#define ALC_LTSSM_ID_CFG 0x12FC
#define LTSSM_ID_WRO_ENB 0x00001000
@@ -131,6 +178,7 @@
#define MASTER_RESET 0x00000001
#define MASTER_TEST_MODE_MASK 0x0000000C
#define MASTER_BERT_START 0x00000010
+#define MASTER_WAKEN_25M 0x00000020
#define MASTER_OOB_DIS_OFF 0x00000040
#define MASTER_SA_TIMER_ENB 0x00000080
#define MASTER_MTIMER_ENB 0x00000100
@@ -171,7 +219,7 @@
*/
#define ALC_IM_TX_TIMER_DEFAULT 1000 /* 1ms */
-#define ALC_GPHY_CFG 0x140C /* 16bits */
+#define ALC_GPHY_CFG 0x140C /* 16 bits, 32 bits on AR816x */
#define GPHY_CFG_EXT_RESET 0x0001
#define GPHY_CFG_RTL_MODE 0x0002
#define GPHY_CFG_LED_MODE 0x0004
@@ -188,6 +236,7 @@
#define GPHY_CFG_PHY_PLL_ON 0x2000
#define GPHY_CFG_PWDOWN_HW 0x4000
#define GPHY_CFG_PHY_PLL_BYPASS 0x8000
+#define GPHY_CFG_100AB_ENB 0x00020000
#define ALC_IDLE_STATUS 0x1410
#define IDLE_STATUS_RXMAC 0x00000001
@@ -212,9 +261,10 @@
#define MDIO_CLK_25_10 0x04000000
#define MDIO_CLK_25_14 0x05000000
#define MDIO_CLK_25_20 0x06000000
-#define MDIO_CLK_25_28 0x07000000
+#define MDIO_CLK_25_128 0x07000000
#define MDIO_OP_BUSY 0x08000000
#define MDIO_AP_ENB 0x10000000
+#define MDIO_MODE_EXT 0x40000000
#define MDIO_DATA_SHIFT 0
#define MDIO_REG_ADDR_SHIFT 16
@@ -248,6 +298,23 @@
#define SERDES_MAC_CLK_SLOWDOWN 0x00020000
#define SERDES_PHY_CLK_SLOWDOWN 0x00040000
+#define ALC_LPI_CTL 0x1440
+#define LPI_CTL_ENB 0x00000001
+
+#define ALC_EXT_MDIO 0x1448
+#define EXT_MDIO_REG_MASK 0x0000FFFF
+#define EXT_MDIO_DEVADDR_MASK 0x001F0000
+#define EXT_MDIO_REG_SHIFT 0
+#define EXT_MDIO_DEVADDR_SHIFT 16
+
+#define EXT_MDIO_REG(x) \
+ (((x) << EXT_MDIO_REG_SHIFT) & EXT_MDIO_REG_MASK)
+#define EXT_MDIO_DEVADDR(x) \
+ (((x) << EXT_MDIO_DEVADDR_SHIFT) & EXT_MDIO_DEVADDR_MASK)
+
+#define ALC_IDLE_DECISN_TIMER 0x1474
+#define IDLE_DECISN_TIMER_DEFAULT_1MS 0x400
+
#define ALC_MAC_CFG 0x1480
#define MAC_CFG_TX_ENB 0x00000001
#define MAC_CFG_RX_ENB 0x00000002
@@ -278,6 +345,7 @@
#define MAC_CFG_SINGLE_PAUSE_ENB 0x10000000
#define MAC_CFG_HASH_ALG_CRC32 0x20000000
#define MAC_CFG_SPEED_MODE_SW 0x40000000
+#define MAC_CFG_FAST_PAUSE 0x80000000
#define MAC_CFG_PREAMBLE_SHIFT 10
#define MAC_CFG_PREAMBLE_DEFAULT 7
@@ -378,8 +446,12 @@
#define ALC_RSS_IDT_TABLE0 0x14E0
+#define ALC_TD_PRI2_HEAD_ADDR_LO 0x14E0 /* AR816x */
+
#define ALC_RSS_IDT_TABLE1 0x14E4
+#define ALC_TD_PRI3_HEAD_ADDR_LO 0x14E4 /* AR816x */
+
#define ALC_RSS_IDT_TABLE2 0x14E8
#define ALC_RSS_IDT_TABLE3 0x14EC
@@ -422,6 +494,8 @@
#define ALC_SRAM_RX_FIFO_ADDR 0x1520
#define ALC_SRAM_RX_FIFO_LEN 0x1524
+#define SRAM_RX_FIFO_LEN_MASK 0x00000FFF
+#define SRAM_RX_FIFO_LEN_SHIFT 0
#define ALC_SRAM_TX_FIFO_ADDR 0x1528
@@ -478,8 +552,12 @@
#define ALC_TDH_HEAD_ADDR_LO 0x157C
+#define ALC_TD_PRI1_HEAD_ADDR_LO 0x157C /* AR816x */
+
#define ALC_TDL_HEAD_ADDR_LO 0x1580
+#define ALC_TD_PRI0_HEAD_ADDR_LO 0x1580 /* AR816x */
+
#define ALC_TD_RING_CNT 0x1584
#define TD_RING_CNT_MASK 0x0000FFFF
#define TD_RING_CNT_SHIFT 0
@@ -499,6 +577,7 @@
#define ALC_TSO_OFFLOAD_THRESH 0x1594 /* 8 bytes unit */
#define TSO_OFFLOAD_THRESH_MASK 0x000007FF
+#define TSO_OFFLOAD_ERRLGPKT_DROP_ENB 0x00000800
#define TSO_OFFLOAD_THRESH_SHIFT 0
#define TSO_OFFLOAD_THRESH_UNIT 8
#define TSO_OFFLOAD_THRESH_UNIT_SHIFT 3
@@ -546,6 +625,17 @@
(RXQ_CFG_QUEUE0_ENB | RXQ_CFG_QUEUE1_ENB | \
RXQ_CFG_QUEUE2_ENB | RXQ_CFG_QUEUE3_ENB)
+/* AR816x specific bits */
+#define RXQ_CFG_816X_RSS_HASH_IPV4 0x00000004
+#define RXQ_CFG_816X_RSS_HASH_IPV4_TCP 0x00000008
+#define RXQ_CFG_816X_RSS_HASH_IPV6 0x00000010
+#define RXQ_CFG_816X_RSS_HASH_IPV6_TCP 0x00000020
+#define RXQ_CFG_816X_RSS_HASH_MASK 0x0000003C
+#define RXQ_CFG_816X_IPV6_PARSE_ENB 0x00000080
+#define RXQ_CFG_816X_IDT_TBL_SIZE_MASK 0x0001FF00
+#define RXQ_CFG_816X_IDT_TBL_SIZE_SHIFT 8
+#define RXQ_CFG_816X_IDT_TBL_SIZE_DEFAULT 0x100
+
#define ALC_RX_RD_FREE_THRESH 0x15A4 /* 8 bytes unit. */
#define RX_RD_FREE_THRESH_HI_MASK 0x0000003F
#define RX_RD_FREE_THRESH_LO_MASK 0x00000FC0
@@ -559,6 +649,12 @@
#define RX_FIFO_PAUSE_THRESH_HI_MASK 0x0FFF0000
#define RX_FIFO_PAUSE_THRESH_LO_SHIFT 0
#define RX_FIFO_PAUSE_THRESH_HI_SHIFT 16
+/*
+ * Size = tx-packet(1522) + IPG(12) + SOF(8) + 64(Pause) + IPG(12) + SOF(8) +
+ * rx-packet(1522) + delay-of-link(64)
+ * = 3212.
+ */
+#define RX_FIFO_PAUSE_816X_RSVD 3212
#define ALC_RD_DMA_CFG 0x15AC
#define RD_DMA_CFG_THRESH_MASK 0x00000FFF /* 8 bytes unit */
@@ -582,6 +678,7 @@
#define DMA_CFG_OUT_ORDER 0x00000004
#define DMA_CFG_RCB_64 0x00000000
#define DMA_CFG_RCB_128 0x00000008
+#define DMA_CFG_PEND_AUTO_RST 0x00000008
#define DMA_CFG_RD_BURST_128 0x00000000
#define DMA_CFG_RD_BURST_256 0x00000010
#define DMA_CFG_RD_BURST_512 0x00000020
@@ -601,6 +698,14 @@
#define DMA_CFG_SMB_ENB 0x00200000
#define DMA_CFG_CMB_NOW 0x00400000
#define DMA_CFG_SMB_DIS 0x01000000
+#define DMA_CFG_RD_CHNL_SEL_MASK 0x0C000000
+#define DMA_CFG_RD_CHNL_SEL_1 0x00000000
+#define DMA_CFG_RD_CHNL_SEL_2 0x04000000
+#define DMA_CFG_RD_CHNL_SEL_3 0x08000000
+#define DMA_CFG_RD_CHNL_SEL_4 0x0C000000
+#define DMA_CFG_WSRAM_RDCTL 0x10000000
+#define DMA_CFG_RD_PEND_CLR 0x20000000
+#define DMA_CFG_WR_PEND_CLR 0x40000000
#define DMA_CFG_SMB_NOW 0x80000000
#define DMA_CFG_RD_BURST_MASK 0x07
#define DMA_CFG_RD_BURST_SHIFT 4
@@ -623,6 +728,12 @@
#define CMB_TX_TIMER_MASK 0x0000FFFF
#define CMB_TX_TIMER_SHIFT 0
+#define ALC_MSI_MAP_TBL1 0x15D0
+
+#define ALC_MSI_ID_MAP 0x15D4
+
+#define ALC_MSI_MAP_TBL2 0x15D8
+
#define ALC_MBOX_RD0_PROD_IDX 0x15E0
#define ALC_MBOX_RD1_PROD_IDX 0x15E4
@@ -640,12 +751,20 @@
#define MBOX_TD_PROD_HI_IDX_SHIFT 0
#define MBOX_TD_PROD_LO_IDX_SHIFT 16
+#define ALC_MBOX_TD_PRI1_PROD_IDX 0x15F0 /* 16 bits AR816x */
+
+#define ALC_MBOX_TD_PRI0_PROD_IDX 0x15F2 /* 16 bits AR816x */
+
#define ALC_MBOX_TD_CONS_IDX 0x15F4
#define MBOX_TD_CONS_HI_IDX_MASK 0x0000FFFF
#define MBOX_TD_CONS_LO_IDX_MASK 0xFFFF0000
#define MBOX_TD_CONS_HI_IDX_SHIFT 0
#define MBOX_TD_CONS_LO_IDX_SHIFT 16
+#define ALC_MBOX_TD_PRI1_CONS_IDX 0x15F4 /* 16 bits AR816x */
+
+#define ALC_MBOX_TD_PRI0_CONS_IDX 0x15F6 /* 16 bits AR816x */
+
#define ALC_MBOX_RD01_CONS_IDX 0x15F8
#define MBOX_RD0_CONS_IDX_MASK 0x0000FFFF
#define MBOX_RD1_CONS_IDX_MASK 0xFFFF0000
@@ -674,7 +793,7 @@
#define INTR_GPHY 0x00001000
#define INTR_GPHY_LOW_PW 0x00002000
#define INTR_TXQ_TO_RST 0x00004000
-#define INTR_TX_PKT 0x00008000
+#define INTR_TX_PKT0 0x00008000
#define INTR_RX_PKT0 0x00010000
#define INTR_RX_PKT1 0x00020000
#define INTR_RX_PKT2 0x00040000
@@ -688,6 +807,15 @@
#define INTR_PHY_LINK_DOWN 0x04000000
#define INTR_DIS_INT 0x80000000
+/* INTR status for AR816x/AR817x 4 TX queues, 8 RX queues */
+#define INTR_TX_PKT1 0x00000020
+#define INTR_TX_PKT2 0x00000040
+#define INTR_TX_PKT3 0x00000080
+#define INTR_RX_PKT4 0x08000000
+#define INTR_RX_PKT5 0x10000000
+#define INTR_RX_PKT6 0x20000000
+#define INTR_RX_PKT7 0x40000000
+
/* Interrupt Mask Register */
#define ALC_INTR_MASK 0x1604
@@ -699,6 +827,7 @@
(INTR_RD0_UNDERRUN | INTR_RD1_UNDERRUN | \
INTR_RD2_UNDERRUN | INTR_RD3_UNDERRUN)
#else
+#define INTR_TX_PKT INTR_TX_PKT0
#define INTR_RX_PKT INTR_RX_PKT0
#define INTR_RD_UNDERRUN INTR_RD0_UNDERRUN
#endif
@@ -720,11 +849,54 @@
#define HDS_CFG_BACKFILLSIZE_SHIFT 8
#define HDS_CFG_MAX_HDRSIZE_SHIFT 20
+#define ALC_MBOX_TD_PRI3_PROD_IDX 0x1618 /* 16 bits AR816x */
+
+#define ALC_MBOX_TD_PRI2_PROD_IDX 0x161A /* 16 bits AR816x */
+
+#define ALC_MBOX_TD_PRI3_CONS_IDX 0x161C /* 16 bits AR816x */
+
+#define ALC_MBOX_TD_PRI2_CONS_IDX 0x161E /* 16 bits AR816x */
+
/* AR813x/AR815x registers for MAC statistics */
#define ALC_RX_MIB_BASE 0x1700
#define ALC_TX_MIB_BASE 0x1760
+#define ALC_DRV 0x1804 /* AR816x */
+#define DRV_ASPM_SPD10LMT_1M 0x00000000
+#define DRV_ASPM_SPD10LMT_10M 0x00000001
+#define DRV_ASPM_SPD10LMT_100M 0x00000002
+#define DRV_ASPM_SPD10LMT_NO 0x00000003
+#define DRV_ASPM_SPD10LMT_MASK 0x00000003
+#define DRV_ASPM_SPD100LMT_1M 0x00000000
+#define DRV_ASPM_SPD100LMT_10M 0x00000004
+#define DRV_ASPM_SPD100LMT_100M 0x00000008
+#define DRV_ASPM_SPD100LMT_NO 0x0000000C
+#define DRV_ASPM_SPD100LMT_MASK 0x0000000C
+#define DRV_ASPM_SPD1000LMT_100M 0x00000000
+#define DRV_ASPM_SPD1000LMT_NO 0x00000010
+#define DRV_ASPM_SPD1000LMT_1M 0x00000020
+#define DRV_ASPM_SPD1000LMT_10M 0x00000030
+#define DRV_ASPM_SPD1000LMT_MASK 0x00000000
+#define DRV_WOLCAP_BIOS_EN 0x00000100
+#define DRV_WOLMAGIC_EN 0x00000200
+#define DRV_WOLLINKUP_EN 0x00000400
+#define DRV_WOLPATTERN_EN 0x00000800
+#define DRV_AZ_EN 0x00001000
+#define DRV_WOLS5_BIOS_EN 0x00010000
+#define DRV_WOLS5_EN 0x00020000
+#define DRV_DISABLE 0x00040000
+#define DRV_PHY_MASK 0x1FE00000
+#define DRV_PHY_EEE 0x00200000
+#define DRV_PHY_APAUSE 0x00400000
+#define DRV_PHY_PAUSE 0x00800000
+#define DRV_PHY_DUPLEX 0x01000000
+#define DRV_PHY_10 0x02000000
+#define DRV_PHY_100 0x04000000
+#define DRV_PHY_1000 0x08000000
+#define DRV_PHY_AUTO 0x10000000
+#define DRV_PHY_SHIFT 21
+
#define ALC_CLK_GATING_CFG 0x1814
#define CLK_GATING_DMAW_ENB 0x0001
#define CLK_GATING_DMAR_ENB 0x0002
@@ -737,6 +909,52 @@
#define ALC_DEBUG_DATA1 0x1904
+#define ALC_MSI_RETRANS_TIMER 0x1920
+#define MSI_RETRANS_TIMER_MASK 0x0000FFFF
+#define MSI_RETRANS_MASK_SEL_STD 0x00000000
+#define MSI_RETRANS_MASK_SEL_LINE 0x00010000
+#define MSI_RETRANS_TIMER_SHIFT 0
+
+#define ALC_WRR 0x1938
+#define WRR_PRI0_MASK 0x0000001F
+#define WRR_PRI1_MASK 0x00001F00
+#define WRR_PRI2_MASK 0x001F0000
+#define WRR_PRI3_MASK 0x1F000000
+#define WRR_PRI_RESTRICT_MASK 0x60000000
+#define WRR_PRI_RESTRICT_ALL 0x00000000
+#define WRR_PRI_RESTRICT_HI 0x20000000
+#define WRR_PRI_RESTRICT_HI2 0x40000000
+#define WRR_PRI_RESTRICT_NONE 0x60000000
+#define WRR_PRI0_SHIFT 0
+#define WRR_PRI1_SHIFT 8
+#define WRR_PRI2_SHIFT 16
+#define WRR_PRI3_SHIFT 24
+#define WRR_PRI_DEFAULT 4
+#define WRR_PRI_RESTRICT_SHIFT 29
+
+#define ALC_HQTD_CFG 0x193C
+#define HQTD_CFG_Q1_BURST_MASK 0x0000000F
+#define HQTD_CFG_Q2_BURST_MASK 0x000000F0
+#define HQTD_CFG_Q3_BURST_MASK 0x00000F00
+#define HQTD_CFG_BURST_ENB 0x80000000
+#define HQTD_CFG_Q1_BURST_SHIFT 0
+#define HQTD_CFG_Q2_BURST_SHIFT 4
+#define HQTD_CFG_Q3_BURST_SHIFT 8
+
+#define ALC_MISC 0x19C0
+#define MISC_INTNLOSC_OPEN 0x00000008
+#define MISC_ISO_ENB 0x00001000
+#define MISC_PSW_OCP_MASK 0x00E00000
+#define MISC_PSW_OCP_SHIFT 21
+#define MISC_PSW_OCP_DEFAULT 7
+
+#define ALC_MISC2 0x19C8
+#define MISC2_CALB_START 0x00000001
+
+#define ALC_MISC3 0x19CC
+#define MISC3_25M_NOTO_INTNL 0x00000001
+#define MISC3_25M_BY_SW 0x00000002
+
#define ALC_MII_DBG_ADDR 0x1D
#define ALC_MII_DBG_DATA 0x1E
@@ -756,6 +974,9 @@
#define ANA_SEL_CLK125M_DSP 0x8000
#define ANA_MANUL_SWICH_ON_SHIFT 1
+#define MII_DBG_ANACTL 0x00
+#define DBG_ANACTL_DEFAULT 0x02EF
+
#define MII_ANA_CFG4 0x04
#define ANA_IECHO_ADJ_MASK 0x0F
#define ANA_IECHO_ADJ_3_MASK 0x000F
@@ -767,6 +988,9 @@
#define ANA_IECHO_ADJ_1_SHIFT 8
#define ANA_IECHO_ADJ_0_SHIFT 12
+#define MII_DBG_SYSMODCTL 0x04
+#define DBG_SYSMODCTL_DEFAULT 0xBB8B
+
#define MII_ANA_CFG5 0x05
#define ANA_SERDES_CDR_BW_MASK 0x0003
#define ANA_MS_PAD_DBG 0x0004
@@ -783,9 +1007,17 @@
#define ANA_SERDES_CDR_BW_SHIFT 0
#define ANA_SERDES_TH_LOS_SHIFT 4
+#define MII_DBG_SRDSYSMOD 0x05
+#define DBG_SRDSYSMOD_DEFAULT 0x2C46
+
#define MII_ANA_CFG11 0x0B
#define ANA_PS_HIB_EN 0x8000
+#define MII_DBG_HIBNEG 0x0B
+#define DBG_HIBNEG_HIB_PULSE 0x1000
+#define DBG_HIBNEG_PSHIB_EN 0x8000
+#define DBG_HIBNEG_DEFAULT 0xBC40
+
#define MII_ANA_CFG18 0x12
#define ANA_TEST_MODE_10BT_01MASK 0x0003
#define ANA_LOOP_SEL_10BT 0x0004
@@ -800,9 +1032,36 @@
#define ANA_TRIGGER_SEL_TIMER_SHIFT 12
#define ANA_INTERVAL_SEL_TIMER_SHIFT 14
+#define MII_DBG_TST10BTCFG 0x12
+#define DBG_TST10BTCFG_DEFAULT 0x4C04
+
+#define MII_DBG_AZ_ANADECT 0x15
+#define DBG_AZ_ANADECT_DEFAULT 0x3220
+#define DBG_AZ_ANADECT_LONG 0x3210
+
+#define MII_DBG_MSE16DB 0x18
+#define DBG_MSE16DB_UP 0x05EA
+#define DBG_MSE16DB_DOWN 0x02EA
+
+#define MII_DBG_MSE20DB 0x1C
+#define DBG_MSE20DB_TH_MASK 0x01FC
+#define DBG_MSE20DB_TH_DEFAULT 0x2E
+#define DBG_MSE20DB_TH_HI 0x54
+#define DBG_MSE20DB_TH_SHIFT 2
+
+#define MII_DBG_AGC 0x23
+#define DBG_AGC_2_VGA_MASK 0x3F00
+#define DBG_AGC_2_VGA_SHIFT 8
+#define DBG_AGC_LONG1G_LIMT 40
+#define DBG_AGC_LONG100M_LIMT 44
+
#define MII_ANA_CFG41 0x29
#define ANA_TOP_PS_EN 0x8000
+#define MII_DBG_LEGCYPS 0x29
+#define DBG_LEGCYPS_ENB 0x8000
+#define DBG_LEGCYPS_DEFAULT 0x129D
+
#define MII_ANA_CFG54 0x36
#define ANA_LONG_CABLE_TH_100_MASK 0x003F
#define ANA_DESERVED 0x0040
@@ -813,6 +1072,51 @@
#define ANA_LONG_CABLE_TH_100_SHIFT 0
#define ANA_SHORT_CABLE_TH_100_SHIFT 8
+#define MII_DBG_TST100BTCFG 0x36
+#define DBG_TST100BTCFG_DEFAULT 0xE12C
+
+#define MII_DBG_GREENCFG 0x3B
+#define DBG_GREENCFG_DEFAULT 0x7078
+
+#define MII_DBG_GREENCFG2 0x3D
+#define DBG_GREENCFG2_GATE_DFSE_EN 0x0080
+#define DBG_GREENCFG2_BP_GREEN 0x8000
+
+/* Device addr 3 */
+#define MII_EXT_PCS 3
+
+#define MII_EXT_CLDCTL3 0x8003
+#define EXT_CLDCTL3_BP_CABLE1TH_DET_GT 0x8000
+
+#define MII_EXT_CLDCTL5 0x8005
+#define EXT_CLDCTL5_BP_VD_HLFBIAS 0x4000
+
+#define MII_EXT_CLDCTL6 0x8006
+#define EXT_CLDCTL6_CAB_LEN_MASK 0x00FF
+#define EXT_CLDCTL6_CAB_LEN_SHIFT 0
+#define EXT_CLDCTL6_CAB_LEN_SHORT1G 116
+#define EXT_CLDCTL6_CAB_LEN_SHORT100M 152
+
+#define MII_EXT_VDRVBIAS 0x8062
+#define EXT_VDRVBIAS_DEFAULT 3
+
+/* Device addr 7 */
+#define MII_EXT_ANEG 7
+
+#define MII_EXT_ANEG_LOCAL_EEEADV 0x3C
+#define ANEG_LOCA_EEEADV_100BT 0x0002
+#define ANEG_LOCA_EEEADV_1000BT 0x0004
+
+#define MII_EXT_ANEG_AFE 0x801A
+#define ANEG_AFEE_10BT_100M_TH 0x0040
+
+#define MII_EXT_ANEG_S3DIG10 0x8023
+#define ANEG_S3DIG10_SL 0x0001
+#define ANEG_S3DIG10_DEFAULT 0
+
+#define MII_EXT_ANEG_NLP78 0x8027
+#define ANEG_NLP78_120M_DEFAULT 0x8A05
+
/* Statistics counters collected by the MAC. */
struct smb {
/* Rx stats. */
@@ -860,7 +1164,6 @@ struct smb {
uint32_t tx_multi_colls;
uint32_t tx_late_colls;
uint32_t tx_excess_colls;
- uint32_t tx_abort;
uint32_t tx_underrun;
uint32_t tx_desc_underrun;
uint32_t tx_lenerrs;
diff --git a/sys/dev/alc/if_alcvar.h b/sys/dev/alc/if_alcvar.h
index f2d806f..9a73ef4 100644
--- a/sys/dev/alc/if_alcvar.h
+++ b/sys/dev/alc/if_alcvar.h
@@ -52,6 +52,10 @@
/* Water mark to kick reclaiming Tx buffers. */
#define ALC_TX_DESC_HIWAT ((ALC_TX_RING_CNT * 6) / 10)
+/*
+ * AR816x controllers support up to 16 messages but this driver
+ * uses single message.
+ */
#define ALC_MSI_MESSAGES 1
#define ALC_MSIX_MESSAGES 1
@@ -224,12 +228,13 @@ struct alc_softc {
#define ALC_FLAG_PM 0x0010
#define ALC_FLAG_FASTETHER 0x0020
#define ALC_FLAG_JUMBO 0x0040
-#define ALC_FLAG_ASPM_MON 0x0080
#define ALC_FLAG_CMB_BUG 0x0100
#define ALC_FLAG_SMB_BUG 0x0200
#define ALC_FLAG_L0S 0x0400
#define ALC_FLAG_L1S 0x0800
#define ALC_FLAG_APS 0x1000
+#define ALC_FLAG_AR816X_FAMILY 0x2000
+#define ALC_FLAG_LINK_WAR 0x4000
#define ALC_FLAG_LINK 0x8000
struct callout alc_tick_ch;
diff --git a/sys/dev/ale/if_ale.c b/sys/dev/ale/if_ale.c
index 78dfa0e..3a728f4 100644
--- a/sys/dev/ale/if_ale.c
+++ b/sys/dev/ale/if_ale.c
@@ -946,8 +946,6 @@ ale_sysctl_node(struct ale_softc *sc)
&stats->tx_late_colls, "Late collisions");
ALE_SYSCTL_STAT_ADD32(ctx, child, "excess_colls",
&stats->tx_excess_colls, "Excessive collisions");
- ALE_SYSCTL_STAT_ADD32(ctx, child, "abort",
- &stats->tx_abort, "Aborted frames due to Excessive collisions");
ALE_SYSCTL_STAT_ADD32(ctx, child, "underruns",
&stats->tx_underrun, "FIFO underruns");
ALE_SYSCTL_STAT_ADD32(ctx, child, "desc_underruns",
@@ -2197,7 +2195,6 @@ ale_stats_update(struct ale_softc *sc)
stat->tx_multi_colls += smb->tx_multi_colls;
stat->tx_late_colls += smb->tx_late_colls;
stat->tx_excess_colls += smb->tx_excess_colls;
- stat->tx_abort += smb->tx_abort;
stat->tx_underrun += smb->tx_underrun;
stat->tx_desc_underrun += smb->tx_desc_underrun;
stat->tx_lenerrs += smb->tx_lenerrs;
@@ -2210,17 +2207,10 @@ ale_stats_update(struct ale_softc *sc)
if_inc_counter(ifp, IFCOUNTER_COLLISIONS, smb->tx_single_colls +
smb->tx_multi_colls * 2 + smb->tx_late_colls +
- smb->tx_abort * HDPX_CFG_RETRY_DEFAULT);
+ smb->tx_excess_colls * HDPX_CFG_RETRY_DEFAULT);
- /*
- * XXX
- * tx_pkts_truncated counter looks suspicious. It constantly
- * increments with no sign of Tx errors. This may indicate
- * the counter name is not correct one so I've removed the
- * counter in output errors.
- */
- if_inc_counter(ifp, IFCOUNTER_OERRORS,
- smb->tx_abort + smb->tx_late_colls + smb->tx_underrun);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, smb->tx_late_colls +
+ smb->tx_excess_colls + smb->tx_underrun + smb->tx_pkts_truncated);
if_inc_counter(ifp, IFCOUNTER_IPACKETS, smb->rx_frames);
diff --git a/sys/dev/ale/if_alereg.h b/sys/dev/ale/if_alereg.h
index 445af99..5804c53 100644
--- a/sys/dev/ale/if_alereg.h
+++ b/sys/dev/ale/if_alereg.h
@@ -605,7 +605,6 @@ struct smb {
uint32_t tx_multi_colls;
uint32_t tx_late_colls;
uint32_t tx_excess_colls;
- uint32_t tx_abort;
uint32_t tx_underrun;
uint32_t tx_desc_underrun;
uint32_t tx_lenerrs;
diff --git a/sys/dev/cxgbe/common/t4_msg.h b/sys/dev/cxgbe/common/t4_msg.h
index ef8fbe6..c30b6f1f 100644
--- a/sys/dev/cxgbe/common/t4_msg.h
+++ b/sys/dev/cxgbe/common/t4_msg.h
@@ -273,6 +273,7 @@ union opcode_tid {
/* extract the TID from a CPL command */
#define GET_TID(cmd) (G_TID(ntohl(OPCODE_TID(cmd))))
+#define GET_OPCODE(cmd) ((cmd)->ot.opcode)
/* partitioning of TID fields that also carry a queue id */
#define S_TID_TID 0
diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c
index 9973fa5..425c563 100644
--- a/sys/dev/cxgbe/tom/t4_connect.c
+++ b/sys/dev/cxgbe/tom/t4_connect.c
@@ -115,8 +115,8 @@ do_act_establish(struct sge_iq *iq, const struct rss_header *rss,
{
struct adapter *sc = iq->adapter;
const struct cpl_act_establish *cpl = (const void *)(rss + 1);
- unsigned int tid = GET_TID(cpl);
- unsigned int atid = G_TID_TID(ntohl(cpl->tos_atid));
+ u_int tid = GET_TID(cpl);
+ u_int atid = G_TID_TID(ntohl(cpl->tos_atid));
struct toepcb *toep = lookup_atid(sc, atid);
struct inpcb *inp = toep->inp;
@@ -178,17 +178,34 @@ act_open_rpl_status_to_errno(int status)
}
}
+void
+act_open_failure_cleanup(struct adapter *sc, u_int atid, u_int status)
+{
+ struct toepcb *toep = lookup_atid(sc, atid);
+ struct inpcb *inp = toep->inp;
+ struct toedev *tod = &toep->td->tod;
+
+ free_atid(sc, atid);
+ toep->tid = -1;
+
+ if (status != EAGAIN)
+ INP_INFO_WLOCK(&V_tcbinfo);
+ INP_WLOCK(inp);
+ toe_connect_failed(tod, inp, status);
+ final_cpl_received(toep); /* unlocks inp */
+ if (status != EAGAIN)
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+}
+
static int
do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
struct mbuf *m)
{
struct adapter *sc = iq->adapter;
const struct cpl_act_open_rpl *cpl = (const void *)(rss + 1);
- unsigned int atid = G_TID_TID(G_AOPEN_ATID(be32toh(cpl->atid_status)));
- unsigned int status = G_AOPEN_STATUS(be32toh(cpl->atid_status));
+ u_int atid = G_TID_TID(G_AOPEN_ATID(be32toh(cpl->atid_status)));
+ u_int status = G_AOPEN_STATUS(be32toh(cpl->atid_status));
struct toepcb *toep = lookup_atid(sc, atid);
- struct inpcb *inp = toep->inp;
- struct toedev *tod = &toep->td->tod;
int rc;
KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
@@ -200,20 +217,11 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
if (negative_advice(status))
return (0);
- free_atid(sc, atid);
- toep->tid = -1;
-
if (status && act_open_has_tid(status))
release_tid(sc, GET_TID(cpl), toep->ctrlq);
rc = act_open_rpl_status_to_errno(status);
- if (rc != EAGAIN)
- INP_INFO_WLOCK(&V_tcbinfo);
- INP_WLOCK(inp);
- toe_connect_failed(tod, inp, rc);
- final_cpl_received(toep); /* unlocks inp */
- if (rc != EAGAIN)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ act_open_failure_cleanup(sc, atid, rc);
return (0);
}
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index 109543a6..71ea1df 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -98,6 +98,7 @@ static void t4_clip_task(void *, int);
static void update_clip_table(struct adapter *, struct tom_data *);
static void destroy_clip_table(struct adapter *, struct tom_data *);
static void free_tom_data(struct adapter *, struct tom_data *);
+static void reclaim_wr_resources(void *, int);
static int in6_ifaddr_gen;
static eventhandler_tag ifaddr_evhandler;
@@ -903,6 +904,8 @@ free_tom_data(struct adapter *sc, struct tom_data *td)
if (td->listen_mask != 0)
hashdestroy(td->listen_hash, M_CXGBE, td->listen_mask);
+ if (mtx_initialized(&td->unsent_wr_lock))
+ mtx_destroy(&td->unsent_wr_lock);
if (mtx_initialized(&td->lctx_hash_lock))
mtx_destroy(&td->lctx_hash_lock);
if (mtx_initialized(&td->toep_list_lock))
@@ -912,6 +915,44 @@ free_tom_data(struct adapter *sc, struct tom_data *td)
free(td, M_CXGBE);
}
+static void
+reclaim_wr_resources(void *arg, int count)
+{
+ struct tom_data *td = arg;
+ STAILQ_HEAD(, wrqe) twr_list = STAILQ_HEAD_INITIALIZER(twr_list);
+ struct cpl_act_open_req *cpl;
+ u_int opcode, atid;
+ struct wrqe *wr;
+ struct adapter *sc;
+
+ mtx_lock(&td->unsent_wr_lock);
+ STAILQ_SWAP(&td->unsent_wr_list, &twr_list, wrqe);
+ mtx_unlock(&td->unsent_wr_lock);
+
+ while ((wr = STAILQ_FIRST(&twr_list)) != NULL) {
+ STAILQ_REMOVE_HEAD(&twr_list, link);
+
+ cpl = wrtod(wr);
+ opcode = GET_OPCODE(cpl);
+
+ switch (opcode) {
+ case CPL_ACT_OPEN_REQ:
+ case CPL_ACT_OPEN_REQ6:
+ atid = G_TID_TID(be32toh(OPCODE_TID(cpl)));
+ sc = td_adapter(td);
+
+ CTR2(KTR_CXGBE, "%s: atid %u ", __func__, atid);
+ act_open_failure_cleanup(sc, atid, EHOSTUNREACH);
+ free(wr, M_CXGBE);
+ break;
+ default:
+ log(LOG_ERR, "%s: leaked work request %p, wr_len %d, "
+ "opcode %x\n", __func__, wr, wr->wr_len, opcode);
+ /* WR not freed here; go look at it with a debugger. */
+ }
+ }
+}
+
/*
* Ground control to Major TOM
* Commencing countdown, engines on
@@ -939,6 +980,11 @@ t4_tom_activate(struct adapter *sc)
td->listen_hash = hashinit_flags(LISTEN_HASH_SIZE, M_CXGBE,
&td->listen_mask, HASH_NOWAIT);
+ /* List of WRs for which L2 resolution failed */
+ mtx_init(&td->unsent_wr_lock, "Unsent WR list lock", NULL, MTX_DEF);
+ STAILQ_INIT(&td->unsent_wr_list);
+ TASK_INIT(&td->reclaim_wr_resources, 0, reclaim_wr_resources, td);
+
/* TID tables */
rc = alloc_tid_tabs(&sc->tids);
if (rc != 0)
@@ -1012,6 +1058,12 @@ t4_tom_deactivate(struct adapter *sc)
rc = EBUSY;
mtx_unlock(&td->lctx_hash_lock);
+ taskqueue_drain(taskqueue_thread, &td->reclaim_wr_resources);
+ mtx_lock(&td->unsent_wr_lock);
+ if (!STAILQ_EMPTY(&td->unsent_wr_list))
+ rc = EBUSY;
+ mtx_unlock(&td->unsent_wr_lock);
+
if (rc == 0) {
unregister_toedev(sc->tom_softc);
free_tom_data(sc, td);
diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h
index 1d883fe..5b68074 100644
--- a/sys/dev/cxgbe/tom/t4_tom.h
+++ b/sys/dev/cxgbe/tom/t4_tom.h
@@ -210,6 +210,11 @@ struct tom_data {
struct mtx clip_table_lock;
struct clip_head clip_table;
int clip_gen;
+
+ /* WRs that will not be sent to the chip because L2 resolution failed */
+ struct mtx unsent_wr_lock;
+ STAILQ_HEAD(, wrqe) unsent_wr_list;
+ struct task reclaim_wr_resources;
};
static inline struct tom_data *
@@ -252,6 +257,7 @@ void release_lip(struct tom_data *, struct clip_entry *);
void t4_init_connect_cpl_handlers(struct adapter *);
int t4_connect(struct toedev *, struct socket *, struct rtentry *,
struct sockaddr *);
+void act_open_failure_cleanup(struct adapter *, u_int, u_int);
/* t4_listen.c */
void t4_init_listen_cpl_handlers(struct adapter *);
diff --git a/sys/dev/cxgbe/tom/t4_tom_l2t.c b/sys/dev/cxgbe/tom/t4_tom_l2t.c
index 7a75394..65f7d23 100644
--- a/sys/dev/cxgbe/tom/t4_tom_l2t.c
+++ b/sys/dev/cxgbe/tom/t4_tom_l2t.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rwlock.h>
#include <sys/socket.h>
#include <sys/sbuf.h>
+#include <sys/taskqueue.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/ethernet.h>
@@ -161,25 +162,17 @@ send_pending(struct adapter *sc, struct l2t_entry *e)
}
static void
-resolution_failed_for_wr(struct wrqe *wr)
+resolution_failed(struct adapter *sc, struct l2t_entry *e)
{
- log(LOG_ERR, "%s: leaked work request %p, wr_len %d\n", __func__, wr,
- wr->wr_len);
-
- /* free(wr, M_CXGBE); */
-}
-
-static void
-resolution_failed(struct l2t_entry *e)
-{
- struct wrqe *wr;
+ struct tom_data *td = sc->tom_softc;
mtx_assert(&e->lock, MA_OWNED);
- while ((wr = STAILQ_FIRST(&e->wr_list)) != NULL) {
- STAILQ_REMOVE_HEAD(&e->wr_list, link);
- resolution_failed_for_wr(wr);
- }
+ mtx_lock(&td->unsent_wr_lock);
+ STAILQ_CONCAT(&td->unsent_wr_list, &e->wr_list);
+ mtx_unlock(&td->unsent_wr_lock);
+
+ taskqueue_enqueue(taskqueue_thread, &td->reclaim_wr_resources);
}
static void
@@ -203,7 +196,7 @@ update_entry(struct adapter *sc, struct l2t_entry *e, uint8_t *lladdr,
* need to wlock the table).
*/
e->state = L2T_STATE_FAILED;
- resolution_failed(e);
+ resolution_failed(sc, e);
return;
} else if (lladdr == NULL) {
@@ -305,12 +298,11 @@ again:
if (e->state == L2T_STATE_VALID && !STAILQ_EMPTY(&e->wr_list))
send_pending(sc, e);
if (e->state == L2T_STATE_FAILED)
- resolution_failed(e);
+ resolution_failed(sc, e);
mtx_unlock(&e->lock);
break;
case L2T_STATE_FAILED:
- resolution_failed_for_wr(wr);
return (EHOSTUNREACH);
}
diff --git a/sys/dev/drm2/i915/intel_ringbuffer.c b/sys/dev/drm2/i915/intel_ringbuffer.c
index 26bc695..89a5c94 100644
--- a/sys/dev/drm2/i915/intel_ringbuffer.c
+++ b/sys/dev/drm2/i915/intel_ringbuffer.c
@@ -366,7 +366,7 @@ init_pipe_control(struct intel_ring_buffer *ring)
goto err_unpin;
pmap_qenter((uintptr_t)pc->cpu_page, &obj->pages[0], 1);
pmap_invalidate_cache_range((vm_offset_t)pc->cpu_page,
- (vm_offset_t)pc->cpu_page + PAGE_SIZE);
+ (vm_offset_t)pc->cpu_page + PAGE_SIZE, FALSE);
pc->obj = obj;
ring->private = pc;
@@ -1014,7 +1014,7 @@ static int init_status_page(struct intel_ring_buffer *ring)
pmap_qenter((vm_offset_t)ring->status_page.page_addr, &obj->pages[0],
1);
pmap_invalidate_cache_range((vm_offset_t)ring->status_page.page_addr,
- (vm_offset_t)ring->status_page.page_addr + PAGE_SIZE);
+ (vm_offset_t)ring->status_page.page_addr + PAGE_SIZE, FALSE);
ring->status_page.obj = obj;
memset(ring->status_page.page_addr, 0, PAGE_SIZE);
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index 792f303..a2bcf73 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -1796,7 +1796,7 @@ iap_is_event_architectural(enum pmc_event pe, enum pmc_event *map)
switch (pe) {
case PMC_EV_IAP_ARCH_UNH_COR_CYC:
ae = CORE_AE_UNHALTED_CORE_CYCLES;
- *map = PMC_EV_IAP_EVENT_C4H_00H;
+ *map = PMC_EV_IAP_EVENT_3CH_00H;
break;
case PMC_EV_IAP_ARCH_INS_RET:
ae = CORE_AE_INSTRUCTION_RETIRED;
diff --git a/sys/dev/iscsi/icl.c b/sys/dev/iscsi/icl.c
index af59407..5a6436a 100644
--- a/sys/dev/iscsi/icl.c
+++ b/sys/dev/iscsi/icl.c
@@ -771,6 +771,7 @@ icl_receive_thread(void *arg)
ICL_CONN_LOCK(ic);
ic->ic_receive_running = false;
+ cv_signal(&ic->ic_send_cv);
ICL_CONN_UNLOCK(ic);
kthread_exit();
}
@@ -872,8 +873,6 @@ icl_conn_send_pdus(struct icl_conn *ic, struct icl_pdu_stailq *queue)
SOCKBUF_UNLOCK(&so->so_snd);
while (!STAILQ_EMPTY(queue)) {
- if (ic->ic_disconnecting)
- return;
request = STAILQ_FIRST(queue);
size = icl_pdu_size(request);
if (available < size) {
@@ -970,11 +969,6 @@ icl_send_thread(void *arg)
ic->ic_send_running = true;
for (;;) {
- if (ic->ic_disconnecting) {
- //ICL_DEBUG("terminating");
- break;
- }
-
for (;;) {
/*
* If the local queue is empty, populate it from
@@ -1013,6 +1007,11 @@ icl_send_thread(void *arg)
break;
}
+ if (ic->ic_disconnecting) {
+ //ICL_DEBUG("terminating");
+ break;
+ }
+
cv_wait(&ic->ic_send_cv, ic->ic_lock);
}
@@ -1023,6 +1022,7 @@ icl_send_thread(void *arg)
STAILQ_CONCAT(&ic->ic_to_send, &queue);
ic->ic_send_running = false;
+ cv_signal(&ic->ic_send_cv);
ICL_CONN_UNLOCK(ic);
kthread_exit();
}
@@ -1296,21 +1296,6 @@ icl_conn_handoff(struct icl_conn *ic, int fd)
}
void
-icl_conn_shutdown(struct icl_conn *ic)
-{
- ICL_CONN_LOCK_ASSERT_NOT(ic);
-
- ICL_CONN_LOCK(ic);
- if (ic->ic_socket == NULL) {
- ICL_CONN_UNLOCK(ic);
- return;
- }
- ICL_CONN_UNLOCK(ic);
-
- soshutdown(ic->ic_socket, SHUT_RDWR);
-}
-
-void
icl_conn_close(struct icl_conn *ic)
{
struct icl_pdu *pdu;
@@ -1342,15 +1327,11 @@ icl_conn_close(struct icl_conn *ic)
/*
* Wake up the threads, so they can properly terminate.
*/
- cv_signal(&ic->ic_receive_cv);
- cv_signal(&ic->ic_send_cv);
while (ic->ic_receive_running || ic->ic_send_running) {
//ICL_DEBUG("waiting for send/receive threads to terminate");
- ICL_CONN_UNLOCK(ic);
cv_signal(&ic->ic_receive_cv);
cv_signal(&ic->ic_send_cv);
- pause("icl_close", 1 * hz);
- ICL_CONN_LOCK(ic);
+ cv_wait(&ic->ic_send_cv, ic->ic_lock);
}
//ICL_DEBUG("send/receive threads terminated");
diff --git a/sys/dev/iscsi/icl.h b/sys/dev/iscsi/icl.h
index 5f03434..ca5ee8f 100644
--- a/sys/dev/iscsi/icl.h
+++ b/sys/dev/iscsi/icl.h
@@ -107,7 +107,6 @@ struct icl_conn {
struct icl_conn *icl_conn_new(const char *name, struct mtx *lock);
void icl_conn_free(struct icl_conn *ic);
int icl_conn_handoff(struct icl_conn *ic, int fd);
-void icl_conn_shutdown(struct icl_conn *ic);
void icl_conn_close(struct icl_conn *ic);
bool icl_conn_connected(struct icl_conn *ic);
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index e11b2b6..1576f7d 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -367,7 +367,6 @@ static void
iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
{
- icl_conn_shutdown(is->is_conn);
icl_conn_close(is->is_conn);
ISCSI_SESSION_LOCK(is);
diff --git a/sys/dev/mmc/host/dwmmc.c b/sys/dev/mmc/host/dwmmc.c
new file mode 100644
index 0000000..79fe69b
--- /dev/null
+++ b/sys/dev/mmc/host/dwmmc.c
@@ -0,0 +1,1101 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * 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:
+ * 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.
+ */
+
+/*
+ * Synopsys DesignWare Mobile Storage Host Controller
+ * Chapter 14, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/mmc/host/dwmmc.h>
+
+#include "mmcbr_if.h"
+
+#define dprintf(x, arg...)
+
+#define READ4(_sc, _reg) \
+ bus_read_4((_sc)->res[0], _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_write_4((_sc)->res[0], _reg, _val)
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#define DWMMC_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define DWMMC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define DWMMC_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
+ "dwmmc", MTX_DEF)
+#define DWMMC_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define DWMMC_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define DWMMC_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+#define PENDING_CMD 0x01
+#define PENDING_STOP 0x02
+#define CARD_INIT_DONE 0x04
+
+#define DWMMC_DATA_ERR_FLAGS (SDMMC_INTMASK_DRT | SDMMC_INTMASK_DCRC \
+ |SDMMC_INTMASK_HTO | SDMMC_INTMASK_SBE \
+ |SDMMC_INTMASK_EBE)
+#define DWMMC_CMD_ERR_FLAGS (SDMMC_INTMASK_RTO | SDMMC_INTMASK_RCRC \
+ |SDMMC_INTMASK_RE)
+#define DWMMC_ERR_FLAGS (DWMMC_DATA_ERR_FLAGS | DWMMC_CMD_ERR_FLAGS \
+ |SDMMC_INTMASK_HLE)
+
+#define DES0_DIC (1 << 1)
+#define DES0_LD (1 << 2)
+#define DES0_FS (1 << 3)
+#define DES0_CH (1 << 4)
+#define DES0_ER (1 << 5)
+#define DES0_CES (1 << 30)
+#define DES0_OWN (1 << 31)
+
+#define DES1_BS1_MASK 0xfff
+#define DES1_BS1_SHIFT 0
+
+struct idmac_desc {
+ uint32_t des0; /* control */
+ uint32_t des1; /* bufsize */
+ uint32_t des2; /* buf1 phys addr */
+ uint32_t des3; /* buf2 phys addr or next descr */
+};
+
+#define DESC_COUNT 256
+#define DESC_SIZE (sizeof(struct idmac_desc) * DESC_COUNT)
+#define DEF_MSIZE 0x2 /* Burst size of multiple transaction */
+
+struct dwmmc_softc {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ void *intr_cookie;
+ struct mmc_host host;
+ struct mtx sc_mtx;
+ struct mmc_request *req;
+ struct mmc_command *curcmd;
+ uint32_t flags;
+ uint32_t hwtype;
+ uint32_t use_auto_stop;
+
+ bus_dma_tag_t desc_tag;
+ bus_dmamap_t desc_map;
+ struct idmac_desc *desc_ring;
+ bus_addr_t desc_ring_paddr;
+ bus_dma_tag_t buf_tag;
+ bus_dmamap_t buf_map;
+
+ uint32_t bus_busy;
+ uint32_t dto_rcvd;
+ uint32_t acd_rcvd;
+ uint32_t cmd_done;
+ uint32_t bus_hz;
+ uint32_t fifo_depth;
+ uint32_t num_slots;
+ uint32_t sdr_timing;
+ uint32_t ddr_timing;
+};
+
+static void dwmmc_next_operation(struct dwmmc_softc *);
+static int dwmmc_setup_bus(struct dwmmc_softc *, int);
+static int dma_done(struct dwmmc_softc *, struct mmc_command *);
+static int dma_stop(struct dwmmc_softc *);
+
+static struct resource_spec dwmmc_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+enum {
+ HWTYPE_NONE,
+ HWTYPE_ALTERA,
+ HWTYPE_EXYNOS,
+};
+
+#define HWTYPE_MASK (0x0000ffff)
+#define HWFLAG_MASK (0xffff << 16)
+
+static struct ofw_compat_data compat_data[] = {
+ {"altr,socfpga-dw-mshc", HWTYPE_ALTERA},
+ {"samsung,exynos5420-dw-mshc", HWTYPE_EXYNOS},
+ {NULL, HWTYPE_NONE},
+};
+
+static void
+dwmmc_get1paddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+ if (error != 0)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+static void
+dwmmc_ring_setup(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct dwmmc_softc *sc;
+ int idx;
+
+ if (error != 0)
+ return;
+
+ sc = arg;
+
+ dprintf("nsegs %d seg0len %lu\n", nsegs, segs[0].ds_len);
+
+ for (idx = 0; idx < nsegs; idx++) {
+ sc->desc_ring[idx].des0 = (DES0_OWN | DES0_DIC | DES0_CH);
+ sc->desc_ring[idx].des1 = segs[idx].ds_len;
+ sc->desc_ring[idx].des2 = segs[idx].ds_addr;
+
+ if (idx == 0)
+ sc->desc_ring[idx].des0 |= DES0_FS;
+
+ if (idx == (nsegs - 1)) {
+ sc->desc_ring[idx].des0 &= ~(DES0_DIC | DES0_CH);
+ sc->desc_ring[idx].des0 |= DES0_LD;
+ }
+ }
+}
+
+static int
+dwmmc_ctrl_reset(struct dwmmc_softc *sc, int reset_bits)
+{
+ int reg;
+ int i;
+
+ reg = READ4(sc, SDMMC_CTRL);
+ reg |= (reset_bits);
+ WRITE4(sc, SDMMC_CTRL, reg);
+
+ /* Wait reset done */
+ for (i = 0; i < 100; i++) {
+ if (!(READ4(sc, SDMMC_CTRL) & reset_bits))
+ return (0);
+ DELAY(10);
+ };
+
+ device_printf(sc->dev, "Reset failed\n");
+
+ return (1);
+}
+
+static int
+dma_setup(struct dwmmc_softc *sc)
+{
+ int error;
+ int nidx;
+ int idx;
+
+ /*
+ * Set up TX descriptor ring, descriptors, and dma maps.
+ */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* Parent tag. */
+ 4096, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ DESC_SIZE, 1, /* maxsize, nsegments */
+ DESC_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->desc_tag);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create ring DMA tag.\n");
+ return (1);
+ }
+
+ error = bus_dmamem_alloc(sc->desc_tag, (void**)&sc->desc_ring,
+ BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
+ &sc->desc_map);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not allocate descriptor ring.\n");
+ return (1);
+ }
+
+ error = bus_dmamap_load(sc->desc_tag, sc->desc_map,
+ sc->desc_ring, DESC_SIZE, dwmmc_get1paddr,
+ &sc->desc_ring_paddr, 0);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not load descriptor ring map.\n");
+ return (1);
+ }
+
+ for (idx = 0; idx < DESC_COUNT; idx++) {
+ sc->desc_ring[idx].des0 = DES0_CH;
+ sc->desc_ring[idx].des1 = 0;
+ nidx = (idx + 1) % DESC_COUNT;
+ sc->desc_ring[idx].des3 = sc->desc_ring_paddr + \
+ (nidx * sizeof(struct idmac_desc));
+ }
+
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* Parent tag. */
+ 4096, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ DESC_COUNT*MMC_SECTOR_SIZE, /* maxsize */
+ DESC_COUNT, /* nsegments */
+ MMC_SECTOR_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->buf_tag);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create ring DMA tag.\n");
+ return (1);
+ }
+
+ error = bus_dmamap_create(sc->buf_tag, 0,
+ &sc->buf_map);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create TX buffer DMA map.\n");
+ return (1);
+ }
+
+ return (0);
+}
+
+static void
+dwmmc_cmd_done(struct dwmmc_softc *sc)
+{
+ struct mmc_command *cmd;
+
+ cmd = sc->curcmd;
+ if (cmd == NULL)
+ return;
+
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136) {
+ cmd->resp[3] = READ4(sc, SDMMC_RESP0);
+ cmd->resp[2] = READ4(sc, SDMMC_RESP1);
+ cmd->resp[1] = READ4(sc, SDMMC_RESP2);
+ cmd->resp[0] = READ4(sc, SDMMC_RESP3);
+ } else {
+ cmd->resp[3] = 0;
+ cmd->resp[2] = 0;
+ cmd->resp[1] = 0;
+ cmd->resp[0] = READ4(sc, SDMMC_RESP0);
+ }
+ }
+}
+
+static void
+dwmmc_tasklet(struct dwmmc_softc *sc)
+{
+ struct mmc_command *cmd;
+
+ cmd = sc->curcmd;
+ if (cmd == NULL)
+ return;
+
+ if (!sc->cmd_done)
+ return;
+
+ if (cmd->error != MMC_ERR_NONE || !cmd->data) {
+ dwmmc_next_operation(sc);
+ } else if (cmd->data && sc->dto_rcvd) {
+ if ((cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK ||
+ cmd->opcode == MMC_READ_MULTIPLE_BLOCK) &&
+ sc->use_auto_stop) {
+ if (sc->acd_rcvd)
+ dwmmc_next_operation(sc);
+ } else {
+ dwmmc_next_operation(sc);
+ }
+ }
+}
+
+static void
+dwmmc_intr(void *arg)
+{
+ struct mmc_command *cmd;
+ struct dwmmc_softc *sc;
+ uint32_t reg;
+
+ sc = arg;
+
+ DWMMC_LOCK(sc);
+
+ cmd = sc->curcmd;
+
+ /* First handle SDMMC controller interrupts */
+ reg = READ4(sc, SDMMC_MINTSTS);
+ if (reg) {
+ dprintf("%s 0x%08x\n", __func__, reg);
+
+ if (reg & DWMMC_CMD_ERR_FLAGS) {
+ WRITE4(sc, SDMMC_RINTSTS, DWMMC_CMD_ERR_FLAGS);
+ dprintf("cmd err 0x%08x cmd 0x%08x\n",
+ reg, cmd->opcode);
+ cmd->error = MMC_ERR_TIMEOUT;
+ }
+
+ if (reg & DWMMC_DATA_ERR_FLAGS) {
+ WRITE4(sc, SDMMC_RINTSTS, DWMMC_DATA_ERR_FLAGS);
+ dprintf("data err 0x%08x cmd 0x%08x\n",
+ reg, cmd->opcode);
+ cmd->error = MMC_ERR_FAILED;
+ dma_done(sc, cmd);
+ dma_stop(sc);
+ }
+
+ if (reg & SDMMC_INTMASK_CMD_DONE) {
+ dwmmc_cmd_done(sc);
+ sc->cmd_done = 1;
+ WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_CMD_DONE);
+ }
+
+ if (reg & SDMMC_INTMASK_ACD) {
+ sc->acd_rcvd = 1;
+ WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_ACD);
+ }
+
+ if (reg & SDMMC_INTMASK_DTO) {
+ sc->dto_rcvd = 1;
+ WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_DTO);
+ }
+
+ if (reg & SDMMC_INTMASK_CD) {
+ /* XXX: Handle card detect */
+ WRITE4(sc, SDMMC_RINTSTS, SDMMC_INTMASK_CD);
+ }
+ }
+
+ /* Now handle DMA interrupts */
+ reg = READ4(sc, SDMMC_IDSTS);
+ if (reg) {
+ dprintf("dma intr 0x%08x\n", reg);
+ if (reg & (SDMMC_IDINTEN_TI | SDMMC_IDINTEN_RI)) {
+ WRITE4(sc, SDMMC_IDSTS, (SDMMC_IDINTEN_TI |
+ SDMMC_IDINTEN_RI));
+ WRITE4(sc, SDMMC_IDSTS, SDMMC_IDINTEN_NI);
+ dma_done(sc, cmd);
+ }
+ }
+
+ dwmmc_tasklet(sc);
+
+ DWMMC_UNLOCK(sc);
+}
+
+static int
+parse_fdt(struct dwmmc_softc *sc)
+{
+ pcell_t dts_value[3];
+ phandle_t node;
+ int len;
+
+ if ((node = ofw_bus_get_node(sc->dev)) == -1)
+ return (ENXIO);
+
+ /* fifo-depth */
+ if ((len = OF_getproplen(node, "fifo-depth")) <= 0)
+ return (ENXIO);
+ OF_getencprop(node, "fifo-depth", dts_value, len);
+ sc->fifo_depth = dts_value[0];
+
+ /* num-slots */
+ if ((len = OF_getproplen(node, "num-slots")) <= 0)
+ return (ENXIO);
+ OF_getencprop(node, "num-slots", dts_value, len);
+ sc->num_slots = dts_value[0];
+
+ /*
+ * We need some platform-specific code to know
+ * what the clock is supplied for our device.
+ * For now rely on the value specified in FDT.
+ */
+ if ((len = OF_getproplen(node, "bus-frequency")) <= 0)
+ return (ENXIO);
+ OF_getencprop(node, "bus-frequency", dts_value, len);
+ sc->bus_hz = dts_value[0];
+
+ /*
+ * Platform-specific stuff
+ * XXX: Move to separate file
+ */
+
+ if ((sc->hwtype & HWTYPE_MASK) != HWTYPE_EXYNOS)
+ return (0);
+
+ if ((len = OF_getproplen(node, "samsung,dw-mshc-ciu-div")) <= 0)
+ return (ENXIO);
+ OF_getencprop(node, "samsung,dw-mshc-ciu-div", dts_value, len);
+ sc->sdr_timing = (dts_value[0] << SDMMC_CLKSEL_DIVIDER_SHIFT);
+ sc->ddr_timing = (dts_value[0] << SDMMC_CLKSEL_DIVIDER_SHIFT);
+
+ if ((len = OF_getproplen(node, "samsung,dw-mshc-sdr-timing")) <= 0)
+ return (ENXIO);
+ OF_getencprop(node, "samsung,dw-mshc-sdr-timing", dts_value, len);
+ sc->sdr_timing |= ((dts_value[0] << SDMMC_CLKSEL_SAMPLE_SHIFT) |
+ (dts_value[1] << SDMMC_CLKSEL_DRIVE_SHIFT));
+
+ if ((len = OF_getproplen(node, "samsung,dw-mshc-ddr-timing")) <= 0)
+ return (ENXIO);
+ OF_getencprop(node, "samsung,dw-mshc-ddr-timing", dts_value, len);
+ sc->ddr_timing |= ((dts_value[0] << SDMMC_CLKSEL_SAMPLE_SHIFT) |
+ (dts_value[1] << SDMMC_CLKSEL_DRIVE_SHIFT));
+
+ return (0);
+}
+
+static int
+dwmmc_probe(device_t dev)
+{
+ uintptr_t hwtype;
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ if (hwtype == HWTYPE_NONE)
+ return (ENXIO);
+
+ device_set_desc(dev, "Synopsys DesignWare Mobile "
+ "Storage Host Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+dwmmc_attach(device_t dev)
+{
+ struct dwmmc_softc *sc;
+ device_t child;
+ int error;
+ int slot;
+
+ sc = device_get_softc(dev);
+
+ sc->dev = dev;
+ sc->hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+
+ /* Why not to use Auto Stop? It save a hundred of irq per second */
+ sc->use_auto_stop = 1;
+
+ error = parse_fdt(sc);
+ if (error != 0) {
+ device_printf(dev, "Can't get FDT property.\n");
+ return (ENXIO);
+ }
+
+ DWMMC_LOCK_INIT(sc);
+
+ if (bus_alloc_resources(dev, dwmmc_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Setup interrupt handler. */
+ error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, dwmmc_intr, sc, &sc->intr_cookie);
+ if (error != 0) {
+ device_printf(dev, "could not setup interrupt handler.\n");
+ return (ENXIO);
+ }
+
+ device_printf(dev, "Hardware version ID is %04x\n",
+ READ4(sc, SDMMC_VERID) & 0xffff);
+
+ WRITE4(sc, EMMCP_MPSBEGIN0, 0);
+ WRITE4(sc, EMMCP_SEND0, 0);
+ WRITE4(sc, EMMCP_CTRL0, (MPSCTRL_SECURE_READ_BIT |
+ MPSCTRL_SECURE_WRITE_BIT |
+ MPSCTRL_NON_SECURE_READ_BIT |
+ MPSCTRL_NON_SECURE_WRITE_BIT |
+ MPSCTRL_VALID));
+
+ /* XXX: we support operation for slot index 0 only */
+ slot = 0;
+ WRITE4(sc, SDMMC_PWREN, (1 << slot));
+
+ /* Reset all */
+ if (dwmmc_ctrl_reset(sc, (SDMMC_CTRL_RESET |
+ SDMMC_CTRL_FIFO_RESET |
+ SDMMC_CTRL_DMA_RESET)))
+ return (ENXIO);
+
+ dwmmc_setup_bus(sc, sc->host.f_min);
+
+ if (dma_setup(sc))
+ return (ENXIO);
+
+ /* Install desc base */
+ WRITE4(sc, SDMMC_DBADDR, sc->desc_ring_paddr);
+
+ /* Enable DMA interrupts */
+ WRITE4(sc, SDMMC_IDSTS, SDMMC_IDINTEN_MASK);
+ WRITE4(sc, SDMMC_IDINTEN, (SDMMC_IDINTEN_NI |
+ SDMMC_IDINTEN_RI |
+ SDMMC_IDINTEN_TI));
+
+ /* Clear and disable interrups for a while */
+ WRITE4(sc, SDMMC_RINTSTS, 0xffffffff);
+ WRITE4(sc, SDMMC_INTMASK, 0);
+
+ /* Maximum timeout */
+ WRITE4(sc, SDMMC_TMOUT, 0xffffffff);
+
+ /* Enable interrupts */
+ WRITE4(sc, SDMMC_RINTSTS, 0xffffffff);
+ WRITE4(sc, SDMMC_INTMASK, (SDMMC_INTMASK_CMD_DONE |
+ SDMMC_INTMASK_DTO |
+ SDMMC_INTMASK_ACD |
+ SDMMC_INTMASK_TXDR |
+ SDMMC_INTMASK_RXDR |
+ DWMMC_ERR_FLAGS |
+ SDMMC_INTMASK_CD));
+ WRITE4(sc, SDMMC_CTRL, SDMMC_CTRL_INT_ENABLE);
+
+ sc->host.f_min = 400000;
+ sc->host.f_max = 200000000;
+ sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
+ sc->host.caps = MMC_CAP_4_BIT_DATA;
+
+ child = device_add_child(dev, "mmc", 0);
+ return (bus_generic_attach(dev));
+}
+
+static int
+dwmmc_setup_bus(struct dwmmc_softc *sc, int freq)
+{
+ int tout;
+ int div;
+
+ if (freq == 0) {
+ WRITE4(sc, SDMMC_CLKENA, 0);
+ WRITE4(sc, SDMMC_CMD, (SDMMC_CMD_WAIT_PRVDATA |
+ SDMMC_CMD_UPD_CLK_ONLY | SDMMC_CMD_START));
+
+ tout = 1000;
+ do {
+ if (tout-- < 0) {
+ device_printf(sc->dev, "Failed update clk\n");
+ return (1);
+ }
+ } while (READ4(sc, SDMMC_CMD) & SDMMC_CMD_START);
+
+ return (0);
+ }
+
+ WRITE4(sc, SDMMC_CLKENA, 0);
+ WRITE4(sc, SDMMC_CLKSRC, 0);
+
+ div = (sc->bus_hz != freq) ? DIV_ROUND_UP(sc->bus_hz, 2 * freq) : 0;
+
+ WRITE4(sc, SDMMC_CLKDIV, div);
+ WRITE4(sc, SDMMC_CMD, (SDMMC_CMD_WAIT_PRVDATA |
+ SDMMC_CMD_UPD_CLK_ONLY | SDMMC_CMD_START));
+
+ tout = 1000;
+ do {
+ if (tout-- < 0) {
+ device_printf(sc->dev, "Failed to update clk");
+ return (1);
+ }
+ } while (READ4(sc, SDMMC_CMD) & SDMMC_CMD_START);
+
+ WRITE4(sc, SDMMC_CLKENA, (SDMMC_CLKENA_CCLK_EN | SDMMC_CLKENA_LP));
+ WRITE4(sc, SDMMC_CMD, SDMMC_CMD_WAIT_PRVDATA |
+ SDMMC_CMD_UPD_CLK_ONLY | SDMMC_CMD_START);
+
+ tout = 1000;
+ do {
+ if (tout-- < 0) {
+ device_printf(sc->dev, "Failed to enable clk\n");
+ return (1);
+ }
+ } while (READ4(sc, SDMMC_CMD) & SDMMC_CMD_START);
+
+ return (0);
+}
+
+static int
+dwmmc_update_ios(device_t brdev, device_t reqdev)
+{
+ struct dwmmc_softc *sc;
+ struct mmc_ios *ios;
+
+ sc = device_get_softc(brdev);
+ ios = &sc->host.ios;
+
+ dprintf("Setting up clk %u bus_width %d\n",
+ ios->clock, ios->bus_width);
+
+ dwmmc_setup_bus(sc, ios->clock);
+
+ if (ios->bus_width == bus_width_8)
+ WRITE4(sc, SDMMC_CTYPE, SDMMC_CTYPE_8BIT);
+ else if (ios->bus_width == bus_width_4)
+ WRITE4(sc, SDMMC_CTYPE, SDMMC_CTYPE_4BIT);
+ else
+ WRITE4(sc, SDMMC_CTYPE, 0);
+
+ if ((sc->hwtype & HWTYPE_MASK) == HWTYPE_EXYNOS) {
+ /* XXX: take care about DDR or SDR use here */
+ WRITE4(sc, SDMMC_CLKSEL, sc->sdr_timing);
+ }
+
+ /*
+ * XXX: take care about DDR bit
+ *
+ * reg = READ4(sc, SDMMC_UHS_REG);
+ * reg |= (SDMMC_UHS_REG_DDR);
+ * WRITE4(sc, SDMMC_UHS_REG, reg);
+ */
+
+ return (0);
+}
+
+static int
+dma_done(struct dwmmc_softc *sc, struct mmc_command *cmd)
+{
+ struct mmc_data *data;
+
+ data = cmd->data;
+
+ if (data->flags & MMC_DATA_WRITE)
+ bus_dmamap_sync(sc->buf_tag, sc->buf_map,
+ BUS_DMASYNC_POSTWRITE);
+ else
+ bus_dmamap_sync(sc->buf_tag, sc->buf_map,
+ BUS_DMASYNC_POSTREAD);
+
+ bus_dmamap_unload(sc->buf_tag, sc->buf_map);
+
+ return (0);
+}
+
+static int
+dma_stop(struct dwmmc_softc *sc)
+{
+ int reg;
+
+ reg = READ4(sc, SDMMC_CTRL);
+ reg &= ~(SDMMC_CTRL_USE_IDMAC);
+ reg |= (SDMMC_CTRL_DMA_RESET);
+ WRITE4(sc, SDMMC_CTRL, reg);
+
+ reg = READ4(sc, SDMMC_BMOD);
+ reg &= ~(SDMMC_BMOD_DE | SDMMC_BMOD_FB);
+ reg |= (SDMMC_BMOD_SWR);
+ WRITE4(sc, SDMMC_BMOD, reg);
+
+ return (0);
+}
+
+static int
+dma_prepare(struct dwmmc_softc *sc, struct mmc_command *cmd)
+{
+ struct mmc_data *data;
+ int len;
+ int err;
+ int reg;
+
+ data = cmd->data;
+ len = data->len;
+
+ reg = READ4(sc, SDMMC_INTMASK);
+ reg &= ~(SDMMC_INTMASK_TXDR | SDMMC_INTMASK_RXDR);
+ WRITE4(sc, SDMMC_INTMASK, reg);
+
+ err = bus_dmamap_load(sc->buf_tag, sc->buf_map,
+ data->data, data->len, dwmmc_ring_setup,
+ sc, BUS_DMA_NOWAIT);
+ if (err != 0)
+ panic("dmamap_load failed\n");
+
+ if (data->flags & MMC_DATA_WRITE)
+ bus_dmamap_sync(sc->buf_tag, sc->buf_map,
+ BUS_DMASYNC_PREWRITE);
+ else
+ bus_dmamap_sync(sc->buf_tag, sc->buf_map,
+ BUS_DMASYNC_PREREAD);
+
+ reg = (DEF_MSIZE << SDMMC_FIFOTH_MSIZE_S);
+ reg |= ((sc->fifo_depth / 2) - 1) << SDMMC_FIFOTH_RXWMARK_S;
+ reg |= (sc->fifo_depth / 2) << SDMMC_FIFOTH_TXWMARK_S;
+
+ WRITE4(sc, SDMMC_FIFOTH, reg);
+ wmb();
+
+ reg = READ4(sc, SDMMC_CTRL);
+ reg |= (SDMMC_CTRL_USE_IDMAC | SDMMC_CTRL_DMA_ENABLE);
+ WRITE4(sc, SDMMC_CTRL, reg);
+ wmb();
+
+ reg = READ4(sc, SDMMC_BMOD);
+ reg |= (SDMMC_BMOD_DE | SDMMC_BMOD_FB);
+ WRITE4(sc, SDMMC_BMOD, reg);
+
+ /* Start */
+ WRITE4(sc, SDMMC_PLDMND, 1);
+
+ return (0);
+}
+
+static void
+dwmmc_start_cmd(struct dwmmc_softc *sc, struct mmc_command *cmd)
+{
+ struct mmc_data *data;
+ uint32_t blksz;
+ uint32_t cmdr;
+
+ sc->curcmd = cmd;
+ data = cmd->data;
+
+ /* XXX Upper layers don't always set this */
+ cmd->mrq = sc->req;
+
+ /* Begin setting up command register. */
+
+ cmdr = cmd->opcode;
+
+ dprintf("cmd->opcode 0x%08x\n", cmd->opcode);
+
+ if (cmd->opcode == MMC_STOP_TRANSMISSION ||
+ cmd->opcode == MMC_GO_IDLE_STATE ||
+ cmd->opcode == MMC_GO_INACTIVE_STATE)
+ cmdr |= SDMMC_CMD_STOP_ABORT;
+ else if (cmd->opcode != MMC_SEND_STATUS && data)
+ cmdr |= SDMMC_CMD_WAIT_PRVDATA;
+
+ /* Set up response handling. */
+ if (MMC_RSP(cmd->flags) != MMC_RSP_NONE) {
+ cmdr |= SDMMC_CMD_RESP_EXP;
+ if (cmd->flags & MMC_RSP_136)
+ cmdr |= SDMMC_CMD_RESP_LONG;
+ }
+
+ if (cmd->flags & MMC_RSP_CRC)
+ cmdr |= SDMMC_CMD_RESP_CRC;
+
+ /*
+ * XXX: Not all platforms want this.
+ */
+ cmdr |= SDMMC_CMD_USE_HOLD_REG;
+
+ if ((sc->flags & CARD_INIT_DONE) == 0) {
+ sc->flags |= (CARD_INIT_DONE);
+ cmdr |= SDMMC_CMD_SEND_INIT;
+ }
+
+ if (data) {
+ if ((cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK ||
+ cmd->opcode == MMC_READ_MULTIPLE_BLOCK) &&
+ sc->use_auto_stop)
+ cmdr |= SDMMC_CMD_SEND_ASTOP;
+
+ cmdr |= SDMMC_CMD_DATA_EXP;
+ if (data->flags & MMC_DATA_STREAM)
+ cmdr |= SDMMC_CMD_MODE_STREAM;
+ if (data->flags & MMC_DATA_WRITE)
+ cmdr |= SDMMC_CMD_DATA_WRITE;
+
+ WRITE4(sc, SDMMC_TMOUT, 0xffffffff);
+ WRITE4(sc, SDMMC_BYTCNT, data->len);
+ blksz = (data->len < MMC_SECTOR_SIZE) ? \
+ data->len : MMC_SECTOR_SIZE;
+ WRITE4(sc, SDMMC_BLKSIZ, blksz);
+
+ dma_prepare(sc, cmd);
+ wmb();
+ }
+
+ dprintf("cmdr 0x%08x\n", cmdr);
+
+ WRITE4(sc, SDMMC_CMDARG, cmd->arg);
+ wmb();
+ WRITE4(sc, SDMMC_CMD, cmdr | SDMMC_CMD_START);
+};
+
+static void
+dwmmc_next_operation(struct dwmmc_softc *sc)
+{
+ struct mmc_request *req;
+
+ req = sc->req;
+ if (req == NULL)
+ return;
+
+ sc->acd_rcvd = 0;
+ sc->dto_rcvd = 0;
+ sc->cmd_done = 0;
+
+ /*
+ * XXX: Wait until card is still busy.
+ * We do need this to prevent data timeouts,
+ * mostly caused by multi-block write command
+ * followed by single-read.
+ */
+ while(READ4(sc, SDMMC_STATUS) & (SDMMC_STATUS_DATA_BUSY))
+ continue;
+
+ if (sc->flags & PENDING_CMD) {
+ sc->flags &= ~PENDING_CMD;
+ dwmmc_start_cmd(sc, req->cmd);
+ return;
+ } else if (sc->flags & PENDING_STOP && !sc->use_auto_stop) {
+ sc->flags &= ~PENDING_STOP;
+ dwmmc_start_cmd(sc, req->stop);
+ return;
+ }
+
+ sc->req = NULL;
+ sc->curcmd = NULL;
+ req->done(req);
+}
+
+static int
+dwmmc_request(device_t brdev, device_t reqdev, struct mmc_request *req)
+{
+ struct dwmmc_softc *sc;
+
+ sc = device_get_softc(brdev);
+
+ dprintf("%s\n", __func__);
+
+ DWMMC_LOCK(sc);
+
+ if (sc->req != NULL) {
+ DWMMC_UNLOCK(sc);
+ return (EBUSY);
+ }
+
+ sc->req = req;
+ sc->flags |= PENDING_CMD;
+ if (sc->req->stop)
+ sc->flags |= PENDING_STOP;
+ dwmmc_next_operation(sc);
+
+ DWMMC_UNLOCK(sc);
+ return (0);
+}
+
+static int
+dwmmc_get_ro(device_t brdev, device_t reqdev)
+{
+
+ dprintf("%s\n", __func__);
+
+ return (0);
+}
+
+static int
+dwmmc_acquire_host(device_t brdev, device_t reqdev)
+{
+ struct dwmmc_softc *sc;
+
+ sc = device_get_softc(brdev);
+
+ DWMMC_LOCK(sc);
+ while (sc->bus_busy)
+ msleep(sc, &sc->sc_mtx, PZERO, "dwmmcah", hz / 5);
+ sc->bus_busy++;
+ DWMMC_UNLOCK(sc);
+ return (0);
+}
+
+static int
+dwmmc_release_host(device_t brdev, device_t reqdev)
+{
+ struct dwmmc_softc *sc;
+
+ sc = device_get_softc(brdev);
+
+ DWMMC_LOCK(sc);
+ sc->bus_busy--;
+ wakeup(sc);
+ DWMMC_UNLOCK(sc);
+ return (0);
+}
+
+static int
+dwmmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
+{
+ struct dwmmc_softc *sc;
+
+ sc = device_get_softc(bus);
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ *(int *)result = sc->host.ios.bus_mode;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ *(int *)result = sc->host.ios.bus_width;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ *(int *)result = sc->host.ios.chip_select;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ *(int *)result = sc->host.ios.clock;
+ break;
+ case MMCBR_IVAR_F_MIN:
+ *(int *)result = sc->host.f_min;
+ break;
+ case MMCBR_IVAR_F_MAX:
+ *(int *)result = sc->host.f_max;
+ break;
+ case MMCBR_IVAR_HOST_OCR:
+ *(int *)result = sc->host.host_ocr;
+ break;
+ case MMCBR_IVAR_MODE:
+ *(int *)result = sc->host.mode;
+ break;
+ case MMCBR_IVAR_OCR:
+ *(int *)result = sc->host.ocr;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ *(int *)result = sc->host.ios.power_mode;
+ break;
+ case MMCBR_IVAR_VDD:
+ *(int *)result = sc->host.ios.vdd;
+ break;
+ case MMCBR_IVAR_CAPS:
+ sc->host.caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+ *(int *)result = sc->host.caps;
+ break;
+ case MMCBR_IVAR_MAX_DATA:
+ *(int *)result = DESC_COUNT;
+ }
+ return (0);
+}
+
+static int
+dwmmc_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
+{
+ struct dwmmc_softc *sc;
+
+ sc = device_get_softc(bus);
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ sc->host.ios.bus_mode = value;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ sc->host.ios.bus_width = value;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ sc->host.ios.chip_select = value;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ sc->host.ios.clock = value;
+ break;
+ case MMCBR_IVAR_MODE:
+ sc->host.mode = value;
+ break;
+ case MMCBR_IVAR_OCR:
+ sc->host.ocr = value;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ sc->host.ios.power_mode = value;
+ break;
+ case MMCBR_IVAR_VDD:
+ sc->host.ios.vdd = value;
+ break;
+ /* These are read-only */
+ case MMCBR_IVAR_CAPS:
+ case MMCBR_IVAR_HOST_OCR:
+ case MMCBR_IVAR_F_MIN:
+ case MMCBR_IVAR_F_MAX:
+ case MMCBR_IVAR_MAX_DATA:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static device_method_t dwmmc_methods[] = {
+ DEVMETHOD(device_probe, dwmmc_probe),
+ DEVMETHOD(device_attach, dwmmc_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, dwmmc_read_ivar),
+ DEVMETHOD(bus_write_ivar, dwmmc_write_ivar),
+
+ /* mmcbr_if */
+ DEVMETHOD(mmcbr_update_ios, dwmmc_update_ios),
+ DEVMETHOD(mmcbr_request, dwmmc_request),
+ DEVMETHOD(mmcbr_get_ro, dwmmc_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, dwmmc_acquire_host),
+ DEVMETHOD(mmcbr_release_host, dwmmc_release_host),
+
+ DEVMETHOD_END
+};
+
+static driver_t dwmmc_driver = {
+ "dwmmc",
+ dwmmc_methods,
+ sizeof(struct dwmmc_softc),
+};
+
+static devclass_t dwmmc_devclass;
+
+DRIVER_MODULE(dwmmc, simplebus, dwmmc_driver, dwmmc_devclass, 0, 0);
+
diff --git a/sys/dev/mmc/host/dwmmc.h b/sys/dev/mmc/host/dwmmc.h
new file mode 100644
index 0000000..8f763cd
--- /dev/null
+++ b/sys/dev/mmc/host/dwmmc.h
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * 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:
+ * 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$
+ */
+
+#define SDMMC_CTRL 0x0 /* Control Register */
+#define SDMMC_CTRL_USE_IDMAC (1 << 25) /* Use Internal DMAC */
+#define SDMMC_CTRL_DMA_ENABLE (1 << 5) /* */
+#define SDMMC_CTRL_INT_ENABLE (1 << 4) /* Enable interrupts */
+#define SDMMC_CTRL_DMA_RESET (1 << 2) /* Reset DMA */
+#define SDMMC_CTRL_FIFO_RESET (1 << 1) /* Reset FIFO */
+#define SDMMC_CTRL_RESET (1 << 0) /* Reset SD/MMC controller */
+#define SDMMC_PWREN 0x4 /* Power Enable Register */
+#define SDMMC_PWREN_PE (1 << 0) /* Power On */
+#define SDMMC_CLKDIV 0x8 /* Clock Divider Register */
+#define SDMMC_CLKSRC 0xC /* SD Clock Source Register */
+#define SDMMC_CLKENA 0x10 /* Clock Enable Register */
+#define SDMMC_CLKENA_LP (1 << 16) /* Low-power mode */
+#define SDMMC_CLKENA_CCLK_EN (1 << 0) /* SD/MMC Enable */
+#define SDMMC_TMOUT 0x14 /* Timeout Register */
+#define SDMMC_CTYPE 0x18 /* Card Type Register */
+#define SDMMC_CTYPE_8BIT (1 << 16)
+#define SDMMC_CTYPE_4BIT (1 << 0)
+#define SDMMC_BLKSIZ 0x1C /* Block Size Register */
+#define SDMMC_BYTCNT 0x20 /* Byte Count Register */
+#define SDMMC_INTMASK 0x24 /* Interrupt Mask Register */
+#define SDMMC_INTMASK_SDIO (1 << 16) /* SDIO Interrupt Enable */
+#define SDMMC_INTMASK_EBE (1 << 15) /* End-bit error */
+#define SDMMC_INTMASK_ACD (1 << 14) /* Auto command done */
+#define SDMMC_INTMASK_SBE (1 << 13) /* Start-bit error */
+#define SDMMC_INTMASK_HLE (1 << 12) /* Hardware locked write err */
+#define SDMMC_INTMASK_FRUN (1 << 11) /* FIFO underrun/overrun err */
+#define SDMMC_INTMASK_HTO (1 << 10) /* Data starvation by host timeout */
+#define SDMMC_INTMASK_DRT (1 << 9) /* Data read timeout */
+#define SDMMC_INTMASK_RTO (1 << 8) /* Response timeout */
+#define SDMMC_INTMASK_DCRC (1 << 7) /* Data CRC error */
+#define SDMMC_INTMASK_RCRC (1 << 6) /* Response CRC error */
+#define SDMMC_INTMASK_RXDR (1 << 5) /* Receive FIFO data request */
+#define SDMMC_INTMASK_TXDR (1 << 4) /* Transmit FIFO data request */
+#define SDMMC_INTMASK_DTO (1 << 3) /* Data transfer over */
+#define SDMMC_INTMASK_CMD_DONE (1 << 2) /* Command done */
+#define SDMMC_INTMASK_RE (1 << 1) /* Response error */
+#define SDMMC_INTMASK_CD (1 << 0) /* Card Detected */
+#define SDMMC_CMDARG 0x28 /* Command Argument Register */
+#define SDMMC_CMD 0x2C /* Command Register */
+#define SDMMC_CMD_START (1 << 31)
+#define SDMMC_CMD_USE_HOLD_REG (1 << 29)
+#define SDMMC_CMD_UPD_CLK_ONLY (1 << 21) /* Update clk only */
+#define SDMMC_CMD_SEND_INIT (1 << 15) /* Send initialization */
+#define SDMMC_CMD_STOP_ABORT (1 << 14) /* stop current data transfer */
+#define SDMMC_CMD_WAIT_PRVDATA (1 << 13) /* Wait for prev data transfer completion */
+#define SDMMC_CMD_SEND_ASTOP (1 << 12) /* Send stop command at end of data tx/rx */
+#define SDMMC_CMD_MODE_STREAM (1 << 11) /* Stream data transfer */
+#define SDMMC_CMD_DATA_WRITE (1 << 10) /* Write to card */
+#define SDMMC_CMD_DATA_EXP (1 << 9) /* Data transfer expected */
+#define SDMMC_CMD_RESP_CRC (1 << 8) /* Check Response CRC */
+#define SDMMC_CMD_RESP_LONG (1 << 7) /* Long response expected */
+#define SDMMC_CMD_RESP_EXP (1 << 6) /* Response expected */
+#define SDMMC_RESP0 0x30 /* Response Register 0 */
+#define SDMMC_RESP1 0x34 /* Response Register 1 */
+#define SDMMC_RESP2 0x38 /* Response Register 2 */
+#define SDMMC_RESP3 0x3C /* Response Register 3 */
+#define SDMMC_MINTSTS 0x40 /* Masked Interrupt Status Register */
+#define SDMMC_RINTSTS 0x44 /* Raw Interrupt Status Register */
+#define SDMMC_STATUS 0x48 /* Status Register */
+#define SDMMC_STATUS_DATA_BUSY (1 << 9) /* card_data[0] */
+#define SDMMC_FIFOTH 0x4C /* FIFO Threshold Watermark Register */
+#define SDMMC_FIFOTH_MSIZE_S 28 /* Burst size of multiple transaction */
+#define SDMMC_FIFOTH_RXWMARK_S 16 /* FIFO threshold watermark level */
+#define SDMMC_FIFOTH_TXWMARK_S 0 /* FIFO threshold watermark level */
+#define SDMMC_CDETECT 0x50 /* Card Detect Register */
+#define SDMMC_WRTPRT 0x54 /* Write Protect Register */
+#define SDMMC_TCBCNT 0x5C /* Transferred CIU Card Byte Count */
+#define SDMMC_TBBCNT 0x60 /* Transferred Host to BIU-FIFO Byte Count */
+#define SDMMC_DEBNCE 0x64 /* Debounce Count Register */
+#define SDMMC_USRID 0x68 /* User ID Register */
+#define SDMMC_VERID 0x6C /* Version ID Register */
+#define SDMMC_HCON 0x70 /* Hardware Configuration Register */
+#define SDMMC_UHS_REG 0x74 /* UHS-1 Register */
+#define SDMMC_UHS_REG_DDR (1 << 16) /* DDR mode */
+#define SDMMC_RST_N 0x78 /* Hardware Reset Register */
+#define SDMMC_BMOD 0x80 /* Bus Mode Register */
+#define SDMMC_BMOD_DE (1 << 7) /* IDMAC Enable */
+#define SDMMC_BMOD_FB (1 << 1) /* AHB Master Fixed Burst */
+#define SDMMC_BMOD_SWR (1 << 0) /* Reset DMA */
+#define SDMMC_PLDMND 0x84 /* Poll Demand Register */
+#define SDMMC_DBADDR 0x88 /* Descriptor List Base Address */
+#define SDMMC_IDSTS 0x8C /* Internal DMAC Status Register */
+#define SDMMC_IDINTEN 0x90 /* Internal DMAC Interrupt Enable */
+#define SDMMC_IDINTEN_AI (1 << 9) /* Abnormal Interrupt Summary */
+#define SDMMC_IDINTEN_NI (1 << 8) /* Normal Interrupt Summary */
+#define SDMMC_IDINTEN_CES (1 << 5) /* Card Error Summary */
+#define SDMMC_IDINTEN_DU (1 << 4) /* Descriptor Unavailable */
+#define SDMMC_IDINTEN_FBE (1 << 2) /* Fatal Bus Error */
+#define SDMMC_IDINTEN_RI (1 << 1) /* Receive Interrupt */
+#define SDMMC_IDINTEN_TI (1 << 0) /* Transmit Interrupt */
+#define SDMMC_IDINTEN_MASK (SDMMC_IDINTEN_AI | SDMMC_IDINTEN_NI | SDMMC_IDINTEN_CES | \
+ SDMMC_IDINTEN_DU | SDMMC_IDINTEN_FBE | SDMMC_IDINTEN_RI | \
+ SDMMC_IDINTEN_TI)
+#define SDMMC_DSCADDR 0x94 /* Current Host Descriptor Address */
+#define SDMMC_BUFADDR 0x98 /* Current Buffer Descriptor Address */
+#define SDMMC_CARDTHRCTL 0x100 /* Card Threshold Control Register */
+#define SDMMC_BACK_END_POWER_R 0x104 /* Back End Power Register */
+#define SDMMC_DATA 0x200 /* Data FIFO Access */
+
+/* eMMC */
+#define EMMCP_MPSBEGIN0 0x1200 /* */
+#define EMMCP_SEND0 0x1204 /* */
+#define EMMCP_CTRL0 0x120C /* */
+#define MPSCTRL_SECURE_READ_BIT (1 << 7)
+#define MPSCTRL_SECURE_WRITE_BIT (1 << 6)
+#define MPSCTRL_NON_SECURE_READ_BIT (1 << 5)
+#define MPSCTRL_NON_SECURE_WRITE_BIT (1 << 4)
+#define MPSCTRL_USE_FUSE_KEY (1 << 3)
+#define MPSCTRL_ECB_MODE (1 << 2)
+#define MPSCTRL_ENCRYPTION (1 << 1)
+#define MPSCTRL_VALID (1 << 0)
+
+/* Platform-specific defines */
+#define SDMMC_CLKSEL 0x9C
+#define SDMMC_CLKSEL_SAMPLE_SHIFT 0
+#define SDMMC_CLKSEL_DRIVE_SHIFT 16
+#define SDMMC_CLKSEL_DIVIDER_SHIFT 24
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index 8b6e1a8..a7762ba 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -1773,4 +1773,5 @@ DRIVER_MODULE(mmc, sdhci_imx, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci_pci, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci_ti, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, ti_mmchs, mmc_driver, mmc_devclass, NULL, NULL);
+DRIVER_MODULE(mmc, dwmmc, mmc_driver, mmc_devclass, NULL, NULL);
diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c
index 97e815c..7ddae71 100644
--- a/sys/dev/mpr/mpr_sas.c
+++ b/sys/dev/mpr/mpr_sas.c
@@ -1043,6 +1043,9 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb)
case 0x0a:
sas->bitrate = 600000;
break;
+ case 0x0b:
+ sas->bitrate = 1200000;
+ break;
default:
sas->valid = 0;
}
diff --git a/sys/dev/mpr/mpr_table.c b/sys/dev/mpr/mpr_table.c
index b1e12b3..6e7797e 100644
--- a/sys/dev/mpr/mpr_table.c
+++ b/sys/dev/mpr/mpr_table.c
@@ -118,6 +118,7 @@ struct mpr_table_lookup mpr_linkrate_names[] = {
{"1.5Gbps", 0x08},
{"3.0Gbps", 0x09},
{"6.0Gbps", 0x0a},
+ {"12.0Gbps", 0x0b},
{NULL, 0},
{"LinkRate Unknown", 0x00}
};
diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c
index b740128..ba15848 100644
--- a/sys/dev/mrsas/mrsas.c
+++ b/sys/dev/mrsas/mrsas.c
@@ -1,43 +1,38 @@
/*
- * Copyright (c) 2014, LSI Corp.
- * All rights reserved.
- * Author: Marian Choy
+ * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
* Support: freebsdraid@lsi.com
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name of the <ORGANIZATION> 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 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 HOLDER 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
+ * 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
+ * <ORGANIZATION> 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 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 HOLDER 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.
*
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing
* official policies,either expressed or implied, of the FreeBSD Project.
*
- * Send feedback to: <megaraidfbsd@lsi.com>
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: MegaRaid FreeBSD
+ * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621
+ * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
*
*/
@@ -54,18 +49,23 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/kthread.h>
#include <sys/taskqueue.h>
+#include <sys/smp.h>
-/*
- * Function prototypes
+/*
+ * Function prototypes
*/
-static d_open_t mrsas_open;
-static d_close_t mrsas_close;
-static d_read_t mrsas_read;
-static d_write_t mrsas_write;
-static d_ioctl_t mrsas_ioctl;
+static d_open_t mrsas_open;
+static d_close_t mrsas_close;
+static d_read_t mrsas_read;
+static d_write_t mrsas_write;
+static d_ioctl_t mrsas_ioctl;
+static d_poll_t mrsas_poll;
+static struct mrsas_mgmt_info mrsas_mgmt_info;
static struct mrsas_ident *mrsas_find_ident(device_t);
+static int mrsas_setup_msix(struct mrsas_softc *sc);
+static int mrsas_allocate_msix(struct mrsas_softc *sc);
static void mrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode);
static void mrsas_flush_cache(struct mrsas_softc *sc);
static void mrsas_reset_reply_desc(struct mrsas_softc *sc);
@@ -79,456 +79,476 @@ static int mrsas_setup_irq(struct mrsas_softc *sc);
static int mrsas_alloc_mem(struct mrsas_softc *sc);
static int mrsas_init_fw(struct mrsas_softc *sc);
static int mrsas_setup_raidmap(struct mrsas_softc *sc);
-static int mrsas_complete_cmd(struct mrsas_softc *sc);
+static int mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex);
static int mrsas_clear_intr(struct mrsas_softc *sc);
-static int mrsas_get_ctrl_info(struct mrsas_softc *sc,
- struct mrsas_ctrl_info *ctrl_info);
-static int mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc,
- struct mrsas_mfi_cmd *cmd_to_abort);
+static int
+mrsas_get_ctrl_info(struct mrsas_softc *sc,
+ struct mrsas_ctrl_info *ctrl_info);
+static int
+mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc,
+ struct mrsas_mfi_cmd *cmd_to_abort);
u_int32_t mrsas_read_reg(struct mrsas_softc *sc, int offset);
-u_int8_t mrsas_build_mptmfi_passthru(struct mrsas_softc *sc,
- struct mrsas_mfi_cmd *mfi_cmd);
-int mrsas_transition_to_ready(struct mrsas_softc *sc, int ocr);
-int mrsas_init_adapter(struct mrsas_softc *sc);
-int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc);
-int mrsas_alloc_ioc_cmd(struct mrsas_softc *sc);
-int mrsas_alloc_ctlr_info_cmd(struct mrsas_softc *sc);
-int mrsas_ioc_init(struct mrsas_softc *sc);
-int mrsas_bus_scan(struct mrsas_softc *sc);
-int mrsas_issue_dcmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
-int mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
-int mrsas_reset_ctrl(struct mrsas_softc *sc);
-int mrsas_wait_for_outstanding(struct mrsas_softc *sc);
-int mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
- struct mrsas_mfi_cmd *cmd);
-int mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd,
- int size);
-void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
-void mrsas_wakeup(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
-void mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
-void mrsas_complete_abort(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
-void mrsas_disable_intr(struct mrsas_softc *sc);
-void mrsas_enable_intr(struct mrsas_softc *sc);
-void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
-void mrsas_free_mem(struct mrsas_softc *sc);
-void mrsas_free_tmp_dcmd(struct mrsas_tmp_dcmd *tmp);
-void mrsas_isr(void *arg);
-void mrsas_teardown_intr(struct mrsas_softc *sc);
-void mrsas_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
-void mrsas_kill_hba (struct mrsas_softc *sc);
-void mrsas_aen_handler(struct mrsas_softc *sc);
-void mrsas_write_reg(struct mrsas_softc *sc, int offset,
- u_int32_t value);
-void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo,
- u_int32_t req_desc_hi);
-void mrsas_free_ctlr_info_cmd(struct mrsas_softc *sc);
-void mrsas_complete_mptmfi_passthru(struct mrsas_softc *sc,
- struct mrsas_mfi_cmd *cmd, u_int8_t status);
-void mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status,
- u_int8_t extStatus);
-struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc);
-MRSAS_REQUEST_DESCRIPTOR_UNION * mrsas_build_mpt_cmd(struct mrsas_softc *sc,
- struct mrsas_mfi_cmd *cmd);
+u_int8_t
+mrsas_build_mptmfi_passthru(struct mrsas_softc *sc,
+ struct mrsas_mfi_cmd *mfi_cmd);
+int mrsas_transition_to_ready(struct mrsas_softc *sc, int ocr);
+int mrsas_init_adapter(struct mrsas_softc *sc);
+int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc);
+int mrsas_alloc_ioc_cmd(struct mrsas_softc *sc);
+int mrsas_alloc_ctlr_info_cmd(struct mrsas_softc *sc);
+int mrsas_ioc_init(struct mrsas_softc *sc);
+int mrsas_bus_scan(struct mrsas_softc *sc);
+int mrsas_issue_dcmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
+int mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
+int mrsas_reset_ctrl(struct mrsas_softc *sc);
+int mrsas_wait_for_outstanding(struct mrsas_softc *sc);
+int
+mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
+ struct mrsas_mfi_cmd *cmd);
+int
+mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd,
+ int size);
+void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
+void mrsas_wakeup(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
+void mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
+void mrsas_complete_abort(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
+void mrsas_disable_intr(struct mrsas_softc *sc);
+void mrsas_enable_intr(struct mrsas_softc *sc);
+void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
+void mrsas_free_mem(struct mrsas_softc *sc);
+void mrsas_free_tmp_dcmd(struct mrsas_tmp_dcmd *tmp);
+void mrsas_isr(void *arg);
+void mrsas_teardown_intr(struct mrsas_softc *sc);
+void mrsas_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
+void mrsas_kill_hba(struct mrsas_softc *sc);
+void mrsas_aen_handler(struct mrsas_softc *sc);
+void
+mrsas_write_reg(struct mrsas_softc *sc, int offset,
+ u_int32_t value);
+void
+mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo,
+ u_int32_t req_desc_hi);
+void mrsas_free_ctlr_info_cmd(struct mrsas_softc *sc);
+void
+mrsas_complete_mptmfi_passthru(struct mrsas_softc *sc,
+ struct mrsas_mfi_cmd *cmd, u_int8_t status);
+void
+mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status,
+ u_int8_t extStatus);
+struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc);
+
+MRSAS_REQUEST_DESCRIPTOR_UNION *mrsas_build_mpt_cmd
+ (struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
extern int mrsas_cam_attach(struct mrsas_softc *sc);
extern void mrsas_cam_detach(struct mrsas_softc *sc);
extern void mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd);
extern void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
extern int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
-extern void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd);
+extern void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd);
extern struct mrsas_mpt_cmd *mrsas_get_mpt_cmd(struct mrsas_softc *sc);
-extern int mrsas_passthru(struct mrsas_softc *sc, void *arg);
+extern int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
extern uint8_t MR_ValidateMapInfo(struct mrsas_softc *sc);
-extern u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_FW_RAID_MAP_ALL *map);
-extern MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_FW_RAID_MAP_ALL *map);
+extern u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map);
+extern MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map);
extern void mrsas_xpt_freeze(struct mrsas_softc *sc);
extern void mrsas_xpt_release(struct mrsas_softc *sc);
-extern MRSAS_REQUEST_DESCRIPTOR_UNION *mrsas_get_request_desc(struct mrsas_softc *sc,
- u_int16_t index);
+extern MRSAS_REQUEST_DESCRIPTOR_UNION *
+mrsas_get_request_desc(struct mrsas_softc *sc,
+ u_int16_t index);
extern int mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim);
static int mrsas_alloc_evt_log_info_cmd(struct mrsas_softc *sc);
static void mrsas_free_evt_log_info_cmd(struct mrsas_softc *sc);
-SYSCTL_NODE(_hw, OID_AUTO, mrsas, CTLFLAG_RD, 0, "MRSAS Driver Parameters");
+SYSCTL_NODE(_hw, OID_AUTO, mrsas, CTLFLAG_RD, 0, "MRSAS Driver Parameters");
-/**
+/*
* PCI device struct and table
*
*/
typedef struct mrsas_ident {
- uint16_t vendor;
- uint16_t device;
- uint16_t subvendor;
- uint16_t subdevice;
- const char *desc;
-} MRSAS_CTLR_ID;
+ uint16_t vendor;
+ uint16_t device;
+ uint16_t subvendor;
+ uint16_t subdevice;
+ const char *desc;
+} MRSAS_CTLR_ID;
MRSAS_CTLR_ID device_table[] = {
- {0x1000, MRSAS_TBOLT, 0xffff, 0xffff, "LSI Thunderbolt SAS Controller"},
- {0x1000, MRSAS_INVADER, 0xffff, 0xffff, "LSI Invader SAS Controller"},
- {0x1000, MRSAS_FURY, 0xffff, 0xffff, "LSI Fury SAS Controller"},
- {0, 0, 0, 0, NULL}
+ {0x1000, MRSAS_TBOLT, 0xffff, 0xffff, "LSI Thunderbolt SAS Controller"},
+ {0x1000, MRSAS_INVADER, 0xffff, 0xffff, "LSI Invader SAS Controller"},
+ {0x1000, MRSAS_FURY, 0xffff, 0xffff, "LSI Fury SAS Controller"},
+ {0, 0, 0, 0, NULL}
};
-/**
- * Character device entry points
+/*
+ * Character device entry points
*
*/
static struct cdevsw mrsas_cdevsw = {
- .d_version = D_VERSION,
- .d_open = mrsas_open,
- .d_close = mrsas_close,
- .d_read = mrsas_read,
- .d_write = mrsas_write,
- .d_ioctl = mrsas_ioctl,
- .d_name = "mrsas",
+ .d_version = D_VERSION,
+ .d_open = mrsas_open,
+ .d_close = mrsas_close,
+ .d_read = mrsas_read,
+ .d_write = mrsas_write,
+ .d_ioctl = mrsas_ioctl,
+ .d_poll = mrsas_poll,
+ .d_name = "mrsas",
};
MALLOC_DEFINE(M_MRSAS, "mrsasbuf", "Buffers for the MRSAS driver");
-/**
- * In the cdevsw routines, we find our softc by using the si_drv1 member
- * of struct cdev. We set this variable to point to our softc in our
- * attach routine when we create the /dev entry.
+/*
+ * In the cdevsw routines, we find our softc by using the si_drv1 member of
+ * struct cdev. We set this variable to point to our softc in our attach
+ * routine when we create the /dev entry.
*/
int
mrsas_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td)
{
- struct mrsas_softc *sc;
+ struct mrsas_softc *sc;
- sc = dev->si_drv1;
- return (0);
+ sc = dev->si_drv1;
+ return (0);
}
int
mrsas_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td)
{
- struct mrsas_softc *sc;
+ struct mrsas_softc *sc;
- sc = dev->si_drv1;
- return (0);
+ sc = dev->si_drv1;
+ return (0);
}
int
mrsas_read(struct cdev *dev, struct uio *uio, int ioflag)
{
- struct mrsas_softc *sc;
+ struct mrsas_softc *sc;
- sc = dev->si_drv1;
- return (0);
+ sc = dev->si_drv1;
+ return (0);
}
int
mrsas_write(struct cdev *dev, struct uio *uio, int ioflag)
{
- struct mrsas_softc *sc;
+ struct mrsas_softc *sc;
- sc = dev->si_drv1;
- return (0);
+ sc = dev->si_drv1;
+ return (0);
}
-/**
- * Register Read/Write Functions
+/*
+ * Register Read/Write Functions
*
*/
void
mrsas_write_reg(struct mrsas_softc *sc, int offset,
- u_int32_t value)
+ u_int32_t value)
{
- bus_space_tag_t bus_tag = sc->bus_tag;
- bus_space_handle_t bus_handle = sc->bus_handle;
+ bus_space_tag_t bus_tag = sc->bus_tag;
+ bus_space_handle_t bus_handle = sc->bus_handle;
- bus_space_write_4(bus_tag, bus_handle, offset, value);
+ bus_space_write_4(bus_tag, bus_handle, offset, value);
}
u_int32_t
mrsas_read_reg(struct mrsas_softc *sc, int offset)
{
- bus_space_tag_t bus_tag = sc->bus_tag;
- bus_space_handle_t bus_handle = sc->bus_handle;
+ bus_space_tag_t bus_tag = sc->bus_tag;
+ bus_space_handle_t bus_handle = sc->bus_handle;
- return((u_int32_t)bus_space_read_4(bus_tag, bus_handle, offset));
+ return ((u_int32_t)bus_space_read_4(bus_tag, bus_handle, offset));
}
-/**
- * Interrupt Disable/Enable/Clear Functions
+/*
+ * Interrupt Disable/Enable/Clear Functions
*
*/
-void mrsas_disable_intr(struct mrsas_softc *sc)
+void
+mrsas_disable_intr(struct mrsas_softc *sc)
{
- u_int32_t mask = 0xFFFFFFFF;
- u_int32_t status;
+ u_int32_t mask = 0xFFFFFFFF;
+ u_int32_t status;
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), mask);
- /* Dummy read to force pci flush */
- status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask));
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), mask);
+ /* Dummy read to force pci flush */
+ status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask));
}
-void mrsas_enable_intr(struct mrsas_softc *sc)
+void
+mrsas_enable_intr(struct mrsas_softc *sc)
{
- u_int32_t mask = MFI_FUSION_ENABLE_INTERRUPT_MASK;
- u_int32_t status;
+ u_int32_t mask = MFI_FUSION_ENABLE_INTERRUPT_MASK;
+ u_int32_t status;
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), ~0);
- status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status));
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), ~0);
+ status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status));
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), ~mask);
- status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask));
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask), ~mask);
+ status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_mask));
}
-static int mrsas_clear_intr(struct mrsas_softc *sc)
+static int
+mrsas_clear_intr(struct mrsas_softc *sc)
{
- u_int32_t status, fw_status, fw_state;
+ u_int32_t status, fw_status, fw_state;
- /* Read received interrupt */
- status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status));
+ /* Read received interrupt */
+ status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status));
- /* If FW state change interrupt is received, write to it again to clear */
- if (status & MRSAS_FW_STATE_CHNG_INTERRUPT) {
- fw_status = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- outbound_scratch_pad));
- fw_state = fw_status & MFI_STATE_MASK;
- if (fw_state == MFI_STATE_FAULT) {
- device_printf(sc->mrsas_dev, "FW is in FAULT state!\n");
- if(sc->ocr_thread_active)
- wakeup(&sc->ocr_chan);
- }
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), status);
- mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status));
- return(1);
- }
-
- /* Not our interrupt, so just return */
- if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
- return(0);
+ /*
+ * If FW state change interrupt is received, write to it again to
+ * clear
+ */
+ if (status & MRSAS_FW_STATE_CHNG_INTERRUPT) {
+ fw_status = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad));
+ fw_state = fw_status & MFI_STATE_MASK;
+ if (fw_state == MFI_STATE_FAULT) {
+ device_printf(sc->mrsas_dev, "FW is in FAULT state!\n");
+ if (sc->ocr_thread_active)
+ wakeup(&sc->ocr_chan);
+ }
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status), status);
+ mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_intr_status));
+ return (1);
+ }
+ /* Not our interrupt, so just return */
+ if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
+ return (0);
- /* We got a reply interrupt */
- return(1);
+ /* We got a reply interrupt */
+ return (1);
}
-/**
- * PCI Support Functions
+/*
+ * PCI Support Functions
*
*/
-static struct mrsas_ident * mrsas_find_ident(device_t dev)
+static struct mrsas_ident *
+mrsas_find_ident(device_t dev)
{
- struct mrsas_ident *pci_device;
+ struct mrsas_ident *pci_device;
- for (pci_device=device_table; pci_device->vendor != 0; pci_device++)
- {
- if ((pci_device->vendor == pci_get_vendor(dev)) &&
- (pci_device->device == pci_get_device(dev)) &&
- ((pci_device->subvendor == pci_get_subvendor(dev)) ||
- (pci_device->subvendor == 0xffff)) &&
- ((pci_device->subdevice == pci_get_subdevice(dev)) ||
- (pci_device->subdevice == 0xffff)))
- return (pci_device);
- }
- return (NULL);
+ for (pci_device = device_table; pci_device->vendor != 0; pci_device++) {
+ if ((pci_device->vendor == pci_get_vendor(dev)) &&
+ (pci_device->device == pci_get_device(dev)) &&
+ ((pci_device->subvendor == pci_get_subvendor(dev)) ||
+ (pci_device->subvendor == 0xffff)) &&
+ ((pci_device->subdevice == pci_get_subdevice(dev)) ||
+ (pci_device->subdevice == 0xffff)))
+ return (pci_device);
+ }
+ return (NULL);
}
-static int mrsas_probe(device_t dev)
+static int
+mrsas_probe(device_t dev)
{
- static u_int8_t first_ctrl = 1;
- struct mrsas_ident *id;
+ static u_int8_t first_ctrl = 1;
+ struct mrsas_ident *id;
- if ((id = mrsas_find_ident(dev)) != NULL) {
- if (first_ctrl) {
- printf("LSI MegaRAID SAS FreeBSD mrsas driver version: %s\n", MRSAS_VERSION);
- first_ctrl = 0;
- }
- device_set_desc(dev, id->desc);
- /* between BUS_PROBE_DEFAULT and BUS_PROBE_LOW_PRIORITY */
- return (-30);
- }
- return (ENXIO);
+ if ((id = mrsas_find_ident(dev)) != NULL) {
+ if (first_ctrl) {
+ printf("LSI MegaRAID SAS FreeBSD mrsas driver version: %s\n",
+ MRSAS_VERSION);
+ first_ctrl = 0;
+ }
+ device_set_desc(dev, id->desc);
+ /* between BUS_PROBE_DEFAULT and BUS_PROBE_LOW_PRIORITY */
+ return (-30);
+ }
+ return (ENXIO);
}
-/**
- * mrsas_setup_sysctl: setup sysctl values for mrsas
- * input: Adapter instance soft state
+/*
+ * mrsas_setup_sysctl: setup sysctl values for mrsas
+ * input: Adapter instance soft state
*
* Setup sysctl entries for mrsas driver.
*/
static void
mrsas_setup_sysctl(struct mrsas_softc *sc)
{
- struct sysctl_ctx_list *sysctl_ctx = NULL;
- struct sysctl_oid *sysctl_tree = NULL;
- char tmpstr[80], tmpstr2[80];
-
- /*
- * Setup the sysctl variable so the user can change the debug level
- * on the fly.
- */
- snprintf(tmpstr, sizeof(tmpstr), "MRSAS controller %d",
- device_get_unit(sc->mrsas_dev));
- snprintf(tmpstr2, sizeof(tmpstr2), "%d", device_get_unit(sc->mrsas_dev));
-
- sysctl_ctx = device_get_sysctl_ctx(sc->mrsas_dev);
- if (sysctl_ctx != NULL)
- sysctl_tree = device_get_sysctl_tree(sc->mrsas_dev);
-
- if (sysctl_tree == NULL) {
- sysctl_ctx_init(&sc->sysctl_ctx);
- sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
- SYSCTL_STATIC_CHILDREN(_hw_mrsas), OID_AUTO, tmpstr2,
- CTLFLAG_RD, 0, tmpstr);
- if (sc->sysctl_tree == NULL)
- return;
- sysctl_ctx = &sc->sysctl_ctx;
- sysctl_tree = sc->sysctl_tree;
- }
- SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "disable_ocr", CTLFLAG_RW, &sc->disableOnlineCtrlReset, 0,
- "Disable the use of OCR");
-
- SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "driver_version", CTLFLAG_RD, MRSAS_VERSION,
- strlen(MRSAS_VERSION), "driver version");
-
- SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "reset_count", CTLFLAG_RD,
- &sc->reset_count, 0, "number of ocr from start of the day");
-
- SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "fw_outstanding", CTLFLAG_RD,
- &sc->fw_outstanding, 0, "FW outstanding commands");
+ struct sysctl_ctx_list *sysctl_ctx = NULL;
+ struct sysctl_oid *sysctl_tree = NULL;
+ char tmpstr[80], tmpstr2[80];
+
+ /*
+ * Setup the sysctl variable so the user can change the debug level
+ * on the fly.
+ */
+ snprintf(tmpstr, sizeof(tmpstr), "MRSAS controller %d",
+ device_get_unit(sc->mrsas_dev));
+ snprintf(tmpstr2, sizeof(tmpstr2), "%d", device_get_unit(sc->mrsas_dev));
+
+ sysctl_ctx = device_get_sysctl_ctx(sc->mrsas_dev);
+ if (sysctl_ctx != NULL)
+ sysctl_tree = device_get_sysctl_tree(sc->mrsas_dev);
+
+ if (sysctl_tree == NULL) {
+ sysctl_ctx_init(&sc->sysctl_ctx);
+ sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
+ SYSCTL_STATIC_CHILDREN(_hw_mrsas), OID_AUTO, tmpstr2,
+ CTLFLAG_RD, 0, tmpstr);
+ if (sc->sysctl_tree == NULL)
+ return;
+ sysctl_ctx = &sc->sysctl_ctx;
+ sysctl_tree = sc->sysctl_tree;
+ }
+ SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "disable_ocr", CTLFLAG_RW, &sc->disableOnlineCtrlReset, 0,
+ "Disable the use of OCR");
+
+ SYSCTL_ADD_STRING(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "driver_version", CTLFLAG_RD, MRSAS_VERSION,
+ strlen(MRSAS_VERSION), "driver version");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "io_cmds_highwater", CTLFLAG_RD,
- &sc->io_cmds_highwater, 0, "Max FW outstanding commands");
+ OID_AUTO, "reset_count", CTLFLAG_RD,
+ &sc->reset_count, 0, "number of ocr from start of the day");
- SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "mrsas_debug", CTLFLAG_RW, &sc->mrsas_debug, 0,
- "Driver debug level");
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "fw_outstanding", CTLFLAG_RD,
+ &sc->fw_outstanding, 0, "FW outstanding commands");
- SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "mrsas_io_timeout", CTLFLAG_RW, &sc->mrsas_io_timeout,
- 0, "Driver IO timeout value in mili-second.");
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "io_cmds_highwater", CTLFLAG_RD,
+ &sc->io_cmds_highwater, 0, "Max FW outstanding commands");
+
+ SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "mrsas_debug", CTLFLAG_RW, &sc->mrsas_debug, 0,
+ "Driver debug level");
- SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "mrsas_fw_fault_check_delay", CTLFLAG_RW,
- &sc->mrsas_fw_fault_check_delay,
- 0, "FW fault check thread delay in seconds. <default is 1 sec>");
+ SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "mrsas_io_timeout", CTLFLAG_RW, &sc->mrsas_io_timeout,
+ 0, "Driver IO timeout value in mili-second.");
- SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "reset_in_progress", CTLFLAG_RD,
- &sc->reset_in_progress, 0, "ocr in progress status");
+ SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "mrsas_fw_fault_check_delay", CTLFLAG_RW,
+ &sc->mrsas_fw_fault_check_delay,
+ 0, "FW fault check thread delay in seconds. <default is 1 sec>");
+
+ SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "reset_in_progress", CTLFLAG_RD,
+ &sc->reset_in_progress, 0, "ocr in progress status");
}
-/**
- * mrsas_get_tunables: get tunable parameters.
- * input: Adapter instance soft state
+/*
+ * mrsas_get_tunables: get tunable parameters.
+ * input: Adapter instance soft state
*
* Get tunable parameters. This will help to debug driver at boot time.
*/
static void
mrsas_get_tunables(struct mrsas_softc *sc)
{
- char tmpstr[80];
+ char tmpstr[80];
- /* XXX default to some debugging for now */
- sc->mrsas_debug = MRSAS_FAULT;
- sc->mrsas_io_timeout = MRSAS_IO_TIMEOUT;
- sc->mrsas_fw_fault_check_delay = 1;
- sc->reset_count = 0;
- sc->reset_in_progress = 0;
+ /* XXX default to some debugging for now */
+ sc->mrsas_debug = MRSAS_FAULT;
+ sc->mrsas_io_timeout = MRSAS_IO_TIMEOUT;
+ sc->mrsas_fw_fault_check_delay = 1;
+ sc->reset_count = 0;
+ sc->reset_in_progress = 0;
- /*
- * Grab the global variables.
- */
- TUNABLE_INT_FETCH("hw.mrsas.debug_level", &sc->mrsas_debug);
+ /*
+ * Grab the global variables.
+ */
+ TUNABLE_INT_FETCH("hw.mrsas.debug_level", &sc->mrsas_debug);
- /* Grab the unit-instance variables */
- snprintf(tmpstr, sizeof(tmpstr), "dev.mrsas.%d.debug_level",
- device_get_unit(sc->mrsas_dev));
- TUNABLE_INT_FETCH(tmpstr, &sc->mrsas_debug);
+ /* Grab the unit-instance variables */
+ snprintf(tmpstr, sizeof(tmpstr), "dev.mrsas.%d.debug_level",
+ device_get_unit(sc->mrsas_dev));
+ TUNABLE_INT_FETCH(tmpstr, &sc->mrsas_debug);
}
-/**
- * mrsas_alloc_evt_log_info cmd: Allocates memory to get event log information.
- * Used to get sequence number at driver load time.
- * input: Adapter soft state
+/*
+ * mrsas_alloc_evt_log_info cmd: Allocates memory to get event log information.
+ * Used to get sequence number at driver load time.
+ * input: Adapter soft state
*
* Allocates DMAable memory for the event log info internal command.
*/
-int mrsas_alloc_evt_log_info_cmd(struct mrsas_softc *sc)
-{
- int el_info_size;
-
- /* Allocate get event log info command */
- el_info_size = sizeof(struct mrsas_evt_log_info);
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- el_info_size, // maxsize
- 1, // msegments
- el_info_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->el_info_tag)) {
- device_printf(sc->mrsas_dev, "Cannot allocate event log info tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->el_info_tag, (void **)&sc->el_info_mem,
- BUS_DMA_NOWAIT, &sc->el_info_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot allocate event log info cmd mem\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(sc->el_info_tag, sc->el_info_dmamap,
- sc->el_info_mem, el_info_size, mrsas_addr_cb,
- &sc->el_info_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load event log info cmd mem\n");
- return (ENOMEM);
- }
-
- memset(sc->el_info_mem, 0, el_info_size);
- return (0);
-}
-
-/**
- * mrsas_free_evt_info_cmd: Free memory for Event log info command
- * input: Adapter soft state
+int
+mrsas_alloc_evt_log_info_cmd(struct mrsas_softc *sc)
+{
+ int el_info_size;
+
+ /* Allocate get event log info command */
+ el_info_size = sizeof(struct mrsas_evt_log_info);
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ el_info_size,
+ 1,
+ el_info_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->el_info_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate event log info tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->el_info_tag, (void **)&sc->el_info_mem,
+ BUS_DMA_NOWAIT, &sc->el_info_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate event log info cmd mem\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamap_load(sc->el_info_tag, sc->el_info_dmamap,
+ sc->el_info_mem, el_info_size, mrsas_addr_cb,
+ &sc->el_info_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load event log info cmd mem\n");
+ return (ENOMEM);
+ }
+ memset(sc->el_info_mem, 0, el_info_size);
+ return (0);
+}
+
+/*
+ * mrsas_free_evt_info_cmd: Free memory for Event log info command
+ * input: Adapter soft state
*
* Deallocates memory for the event log info internal command.
*/
-void mrsas_free_evt_log_info_cmd(struct mrsas_softc *sc)
+void
+mrsas_free_evt_log_info_cmd(struct mrsas_softc *sc)
{
- if (sc->el_info_phys_addr)
- bus_dmamap_unload(sc->el_info_tag, sc->el_info_dmamap);
- if (sc->el_info_mem != NULL)
- bus_dmamem_free(sc->el_info_tag, sc->el_info_mem, sc->el_info_dmamap);
- if (sc->el_info_tag != NULL)
- bus_dma_tag_destroy(sc->el_info_tag);
+ if (sc->el_info_phys_addr)
+ bus_dmamap_unload(sc->el_info_tag, sc->el_info_dmamap);
+ if (sc->el_info_mem != NULL)
+ bus_dmamem_free(sc->el_info_tag, sc->el_info_mem, sc->el_info_dmamap);
+ if (sc->el_info_tag != NULL)
+ bus_dma_tag_destroy(sc->el_info_tag);
}
-/**
+/*
* mrsas_get_seq_num: Get latest event sequence number
* @sc: Adapter soft state
* @eli: Firmware event log sequence number information.
- * Firmware maintains a log of all events in a non-volatile area.
- * Driver get the sequence number using DCMD
- * "MR_DCMD_CTRL_EVENT_GET_INFO" at driver load time.
+ *
+ * Firmware maintains a log of all events in a non-volatile area.
+ * Driver get the sequence number using DCMD
+ * "MR_DCMD_CTRL_EVENT_GET_INFO" at driver load time.
*/
static int
mrsas_get_seq_num(struct mrsas_softc *sc,
- struct mrsas_evt_log_info *eli)
+ struct mrsas_evt_log_info *eli)
{
struct mrsas_mfi_cmd *cmd;
struct mrsas_dcmd_frame *dcmd;
- cmd = mrsas_get_mfi_cmd(sc);
+ cmd = mrsas_get_mfi_cmd(sc);
if (!cmd) {
device_printf(sc->mrsas_dev, "Failed to get a free cmd\n");
return -ENOMEM;
}
-
dcmd = &cmd->frame->dcmd;
if (mrsas_alloc_evt_log_info_cmd(sc) != SUCCESS) {
@@ -536,7 +556,6 @@ mrsas_get_seq_num(struct mrsas_softc *sc,
mrsas_release_mfi_cmd(cmd);
return -ENOMEM;
}
-
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->cmd = MFI_CMD_DCMD;
@@ -553,8 +572,8 @@ mrsas_get_seq_num(struct mrsas_softc *sc,
mrsas_issue_blocked_cmd(sc, cmd);
/*
- * Copy the data back into callers buffer
- */
+ * Copy the data back into callers buffer
+ */
memcpy(eli, sc->el_info_mem, sizeof(struct mrsas_evt_log_info));
mrsas_free_evt_log_info_cmd(sc);
mrsas_release_mfi_cmd(cmd);
@@ -563,18 +582,19 @@ mrsas_get_seq_num(struct mrsas_softc *sc,
}
-/**
+/*
* mrsas_register_aen: Register for asynchronous event notification
- * @sc: Adapter soft state
- * @seq_num: Starting sequence number
- * @class_locale: Class of the event
- * This function subscribes for events beyond the @seq_num
- * and type @class_locale.
- *
- * */
+ * @sc: Adapter soft state
+ * @seq_num: Starting sequence number
+ * @class_locale: Class of the event
+ *
+ * This function subscribes for events beyond the @seq_num
+ * and type @class_locale.
+ *
+ */
static int
mrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num,
- u_int32_t class_locale_word)
+ u_int32_t class_locale_word)
{
int ret_val;
struct mrsas_mfi_cmd *cmd;
@@ -582,17 +602,16 @@ mrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num,
union mrsas_evt_class_locale curr_aen;
union mrsas_evt_class_locale prev_aen;
-/*
- * If there an AEN pending already (aen_cmd), check if the
- * class_locale of that pending AEN is inclusive of the new
- * AEN request we currently have. If it is, then we don't have
- * to do anything. In other words, whichever events the current
- * AEN request is subscribing to, have already been subscribed
- * to.
- * If the old_cmd is _not_ inclusive, then we have to abort
- * that command, form a class_locale that is superset of both
- * old and current and re-issue to the FW
- * */
+ /*
+ * If there an AEN pending already (aen_cmd), check if the
+ * class_locale of that pending AEN is inclusive of the new AEN
+ * request we currently have. If it is, then we don't have to do
+ * anything. In other words, whichever events the current AEN request
+ * is subscribing to, have already been subscribed to. If the old_cmd
+ * is _not_ inclusive, then we have to abort that command, form a
+ * class_locale that is superset of both old and current and re-issue
+ * to the FW
+ */
curr_aen.word = class_locale_word;
@@ -600,21 +619,21 @@ mrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num,
prev_aen.word = sc->aen_cmd->frame->dcmd.mbox.w[1];
-/*
- * A class whose enum value is smaller is inclusive of all
- * higher values. If a PROGRESS (= -1) was previously
- * registered, then a new registration requests for higher
- * classes need not be sent to FW. They are automatically
- * included.
- * Locale numbers don't have such hierarchy. They are bitmap values
- */
+ /*
+ * A class whose enum value is smaller is inclusive of all
+ * higher values. If a PROGRESS (= -1) was previously
+ * registered, then a new registration requests for higher
+ * classes need not be sent to FW. They are automatically
+ * included. Locale numbers don't have such hierarchy. They
+ * are bitmap values
+ */
if ((prev_aen.members.class <= curr_aen.members.class) &&
- !((prev_aen.members.locale & curr_aen.members.locale) ^
- curr_aen.members.locale)) {
+ !((prev_aen.members.locale & curr_aen.members.locale) ^
+ curr_aen.members.locale)) {
/*
- * Previously issued event registration includes
- * current request. Nothing to do.
- */
+ * Previously issued event registration includes
+ * current request. Nothing to do.
+ */
return 0;
} else {
curr_aen.members.locale |= prev_aen.members.locale;
@@ -624,17 +643,16 @@ mrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num,
sc->aen_cmd->abort_aen = 1;
ret_val = mrsas_issue_blocked_abort_cmd(sc,
- sc->aen_cmd);
+ sc->aen_cmd);
if (ret_val) {
printf("mrsas: Failed to abort "
- "previous AEN command\n");
+ "previous AEN command\n");
return ret_val;
}
}
}
-
- cmd = mrsas_get_mfi_cmd(sc);
+ cmd = mrsas_get_mfi_cmd(sc);
if (!cmd)
return -ENOMEM;
@@ -643,9 +661,9 @@ mrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num,
memset(sc->evt_detail_mem, 0, sizeof(struct mrsas_evt_detail));
-/*
- * Prepare DCMD for aen registration
- */
+ /*
+ * Prepare DCMD for aen registration
+ */
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->cmd = MFI_CMD_DCMD;
@@ -657,2895 +675,3236 @@ mrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num,
dcmd->data_xfer_len = sizeof(struct mrsas_evt_detail);
dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
dcmd->mbox.w[0] = seq_num;
- sc->last_seq_num = seq_num;
+ sc->last_seq_num = seq_num;
dcmd->mbox.w[1] = curr_aen.word;
- dcmd->sgl.sge32[0].phys_addr = (u_int32_t) sc->evt_detail_phys_addr;
+ dcmd->sgl.sge32[0].phys_addr = (u_int32_t)sc->evt_detail_phys_addr;
dcmd->sgl.sge32[0].length = sizeof(struct mrsas_evt_detail);
if (sc->aen_cmd != NULL) {
mrsas_release_mfi_cmd(cmd);
return 0;
}
-
/*
- * Store reference to the cmd used to register for AEN. When an
- * application wants us to register for AEN, we have to abort this
- * cmd and re-register with a new EVENT LOCALE supplied by that app
- */
+ * Store reference to the cmd used to register for AEN. When an
+ * application wants us to register for AEN, we have to abort this
+ * cmd and re-register with a new EVENT LOCALE supplied by that app
+ */
sc->aen_cmd = cmd;
/*
- Issue the aen registration frame
- */
- if (mrsas_issue_dcmd(sc, cmd)){
- device_printf(sc->mrsas_dev, "Cannot issue AEN DCMD command.\n");
- return(1);
- }
-
+ * Issue the aen registration frame
+ */
+ if (mrsas_issue_dcmd(sc, cmd)) {
+ device_printf(sc->mrsas_dev, "Cannot issue AEN DCMD command.\n");
+ return (1);
+ }
return 0;
}
-/**
- * mrsas_start_aen - Subscribes to AEN during driver load time
- * @instance: Adapter soft state
+
+/*
+ * mrsas_start_aen: Subscribes to AEN during driver load time
+ * @instance: Adapter soft state
*/
-static int mrsas_start_aen(struct mrsas_softc *sc)
+static int
+mrsas_start_aen(struct mrsas_softc *sc)
{
struct mrsas_evt_log_info eli;
union mrsas_evt_class_locale class_locale;
- /* Get the latest sequence number from FW*/
-
+ /* Get the latest sequence number from FW */
+
memset(&eli, 0, sizeof(eli));
if (mrsas_get_seq_num(sc, &eli))
return -1;
- /* Register AEN with FW for latest sequence number plus 1*/
+ /* Register AEN with FW for latest sequence number plus 1 */
class_locale.members.reserved = 0;
class_locale.members.locale = MR_EVT_LOCALE_ALL;
class_locale.members.class = MR_EVT_CLASS_DEBUG;
return mrsas_register_aen(sc, eli.newest_seq_num + 1,
- class_locale.word);
-}
-
-/**
- * mrsas_attach: PCI entry point
- * input: device struct pointer
- *
- * Performs setup of PCI and registers, initializes mutexes and
- * linked lists, registers interrupts and CAM, and initializes
- * the adapter/controller to its proper state.
- */
-static int mrsas_attach(device_t dev)
-{
- struct mrsas_softc *sc = device_get_softc(dev);
- uint32_t cmd, bar, error;
-
- /* Look up our softc and initialize its fields. */
- sc->mrsas_dev = dev;
- sc->device_id = pci_get_device(dev);
-
- mrsas_get_tunables(sc);
-
- /*
- * Set up PCI and registers
- */
- cmd = pci_read_config(dev, PCIR_COMMAND, 2);
- if ( (cmd & PCIM_CMD_PORTEN) == 0) {
- return (ENXIO);
- }
- /* Force the busmaster enable bit on. */
- cmd |= PCIM_CMD_BUSMASTEREN;
- pci_write_config(dev, PCIR_COMMAND, cmd, 2);
-
- //bar = pci_read_config(dev, MRSAS_PCI_BAR0, 4);
- bar = pci_read_config(dev, MRSAS_PCI_BAR1, 4);
-
- sc->reg_res_id = MRSAS_PCI_BAR1; /* BAR1 offset */
- if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
- == NULL) {
- device_printf(dev, "Cannot allocate PCI registers\n");
- goto attach_fail;
- }
- sc->bus_tag = rman_get_bustag(sc->reg_res);
- sc->bus_handle = rman_get_bushandle(sc->reg_res);
-
- /* Intialize mutexes */
- mtx_init(&sc->sim_lock, "mrsas_sim_lock", NULL, MTX_DEF);
- mtx_init(&sc->pci_lock, "mrsas_pci_lock", NULL, MTX_DEF);
- mtx_init(&sc->io_lock, "mrsas_io_lock", NULL, MTX_DEF);
- mtx_init(&sc->aen_lock, "mrsas_aen_lock", NULL, MTX_DEF);
- mtx_init(&sc->ioctl_lock, "mrsas_ioctl_lock", NULL, MTX_SPIN);
- mtx_init(&sc->mpt_cmd_pool_lock, "mrsas_mpt_cmd_pool_lock", NULL, MTX_DEF);
- mtx_init(&sc->mfi_cmd_pool_lock, "mrsas_mfi_cmd_pool_lock", NULL, MTX_DEF);
- mtx_init(&sc->raidmap_lock, "mrsas_raidmap_lock", NULL, MTX_DEF);
-
- /* Intialize linked list */
- TAILQ_INIT(&sc->mrsas_mpt_cmd_list_head);
- TAILQ_INIT(&sc->mrsas_mfi_cmd_list_head);
-
- atomic_set(&sc->fw_outstanding,0);
+ class_locale.word);
- sc->io_cmds_highwater = 0;
+}
+
+/*
+ * mrsas_setup_msix: Allocate MSI-x vectors
+ * @sc: adapter soft state
+ */
+static int
+mrsas_setup_msix(struct mrsas_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < sc->msix_vectors; i++) {
+ sc->irq_context[i].sc = sc;
+ sc->irq_context[i].MSIxIndex = i;
+ sc->irq_id[i] = i + 1;
+ sc->mrsas_irq[i] = bus_alloc_resource_any
+ (sc->mrsas_dev, SYS_RES_IRQ, &sc->irq_id[i]
+ ,RF_ACTIVE);
+ if (sc->mrsas_irq[i] == NULL) {
+ device_printf(sc->mrsas_dev, "Can't allocate MSI-x\n");
+ goto irq_alloc_failed;
+ }
+ if (bus_setup_intr(sc->mrsas_dev,
+ sc->mrsas_irq[i],
+ INTR_MPSAFE | INTR_TYPE_CAM,
+ NULL, mrsas_isr, &sc->irq_context[i],
+ &sc->intr_handle[i])) {
+ device_printf(sc->mrsas_dev,
+ "Cannot set up MSI-x interrupt handler\n");
+ goto irq_alloc_failed;
+ }
+ }
+ return SUCCESS;
- /* Create a /dev entry for this device. */
- sc->mrsas_cdev = make_dev(&mrsas_cdevsw, device_get_unit(dev), UID_ROOT,
- GID_OPERATOR, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP), "mrsas%u",
- device_get_unit(dev));
- if (sc->mrsas_cdev)
- sc->mrsas_cdev->si_drv1 = sc;
+irq_alloc_failed:
+ mrsas_teardown_intr(sc);
+ return (FAIL);
+}
- sc->adprecovery = MRSAS_HBA_OPERATIONAL;
- sc->UnevenSpanSupport = 0;
+/*
+ * mrsas_allocate_msix: Setup MSI-x vectors
+ * @sc: adapter soft state
+ */
+static int
+mrsas_allocate_msix(struct mrsas_softc *sc)
+{
+ if (pci_alloc_msix(sc->mrsas_dev, &sc->msix_vectors) == 0) {
+ device_printf(sc->mrsas_dev, "Using MSI-X with %d number"
+ " of vectors\n", sc->msix_vectors);
+ } else {
+ device_printf(sc->mrsas_dev, "MSI-x setup failed\n");
+ goto irq_alloc_failed;
+ }
+ return SUCCESS;
- /* Initialize Firmware */
- if (mrsas_init_fw(sc) != SUCCESS) {
- goto attach_fail_fw;
- }
+irq_alloc_failed:
+ mrsas_teardown_intr(sc);
+ return (FAIL);
+}
- /* Register SCSI mid-layer */
- if ((mrsas_cam_attach(sc) != SUCCESS)) {
- goto attach_fail_cam;
- }
+/*
+ * mrsas_attach: PCI entry point
+ * input: pointer to device struct
+ *
+ * Performs setup of PCI and registers, initializes mutexes and linked lists,
+ * registers interrupts and CAM, and initializes the adapter/controller to
+ * its proper state.
+ */
+static int
+mrsas_attach(device_t dev)
+{
+ struct mrsas_softc *sc = device_get_softc(dev);
+ uint32_t cmd, bar, error;
- /* Register IRQs */
- if (mrsas_setup_irq(sc) != SUCCESS) {
- goto attach_fail_irq;
- }
+ /* Look up our softc and initialize its fields. */
+ sc->mrsas_dev = dev;
+ sc->device_id = pci_get_device(dev);
- /* Enable Interrupts */
- mrsas_enable_intr(sc);
+ mrsas_get_tunables(sc);
- error = mrsas_kproc_create(mrsas_ocr_thread, sc,
- &sc->ocr_thread, 0, 0, "mrsas_ocr%d",
- device_get_unit(sc->mrsas_dev));
- if (error) {
- printf("Error %d starting rescan thread\n", error);
- goto attach_fail_irq;
- }
+ /*
+ * Set up PCI and registers
+ */
+ cmd = pci_read_config(dev, PCIR_COMMAND, 2);
+ if ((cmd & PCIM_CMD_PORTEN) == 0) {
+ return (ENXIO);
+ }
+ /* Force the busmaster enable bit on. */
+ cmd |= PCIM_CMD_BUSMASTEREN;
+ pci_write_config(dev, PCIR_COMMAND, cmd, 2);
+
+ bar = pci_read_config(dev, MRSAS_PCI_BAR1, 4);
+
+ sc->reg_res_id = MRSAS_PCI_BAR1;/* BAR1 offset */
+ if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
+ &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
+ == NULL) {
+ device_printf(dev, "Cannot allocate PCI registers\n");
+ goto attach_fail;
+ }
+ sc->bus_tag = rman_get_bustag(sc->reg_res);
+ sc->bus_handle = rman_get_bushandle(sc->reg_res);
+
+ /* Intialize mutexes */
+ mtx_init(&sc->sim_lock, "mrsas_sim_lock", NULL, MTX_DEF);
+ mtx_init(&sc->pci_lock, "mrsas_pci_lock", NULL, MTX_DEF);
+ mtx_init(&sc->io_lock, "mrsas_io_lock", NULL, MTX_DEF);
+ mtx_init(&sc->aen_lock, "mrsas_aen_lock", NULL, MTX_DEF);
+ mtx_init(&sc->ioctl_lock, "mrsas_ioctl_lock", NULL, MTX_SPIN);
+ mtx_init(&sc->mpt_cmd_pool_lock, "mrsas_mpt_cmd_pool_lock", NULL, MTX_DEF);
+ mtx_init(&sc->mfi_cmd_pool_lock, "mrsas_mfi_cmd_pool_lock", NULL, MTX_DEF);
+ mtx_init(&sc->raidmap_lock, "mrsas_raidmap_lock", NULL, MTX_DEF);
+
+ /*
+ * Intialize a counting Semaphore to take care no. of concurrent
+ * IOCTLs
+ */
+ sema_init(&sc->ioctl_count_sema, MRSAS_MAX_MFI_CMDS - 5, IOCTL_SEMA_DESCRIPTION);
- mrsas_setup_sysctl(sc);
-
- /* Initiate AEN (Asynchronous Event Notification)*/
+ /* Intialize linked list */
+ TAILQ_INIT(&sc->mrsas_mpt_cmd_list_head);
+ TAILQ_INIT(&sc->mrsas_mfi_cmd_list_head);
+
+ atomic_set(&sc->fw_outstanding, 0);
+
+ sc->io_cmds_highwater = 0;
+
+ /* Create a /dev entry for this device. */
+ sc->mrsas_cdev = make_dev(&mrsas_cdevsw, device_get_unit(dev), UID_ROOT,
+ GID_OPERATOR, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP), "mrsas%u",
+ device_get_unit(dev));
+ if (device_get_unit(dev) == 0)
+ make_dev_alias(sc->mrsas_cdev, "megaraid_sas_ioctl_node");
+ if (sc->mrsas_cdev)
+ sc->mrsas_cdev->si_drv1 = sc;
+
+ sc->adprecovery = MRSAS_HBA_OPERATIONAL;
+ sc->UnevenSpanSupport = 0;
+
+ sc->msix_enable = 0;
+
+ /* Initialize Firmware */
+ if (mrsas_init_fw(sc) != SUCCESS) {
+ goto attach_fail_fw;
+ }
+ /* Register SCSI mid-layer */
+ if ((mrsas_cam_attach(sc) != SUCCESS)) {
+ goto attach_fail_cam;
+ }
+ /* Register IRQs */
+ if (mrsas_setup_irq(sc) != SUCCESS) {
+ goto attach_fail_irq;
+ }
+ /* Enable Interrupts */
+ mrsas_enable_intr(sc);
+
+ error = mrsas_kproc_create(mrsas_ocr_thread, sc,
+ &sc->ocr_thread, 0, 0, "mrsas_ocr%d",
+ device_get_unit(sc->mrsas_dev));
+ if (error) {
+ printf("Error %d starting rescan thread\n", error);
+ goto attach_fail_irq;
+ }
+ mrsas_setup_sysctl(sc);
+
+ /* Initiate AEN (Asynchronous Event Notification) */
if (mrsas_start_aen(sc)) {
printf("Error: start aen failed\n");
goto fail_start_aen;
}
+ /*
+ * Add this controller to mrsas_mgmt_info structure so that it can be
+ * exported to management applications
+ */
+ if (device_get_unit(dev) == 0)
+ memset(&mrsas_mgmt_info, 0, sizeof(mrsas_mgmt_info));
- return (0);
+ mrsas_mgmt_info.count++;
+ mrsas_mgmt_info.sc_ptr[mrsas_mgmt_info.max_index] = sc;
+ mrsas_mgmt_info.max_index++;
+
+ return (0);
fail_start_aen:
attach_fail_irq:
- mrsas_teardown_intr(sc);
+ mrsas_teardown_intr(sc);
attach_fail_cam:
- mrsas_cam_detach(sc);
+ mrsas_cam_detach(sc);
attach_fail_fw:
-//attach_fail_raidmap:
- mrsas_free_mem(sc);
- mtx_destroy(&sc->sim_lock);
- mtx_destroy(&sc->aen_lock);
- mtx_destroy(&sc->pci_lock);
- mtx_destroy(&sc->io_lock);
- mtx_destroy(&sc->ioctl_lock);
- mtx_destroy(&sc->mpt_cmd_pool_lock);
- mtx_destroy(&sc->mfi_cmd_pool_lock);
- mtx_destroy(&sc->raidmap_lock);
+ /* if MSIX vector is allocated and FW Init FAILED then release MSIX */
+ if (sc->msix_enable == 1)
+ pci_release_msi(sc->mrsas_dev);
+ mrsas_free_mem(sc);
+ mtx_destroy(&sc->sim_lock);
+ mtx_destroy(&sc->aen_lock);
+ mtx_destroy(&sc->pci_lock);
+ mtx_destroy(&sc->io_lock);
+ mtx_destroy(&sc->ioctl_lock);
+ mtx_destroy(&sc->mpt_cmd_pool_lock);
+ mtx_destroy(&sc->mfi_cmd_pool_lock);
+ mtx_destroy(&sc->raidmap_lock);
+ /* Destroy the counting semaphore created for Ioctl */
+ sema_destroy(&sc->ioctl_count_sema);
attach_fail:
- destroy_dev(sc->mrsas_cdev);
- if (sc->reg_res){
- bus_release_resource(sc->mrsas_dev, SYS_RES_MEMORY,
- sc->reg_res_id, sc->reg_res);
- }
- return (ENXIO);
-}
-
-/**
- * mrsas_detach: De-allocates and teardown resources
- * input: device struct pointer
- *
- * This function is the entry point for device disconnect and detach. It
- * performs memory de-allocations, shutdown of the controller and various
+ destroy_dev(sc->mrsas_cdev);
+ if (sc->reg_res) {
+ bus_release_resource(sc->mrsas_dev, SYS_RES_MEMORY,
+ sc->reg_res_id, sc->reg_res);
+ }
+ return (ENXIO);
+}
+
+/*
+ * mrsas_detach: De-allocates and teardown resources
+ * input: pointer to device struct
+ *
+ * This function is the entry point for device disconnect and detach.
+ * It performs memory de-allocations, shutdown of the controller and various
* teardown and destroy resource functions.
*/
-static int mrsas_detach(device_t dev)
-{
- struct mrsas_softc *sc;
- int i = 0;
-
- sc = device_get_softc(dev);
- sc->remove_in_progress = 1;
- if(sc->ocr_thread_active)
- wakeup(&sc->ocr_chan);
- while(sc->reset_in_progress){
- i++;
- if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
- mrsas_dprint(sc, MRSAS_INFO,
- "[%2d]waiting for ocr to be finished\n",i);
- }
- pause("mr_shutdown", hz);
- }
- i = 0;
- while(sc->ocr_thread_active){
- i++;
- if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
- mrsas_dprint(sc, MRSAS_INFO,
- "[%2d]waiting for "
- "mrsas_ocr thread to quit ocr %d\n",i,
- sc->ocr_thread_active);
- }
- pause("mr_shutdown", hz);
- }
- mrsas_flush_cache(sc);
- mrsas_shutdown_ctlr(sc, MR_DCMD_CTRL_SHUTDOWN);
- mrsas_disable_intr(sc);
- mrsas_cam_detach(sc);
- mrsas_teardown_intr(sc);
- mrsas_free_mem(sc);
- mtx_destroy(&sc->sim_lock);
- mtx_destroy(&sc->aen_lock);
- mtx_destroy(&sc->pci_lock);
- mtx_destroy(&sc->io_lock);
- mtx_destroy(&sc->ioctl_lock);
- mtx_destroy(&sc->mpt_cmd_pool_lock);
- mtx_destroy(&sc->mfi_cmd_pool_lock);
- mtx_destroy(&sc->raidmap_lock);
- if (sc->reg_res){
- bus_release_resource(sc->mrsas_dev,
- SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res);
- }
- destroy_dev(sc->mrsas_cdev);
- if (sc->sysctl_tree != NULL)
- sysctl_ctx_free(&sc->sysctl_ctx);
- return (0);
-}
-
-/**
- * mrsas_free_mem: Frees allocated memory
- * input: Adapter instance soft state
- *
+static int
+mrsas_detach(device_t dev)
+{
+ struct mrsas_softc *sc;
+ int i = 0;
+
+ sc = device_get_softc(dev);
+ sc->remove_in_progress = 1;
+
+ /* Destroy the character device so no other IOCTL will be handled */
+ destroy_dev(sc->mrsas_cdev);
+
+ /*
+ * Take the instance off the instance array. Note that we will not
+ * decrement the max_index. We let this array be sparse array
+ */
+ for (i = 0; i < mrsas_mgmt_info.max_index; i++) {
+ if (mrsas_mgmt_info.sc_ptr[i] == sc) {
+ mrsas_mgmt_info.count--;
+ mrsas_mgmt_info.sc_ptr[i] = NULL;
+ break;
+ }
+ }
+
+ if (sc->ocr_thread_active)
+ wakeup(&sc->ocr_chan);
+ while (sc->reset_in_progress) {
+ i++;
+ if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
+ mrsas_dprint(sc, MRSAS_INFO,
+ "[%2d]waiting for ocr to be finished\n", i);
+ }
+ pause("mr_shutdown", hz);
+ }
+ i = 0;
+ while (sc->ocr_thread_active) {
+ i++;
+ if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
+ mrsas_dprint(sc, MRSAS_INFO,
+ "[%2d]waiting for "
+ "mrsas_ocr thread to quit ocr %d\n", i,
+ sc->ocr_thread_active);
+ }
+ pause("mr_shutdown", hz);
+ }
+ mrsas_flush_cache(sc);
+ mrsas_shutdown_ctlr(sc, MR_DCMD_CTRL_SHUTDOWN);
+ mrsas_disable_intr(sc);
+ mrsas_cam_detach(sc);
+ mrsas_teardown_intr(sc);
+ mrsas_free_mem(sc);
+ mtx_destroy(&sc->sim_lock);
+ mtx_destroy(&sc->aen_lock);
+ mtx_destroy(&sc->pci_lock);
+ mtx_destroy(&sc->io_lock);
+ mtx_destroy(&sc->ioctl_lock);
+ mtx_destroy(&sc->mpt_cmd_pool_lock);
+ mtx_destroy(&sc->mfi_cmd_pool_lock);
+ mtx_destroy(&sc->raidmap_lock);
+
+ /* Wait for all the semaphores to be released */
+ while (sema_value(&sc->ioctl_count_sema) != (MRSAS_MAX_MFI_CMDS - 5))
+ pause("mr_shutdown", hz);
+
+ /* Destroy the counting semaphore created for Ioctl */
+ sema_destroy(&sc->ioctl_count_sema);
+
+ if (sc->reg_res) {
+ bus_release_resource(sc->mrsas_dev,
+ SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res);
+ }
+ if (sc->sysctl_tree != NULL)
+ sysctl_ctx_free(&sc->sysctl_ctx);
+
+ return (0);
+}
+
+/*
+ * mrsas_free_mem: Frees allocated memory
+ * input: Adapter instance soft state
+ *
* This function is called from mrsas_detach() to free previously allocated
- * memory.
+ * memory.
*/
-void mrsas_free_mem(struct mrsas_softc *sc)
+void
+mrsas_free_mem(struct mrsas_softc *sc)
{
- int i;
- u_int32_t max_cmd;
- struct mrsas_mfi_cmd *mfi_cmd;
- struct mrsas_mpt_cmd *mpt_cmd;
-
+ int i;
+ u_int32_t max_cmd;
+ struct mrsas_mfi_cmd *mfi_cmd;
+ struct mrsas_mpt_cmd *mpt_cmd;
+
+ /*
+ * Free RAID map memory
+ */
+ for (i = 0; i < 2; i++) {
+ if (sc->raidmap_phys_addr[i])
+ bus_dmamap_unload(sc->raidmap_tag[i], sc->raidmap_dmamap[i]);
+ if (sc->raidmap_mem[i] != NULL)
+ bus_dmamem_free(sc->raidmap_tag[i], sc->raidmap_mem[i], sc->raidmap_dmamap[i]);
+ if (sc->raidmap_tag[i] != NULL)
+ bus_dma_tag_destroy(sc->raidmap_tag[i]);
+
+ if (sc->ld_drv_map[i] != NULL)
+ free(sc->ld_drv_map[i], M_MRSAS);
+ }
+
+ /*
+ * Free version buffer memroy
+ */
+ if (sc->verbuf_phys_addr)
+ bus_dmamap_unload(sc->verbuf_tag, sc->verbuf_dmamap);
+ if (sc->verbuf_mem != NULL)
+ bus_dmamem_free(sc->verbuf_tag, sc->verbuf_mem, sc->verbuf_dmamap);
+ if (sc->verbuf_tag != NULL)
+ bus_dma_tag_destroy(sc->verbuf_tag);
+
+
+ /*
+ * Free sense buffer memory
+ */
+ if (sc->sense_phys_addr)
+ bus_dmamap_unload(sc->sense_tag, sc->sense_dmamap);
+ if (sc->sense_mem != NULL)
+ bus_dmamem_free(sc->sense_tag, sc->sense_mem, sc->sense_dmamap);
+ if (sc->sense_tag != NULL)
+ bus_dma_tag_destroy(sc->sense_tag);
+
+ /*
+ * Free chain frame memory
+ */
+ if (sc->chain_frame_phys_addr)
+ bus_dmamap_unload(sc->chain_frame_tag, sc->chain_frame_dmamap);
+ if (sc->chain_frame_mem != NULL)
+ bus_dmamem_free(sc->chain_frame_tag, sc->chain_frame_mem, sc->chain_frame_dmamap);
+ if (sc->chain_frame_tag != NULL)
+ bus_dma_tag_destroy(sc->chain_frame_tag);
+
+ /*
+ * Free IO Request memory
+ */
+ if (sc->io_request_phys_addr)
+ bus_dmamap_unload(sc->io_request_tag, sc->io_request_dmamap);
+ if (sc->io_request_mem != NULL)
+ bus_dmamem_free(sc->io_request_tag, sc->io_request_mem, sc->io_request_dmamap);
+ if (sc->io_request_tag != NULL)
+ bus_dma_tag_destroy(sc->io_request_tag);
+
+ /*
+ * Free Reply Descriptor memory
+ */
+ if (sc->reply_desc_phys_addr)
+ bus_dmamap_unload(sc->reply_desc_tag, sc->reply_desc_dmamap);
+ if (sc->reply_desc_mem != NULL)
+ bus_dmamem_free(sc->reply_desc_tag, sc->reply_desc_mem, sc->reply_desc_dmamap);
+ if (sc->reply_desc_tag != NULL)
+ bus_dma_tag_destroy(sc->reply_desc_tag);
+
+ /*
+ * Free event detail memory
+ */
+ if (sc->evt_detail_phys_addr)
+ bus_dmamap_unload(sc->evt_detail_tag, sc->evt_detail_dmamap);
+ if (sc->evt_detail_mem != NULL)
+ bus_dmamem_free(sc->evt_detail_tag, sc->evt_detail_mem, sc->evt_detail_dmamap);
+ if (sc->evt_detail_tag != NULL)
+ bus_dma_tag_destroy(sc->evt_detail_tag);
+
/*
- * Free RAID map memory
- */
- for (i=0; i < 2; i++)
- {
- if (sc->raidmap_phys_addr[i])
- bus_dmamap_unload(sc->raidmap_tag[i], sc->raidmap_dmamap[i]);
- if (sc->raidmap_mem[i] != NULL)
- bus_dmamem_free(sc->raidmap_tag[i], sc->raidmap_mem[i], sc->raidmap_dmamap[i]);
- if (sc->raidmap_tag[i] != NULL)
- bus_dma_tag_destroy(sc->raidmap_tag[i]);
- }
-
- /*
- * Free version buffer memroy
- */
- if (sc->verbuf_phys_addr)
- bus_dmamap_unload(sc->verbuf_tag, sc->verbuf_dmamap);
- if (sc->verbuf_mem != NULL)
- bus_dmamem_free(sc->verbuf_tag, sc->verbuf_mem, sc->verbuf_dmamap);
- if (sc->verbuf_tag != NULL)
- bus_dma_tag_destroy(sc->verbuf_tag);
-
-
- /*
- * Free sense buffer memory
- */
- if (sc->sense_phys_addr)
- bus_dmamap_unload(sc->sense_tag, sc->sense_dmamap);
- if (sc->sense_mem != NULL)
- bus_dmamem_free(sc->sense_tag, sc->sense_mem, sc->sense_dmamap);
- if (sc->sense_tag != NULL)
- bus_dma_tag_destroy(sc->sense_tag);
-
- /*
- * Free chain frame memory
- */
- if (sc->chain_frame_phys_addr)
- bus_dmamap_unload(sc->chain_frame_tag, sc->chain_frame_dmamap);
- if (sc->chain_frame_mem != NULL)
- bus_dmamem_free(sc->chain_frame_tag, sc->chain_frame_mem, sc->chain_frame_dmamap);
- if (sc->chain_frame_tag != NULL)
- bus_dma_tag_destroy(sc->chain_frame_tag);
-
- /*
- * Free IO Request memory
- */
- if (sc->io_request_phys_addr)
- bus_dmamap_unload(sc->io_request_tag, sc->io_request_dmamap);
- if (sc->io_request_mem != NULL)
- bus_dmamem_free(sc->io_request_tag, sc->io_request_mem, sc->io_request_dmamap);
- if (sc->io_request_tag != NULL)
- bus_dma_tag_destroy(sc->io_request_tag);
-
- /*
- * Free Reply Descriptor memory
- */
- if (sc->reply_desc_phys_addr)
- bus_dmamap_unload(sc->reply_desc_tag, sc->reply_desc_dmamap);
- if (sc->reply_desc_mem != NULL)
- bus_dmamem_free(sc->reply_desc_tag, sc->reply_desc_mem, sc->reply_desc_dmamap);
- if (sc->reply_desc_tag != NULL)
- bus_dma_tag_destroy(sc->reply_desc_tag);
-
- /*
- * Free event detail memory
- */
- if (sc->evt_detail_phys_addr)
- bus_dmamap_unload(sc->evt_detail_tag, sc->evt_detail_dmamap);
- if (sc->evt_detail_mem != NULL)
- bus_dmamem_free(sc->evt_detail_tag, sc->evt_detail_mem, sc->evt_detail_dmamap);
- if (sc->evt_detail_tag != NULL)
- bus_dma_tag_destroy(sc->evt_detail_tag);
-
- /*
- * Free MFI frames
- */
+ * Free MFI frames
+ */
if (sc->mfi_cmd_list) {
- for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
- mfi_cmd = sc->mfi_cmd_list[i];
- mrsas_free_frame(sc, mfi_cmd);
+ for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
+ mfi_cmd = sc->mfi_cmd_list[i];
+ mrsas_free_frame(sc, mfi_cmd);
}
- }
- if (sc->mficmd_frame_tag != NULL)
- bus_dma_tag_destroy(sc->mficmd_frame_tag);
-
- /*
- * Free MPT internal command list
- */
- max_cmd = sc->max_fw_cmds;
+ }
+ if (sc->mficmd_frame_tag != NULL)
+ bus_dma_tag_destroy(sc->mficmd_frame_tag);
+
+ /*
+ * Free MPT internal command list
+ */
+ max_cmd = sc->max_fw_cmds;
if (sc->mpt_cmd_list) {
- for (i = 0; i < max_cmd; i++) {
- mpt_cmd = sc->mpt_cmd_list[i];
- bus_dmamap_destroy(sc->data_tag, mpt_cmd->data_dmamap);
- free(sc->mpt_cmd_list[i], M_MRSAS);
- }
- free(sc->mpt_cmd_list, M_MRSAS);
- sc->mpt_cmd_list = NULL;
- }
-
- /*
- * Free MFI internal command list
- */
-
- if (sc->mfi_cmd_list) {
- for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
- free(sc->mfi_cmd_list[i], M_MRSAS);
- }
- free(sc->mfi_cmd_list, M_MRSAS);
- sc->mfi_cmd_list = NULL;
+ for (i = 0; i < max_cmd; i++) {
+ mpt_cmd = sc->mpt_cmd_list[i];
+ bus_dmamap_destroy(sc->data_tag, mpt_cmd->data_dmamap);
+ free(sc->mpt_cmd_list[i], M_MRSAS);
+ }
+ free(sc->mpt_cmd_list, M_MRSAS);
+ sc->mpt_cmd_list = NULL;
}
+ /*
+ * Free MFI internal command list
+ */
- /*
- * Free request descriptor memory
- */
- free(sc->req_desc, M_MRSAS);
- sc->req_desc = NULL;
+ if (sc->mfi_cmd_list) {
+ for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
+ free(sc->mfi_cmd_list[i], M_MRSAS);
+ }
+ free(sc->mfi_cmd_list, M_MRSAS);
+ sc->mfi_cmd_list = NULL;
+ }
+ /*
+ * Free request descriptor memory
+ */
+ free(sc->req_desc, M_MRSAS);
+ sc->req_desc = NULL;
- /*
- * Destroy parent tag
- */
- if (sc->mrsas_parent_tag != NULL)
- bus_dma_tag_destroy(sc->mrsas_parent_tag);
+ /*
+ * Destroy parent tag
+ */
+ if (sc->mrsas_parent_tag != NULL)
+ bus_dma_tag_destroy(sc->mrsas_parent_tag);
}
-/**
- * mrsas_teardown_intr: Teardown interrupt
- * input: Adapter instance soft state
+/*
+ * mrsas_teardown_intr: Teardown interrupt
+ * input: Adapter instance soft state
*
- * This function is called from mrsas_detach() to teardown and release
- * bus interrupt resourse.
+ * This function is called from mrsas_detach() to teardown and release bus
+ * interrupt resourse.
*/
-void mrsas_teardown_intr(struct mrsas_softc *sc)
+void
+mrsas_teardown_intr(struct mrsas_softc *sc)
{
- if (sc->intr_handle)
- bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq, sc->intr_handle);
- if (sc->mrsas_irq != NULL)
- bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ, sc->irq_id, sc->mrsas_irq);
- sc->intr_handle = NULL;
+ int i;
+
+ if (!sc->msix_enable) {
+ if (sc->intr_handle[0])
+ bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[0], sc->intr_handle[0]);
+ if (sc->mrsas_irq[0] != NULL)
+ bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ,
+ sc->irq_id[0], sc->mrsas_irq[0]);
+ sc->intr_handle[0] = NULL;
+ } else {
+ for (i = 0; i < sc->msix_vectors; i++) {
+ if (sc->intr_handle[i])
+ bus_teardown_intr(sc->mrsas_dev, sc->mrsas_irq[i],
+ sc->intr_handle[i]);
+
+ if (sc->mrsas_irq[i] != NULL)
+ bus_release_resource(sc->mrsas_dev, SYS_RES_IRQ,
+ sc->irq_id[i], sc->mrsas_irq[i]);
+
+ sc->intr_handle[i] = NULL;
+ }
+ pci_release_msi(sc->mrsas_dev);
+ }
+
}
-/**
- * mrsas_suspend: Suspend entry point
- * input: Device struct pointer
- *
- * This function is the entry point for system suspend from the OS.
+/*
+ * mrsas_suspend: Suspend entry point
+ * input: Device struct pointer
+ *
+ * This function is the entry point for system suspend from the OS.
*/
-static int mrsas_suspend(device_t dev)
+static int
+mrsas_suspend(device_t dev)
{
- struct mrsas_softc *sc;
+ struct mrsas_softc *sc;
- sc = device_get_softc(dev);
- return (0);
+ sc = device_get_softc(dev);
+ return (0);
}
-/**
- * mrsas_resume: Resume entry point
- * input: Device struct pointer
- *
- * This function is the entry point for system resume from the OS.
+/*
+ * mrsas_resume: Resume entry point
+ * input: Device struct pointer
+ *
+ * This function is the entry point for system resume from the OS.
*/
-static int mrsas_resume(device_t dev)
+static int
+mrsas_resume(device_t dev)
{
- struct mrsas_softc *sc;
+ struct mrsas_softc *sc;
- sc = device_get_softc(dev);
- return (0);
+ sc = device_get_softc(dev);
+ return (0);
}
-/**
- * mrsas_ioctl: IOCtl commands entry point.
- *
- * This function is the entry point for IOCtls from the OS. It calls the
+/*
+ * mrsas_ioctl: IOCtl commands entry point.
+ *
+ * This function is the entry point for IOCtls from the OS. It calls the
* appropriate function for processing depending on the command received.
*/
static int
mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
{
- struct mrsas_softc *sc;
- int ret = 0, i = 0;
-
- sc = (struct mrsas_softc *)(dev->si_drv1);
-
- if (sc->remove_in_progress) {
- mrsas_dprint(sc, MRSAS_INFO,
- "Driver remove or shutdown called.\n");
- return ENOENT;
- }
-
- mtx_lock_spin(&sc->ioctl_lock);
- if (!sc->reset_in_progress) {
- mtx_unlock_spin(&sc->ioctl_lock);
- goto do_ioctl;
- }
-
- /* Release ioclt_lock, and wait for OCR
- * to be finished */
- mtx_unlock_spin(&sc->ioctl_lock);
- while(sc->reset_in_progress){
- i++;
- if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
- mrsas_dprint(sc, MRSAS_INFO,
- "[%2d]waiting for "
- "OCR to be finished %d\n",i,
- sc->ocr_thread_active);
- }
- pause("mr_ioctl", hz);
- }
+ struct mrsas_softc *sc;
+ int ret = 0, i = 0;
+
+ struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
+
+ /* get the Host number & the softc from data sent by the Application */
+ sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no];
+
+ if ((mrsas_mgmt_info.max_index == user_ioc->host_no) || (sc == NULL)) {
+ printf("Please check the controller number\n");
+ if (sc == NULL)
+ printf("There is NO such Host no. %d\n", user_ioc->host_no);
+
+ return ENOENT;
+ }
+ if (sc->remove_in_progress) {
+ mrsas_dprint(sc, MRSAS_INFO,
+ "Driver remove or shutdown called.\n");
+ return ENOENT;
+ }
+ mtx_lock_spin(&sc->ioctl_lock);
+ if (!sc->reset_in_progress) {
+ mtx_unlock_spin(&sc->ioctl_lock);
+ goto do_ioctl;
+ }
+ mtx_unlock_spin(&sc->ioctl_lock);
+ while (sc->reset_in_progress) {
+ i++;
+ if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
+ mrsas_dprint(sc, MRSAS_INFO,
+ "[%2d]waiting for "
+ "OCR to be finished %d\n", i,
+ sc->ocr_thread_active);
+ }
+ pause("mr_ioctl", hz);
+ }
do_ioctl:
- switch (cmd) {
- case MRSAS_IOC_FIRMWARE_PASS_THROUGH:
- ret = mrsas_passthru(sc, (void *)arg);
- break;
- case MRSAS_IOC_SCAN_BUS:
- ret = mrsas_bus_scan(sc);
- break;
- }
-
- return (ret);
-}
-
-/**
- * mrsas_setup_irq: Set up interrupt.
- * input: Adapter instance soft state
- *
+ switch (cmd) {
+ case MRSAS_IOC_FIRMWARE_PASS_THROUGH64:
+#ifdef COMPAT_FREEBSD32
+ case MRSAS_IOC_FIRMWARE_PASS_THROUGH32:
+#endif
+ /*
+ * Decrement the Ioctl counting Semaphore before getting an
+ * mfi command
+ */
+ sema_wait(&sc->ioctl_count_sema);
+
+ ret = mrsas_passthru(sc, (void *)arg, cmd);
+
+ /* Increment the Ioctl counting semaphore value */
+ sema_post(&sc->ioctl_count_sema);
+
+ break;
+ case MRSAS_IOC_SCAN_BUS:
+ ret = mrsas_bus_scan(sc);
+ break;
+ default:
+ mrsas_dprint(sc, MRSAS_TRACE, "IOCTL command 0x%lx is not handled\n", cmd);
+ ret = ENOENT;
+ }
+
+ return (ret);
+}
+
+/*
+ * mrsas_poll: poll entry point for mrsas driver fd
+ *
+ * This function is the entry point for poll from the OS. It waits for some AEN
+ * events to be triggered from the controller and notifies back.
+ */
+static int
+mrsas_poll(struct cdev *dev, int poll_events, struct thread *td)
+{
+ struct mrsas_softc *sc;
+ int revents = 0;
+
+ sc = dev->si_drv1;
+
+ if (poll_events & (POLLIN | POLLRDNORM)) {
+ if (sc->mrsas_aen_triggered) {
+ revents |= poll_events & (POLLIN | POLLRDNORM);
+ }
+ }
+ if (revents == 0) {
+ if (poll_events & (POLLIN | POLLRDNORM)) {
+ sc->mrsas_poll_waiting = 1;
+ selrecord(td, &sc->mrsas_select);
+ }
+ }
+ return revents;
+}
+
+/*
+ * mrsas_setup_irq: Set up interrupt
+ * input: Adapter instance soft state
+ *
* This function sets up interrupts as a bus resource, with flags indicating
- * resource permitting contemporaneous sharing and for resource to activate
+ * resource permitting contemporaneous sharing and for resource to activate
* atomically.
*/
-static int mrsas_setup_irq(struct mrsas_softc *sc)
+static int
+mrsas_setup_irq(struct mrsas_softc *sc)
+{
+ if (sc->msix_enable && (mrsas_setup_msix(sc) == SUCCESS))
+ device_printf(sc->mrsas_dev, "MSI-x interrupts setup success\n");
+
+ else {
+ device_printf(sc->mrsas_dev, "Fall back to legacy interrupt\n");
+ sc->irq_context[0].sc = sc;
+ sc->irq_context[0].MSIxIndex = 0;
+ sc->irq_id[0] = 0;
+ sc->mrsas_irq[0] = bus_alloc_resource_any(sc->mrsas_dev,
+ SYS_RES_IRQ, &sc->irq_id[0], RF_SHAREABLE | RF_ACTIVE);
+ if (sc->mrsas_irq[0] == NULL) {
+ device_printf(sc->mrsas_dev, "Cannot allocate legcay"
+ "interrupt\n");
+ return (FAIL);
+ }
+ if (bus_setup_intr(sc->mrsas_dev, sc->mrsas_irq[0],
+ INTR_MPSAFE | INTR_TYPE_CAM, NULL, mrsas_isr,
+ &sc->irq_context[0], &sc->intr_handle[0])) {
+ device_printf(sc->mrsas_dev, "Cannot set up legacy"
+ "interrupt\n");
+ return (FAIL);
+ }
+ }
+ return (0);
+}
+
+/*
+ * mrsas_isr: ISR entry point
+ * input: argument pointer
+ *
+ * This function is the interrupt service routine entry point. There are two
+ * types of interrupts, state change interrupt and response interrupt. If an
+ * interrupt is not ours, we just return.
+ */
+void
+mrsas_isr(void *arg)
{
- sc->irq_id = 0;
- sc->mrsas_irq = bus_alloc_resource_any(sc->mrsas_dev, SYS_RES_IRQ,
- &sc->irq_id, RF_SHAREABLE | RF_ACTIVE);
- if (sc->mrsas_irq == NULL){
- device_printf(sc->mrsas_dev, "Cannot allocate interrupt\n");
- return (FAIL);
- }
- if (bus_setup_intr(sc->mrsas_dev, sc->mrsas_irq, INTR_MPSAFE|INTR_TYPE_CAM,
- NULL, mrsas_isr, sc, &sc->intr_handle)) {
- device_printf(sc->mrsas_dev, "Cannot set up interrupt\n");
- return (FAIL);
- }
-
- return (0);
-}
-
-/*
- * mrsas_isr: ISR entry point
- * input: argument pointer
- *
- * This function is the interrupt service routine entry point. There
- * are two types of interrupts, state change interrupt and response
- * interrupt. If an interrupt is not ours, we just return.
- */
-void mrsas_isr(void *arg)
-{
- struct mrsas_softc *sc = (struct mrsas_softc *)arg;
- int status;
-
- /* Clear FW state change interrupt */
- status = mrsas_clear_intr(sc);
-
- /* Not our interrupt */
- if (!status)
- return;
-
- /* If we are resetting, bail */
- if (test_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags)) {
- printf(" Entered into ISR when OCR is going active. \n");
- mrsas_clear_intr(sc);
- return;
- }
- /* Process for reply request and clear response interrupt */
- if (mrsas_complete_cmd(sc) != SUCCESS)
- mrsas_clear_intr(sc);
-
- return;
-}
-
-/*
- * mrsas_complete_cmd: Process reply request
- * input: Adapter instance soft state
- *
- * This function is called from mrsas_isr() to process reply request and
- * clear response interrupt. Processing of the reply request entails
- * walking through the reply descriptor array for the command request
- * pended from Firmware. We look at the Function field to determine
- * the command type and perform the appropriate action. Before we
- * return, we clear the response interrupt.
- */
-static int mrsas_complete_cmd(struct mrsas_softc *sc)
-{
- Mpi2ReplyDescriptorsUnion_t *desc;
- MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
- MRSAS_RAID_SCSI_IO_REQUEST *scsi_io_req;
- struct mrsas_mpt_cmd *cmd_mpt;
- struct mrsas_mfi_cmd *cmd_mfi;
- u_int8_t arm, reply_descript_type;
- u_int16_t smid, num_completed;
- u_int8_t status, extStatus;
- union desc_value desc_val;
- PLD_LOAD_BALANCE_INFO lbinfo;
- u_int32_t device_id;
- int threshold_reply_count = 0;
-
-
- /* If we have a hardware error, not need to continue */
- if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR)
- return (DONE);
-
- desc = sc->reply_desc_mem;
- desc += sc->last_reply_idx;
-
- reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
-
- desc_val.word = desc->Words;
- num_completed = 0;
-
- reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
-
- /* Find our reply descriptor for the command and process */
- while((desc_val.u.low != 0xFFFFFFFF) && (desc_val.u.high != 0xFFFFFFFF))
- {
- smid = reply_desc->SMID;
- cmd_mpt = sc->mpt_cmd_list[smid -1];
- scsi_io_req = (MRSAS_RAID_SCSI_IO_REQUEST *)cmd_mpt->io_request;
-
- status = scsi_io_req->RaidContext.status;
- extStatus = scsi_io_req->RaidContext.exStatus;
-
- switch (scsi_io_req->Function)
- {
- case MPI2_FUNCTION_SCSI_IO_REQUEST : /*Fast Path IO.*/
- device_id = cmd_mpt->ccb_ptr->ccb_h.target_id;
- lbinfo = &sc->load_balance_info[device_id];
- if (cmd_mpt->load_balance == MRSAS_LOAD_BALANCE_FLAG) {
- arm = lbinfo->raid1DevHandle[0] == scsi_io_req->DevHandle ? 0 : 1;
- atomic_dec(&lbinfo->scsi_pending_cmds[arm]);
- cmd_mpt->load_balance &= ~MRSAS_LOAD_BALANCE_FLAG;
- }
- //Fall thru and complete IO
- case MRSAS_MPI2_FUNCTION_LD_IO_REQUEST:
- mrsas_map_mpt_cmd_status(cmd_mpt, status, extStatus);
- mrsas_cmd_done(sc, cmd_mpt);
- scsi_io_req->RaidContext.status = 0;
- scsi_io_req->RaidContext.exStatus = 0;
- atomic_dec(&sc->fw_outstanding);
- break;
- case MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */
- cmd_mfi = sc->mfi_cmd_list[cmd_mpt->sync_cmd_idx];
- mrsas_complete_mptmfi_passthru(sc, cmd_mfi, status);
- cmd_mpt->flags = 0;
- mrsas_release_mpt_cmd(cmd_mpt);
- break;
- }
-
- sc->last_reply_idx++;
- if (sc->last_reply_idx >= sc->reply_q_depth)
- sc->last_reply_idx = 0;
-
- desc->Words = ~((uint64_t)0x00); /* set it back to all 0xFFFFFFFFs */
- num_completed++;
- threshold_reply_count++;
-
- /* Get the next reply descriptor */
- if (!sc->last_reply_idx)
- desc = sc->reply_desc_mem;
- else
- desc++;
-
- reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc;
- desc_val.word = desc->Words;
-
- reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
-
- if(reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
- break;
-
- /*
- * Write to reply post index after completing threshold reply count
- * and still there are more replies in reply queue pending to be
- * completed.
- */
- if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, reply_post_host_index),
- sc->last_reply_idx);
- threshold_reply_count = 0;
- }
- }
-
- /* No match, just return */
- if (num_completed == 0)
- return (DONE);
-
- /* Clear response interrupt */
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, reply_post_host_index),sc->last_reply_idx);
-
- return(0);
-}
-
-/*
- * mrsas_map_mpt_cmd_status: Allocate DMAable memory.
- * input: Adapter instance soft state
+ struct mrsas_irq_context *irq_context = (struct mrsas_irq_context *)arg;
+ struct mrsas_softc *sc = irq_context->sc;
+ int status = 0;
+
+ if (!sc->msix_vectors) {
+ status = mrsas_clear_intr(sc);
+ if (!status)
+ return;
+ }
+ /* If we are resetting, bail */
+ if (test_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags)) {
+ printf(" Entered into ISR when OCR is going active. \n");
+ mrsas_clear_intr(sc);
+ return;
+ }
+ /* Process for reply request and clear response interrupt */
+ if (mrsas_complete_cmd(sc, irq_context->MSIxIndex) != SUCCESS)
+ mrsas_clear_intr(sc);
+
+ return;
+}
+
+/*
+ * mrsas_complete_cmd: Process reply request
+ * input: Adapter instance soft state
+ *
+ * This function is called from mrsas_isr() to process reply request and clear
+ * response interrupt. Processing of the reply request entails walking
+ * through the reply descriptor array for the command request pended from
+ * Firmware. We look at the Function field to determine the command type and
+ * perform the appropriate action. Before we return, we clear the response
+ * interrupt.
+ */
+static int
+mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex)
+{
+ Mpi2ReplyDescriptorsUnion_t *desc;
+ MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
+ MRSAS_RAID_SCSI_IO_REQUEST *scsi_io_req;
+ struct mrsas_mpt_cmd *cmd_mpt;
+ struct mrsas_mfi_cmd *cmd_mfi;
+ u_int8_t arm, reply_descript_type;
+ u_int16_t smid, num_completed;
+ u_int8_t status, extStatus;
+ union desc_value desc_val;
+ PLD_LOAD_BALANCE_INFO lbinfo;
+ u_int32_t device_id;
+ int threshold_reply_count = 0;
+
+
+ /* If we have a hardware error, not need to continue */
+ if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR)
+ return (DONE);
+
+ desc = sc->reply_desc_mem;
+ desc += ((MSIxIndex * sc->reply_alloc_sz) / sizeof(MPI2_REPLY_DESCRIPTORS_UNION))
+ + sc->last_reply_idx[MSIxIndex];
+
+ reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *) desc;
+
+ desc_val.word = desc->Words;
+ num_completed = 0;
+
+ reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+
+ /* Find our reply descriptor for the command and process */
+ while ((desc_val.u.low != 0xFFFFFFFF) && (desc_val.u.high != 0xFFFFFFFF)) {
+ smid = reply_desc->SMID;
+ cmd_mpt = sc->mpt_cmd_list[smid - 1];
+ scsi_io_req = (MRSAS_RAID_SCSI_IO_REQUEST *) cmd_mpt->io_request;
+
+ status = scsi_io_req->RaidContext.status;
+ extStatus = scsi_io_req->RaidContext.exStatus;
+
+ switch (scsi_io_req->Function) {
+ case MPI2_FUNCTION_SCSI_IO_REQUEST: /* Fast Path IO. */
+ device_id = cmd_mpt->ccb_ptr->ccb_h.target_id;
+ lbinfo = &sc->load_balance_info[device_id];
+ if (cmd_mpt->load_balance == MRSAS_LOAD_BALANCE_FLAG) {
+ arm = lbinfo->raid1DevHandle[0] == scsi_io_req->DevHandle ? 0 : 1;
+ atomic_dec(&lbinfo->scsi_pending_cmds[arm]);
+ cmd_mpt->load_balance &= ~MRSAS_LOAD_BALANCE_FLAG;
+ }
+ /* Fall thru and complete IO */
+ case MRSAS_MPI2_FUNCTION_LD_IO_REQUEST:
+ mrsas_map_mpt_cmd_status(cmd_mpt, status, extStatus);
+ mrsas_cmd_done(sc, cmd_mpt);
+ scsi_io_req->RaidContext.status = 0;
+ scsi_io_req->RaidContext.exStatus = 0;
+ atomic_dec(&sc->fw_outstanding);
+ break;
+ case MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /* MFI command */
+ cmd_mfi = sc->mfi_cmd_list[cmd_mpt->sync_cmd_idx];
+ mrsas_complete_mptmfi_passthru(sc, cmd_mfi, status);
+ cmd_mpt->flags = 0;
+ mrsas_release_mpt_cmd(cmd_mpt);
+ break;
+ }
+
+ sc->last_reply_idx[MSIxIndex]++;
+ if (sc->last_reply_idx[MSIxIndex] >= sc->reply_q_depth)
+ sc->last_reply_idx[MSIxIndex] = 0;
+
+ desc->Words = ~((uint64_t)0x00); /* set it back to all
+ * 0xFFFFFFFFs */
+ num_completed++;
+ threshold_reply_count++;
+
+ /* Get the next reply descriptor */
+ if (!sc->last_reply_idx[MSIxIndex]) {
+ desc = sc->reply_desc_mem;
+ desc += ((MSIxIndex * sc->reply_alloc_sz) / sizeof(MPI2_REPLY_DESCRIPTORS_UNION));
+ } else
+ desc++;
+
+ reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *) desc;
+ desc_val.word = desc->Words;
+
+ reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+
+ if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+ break;
+
+ /*
+ * Write to reply post index after completing threshold reply
+ * count and still there are more replies in reply queue
+ * pending to be completed.
+ */
+ if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
+ if (sc->msix_enable) {
+ if ((sc->device_id == MRSAS_INVADER) ||
+ (sc->device_id == MRSAS_FURY))
+ mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8],
+ ((MSIxIndex & 0x7) << 24) |
+ sc->last_reply_idx[MSIxIndex]);
+ else
+ mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
+ sc->last_reply_idx[MSIxIndex]);
+ } else
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set,
+ reply_post_host_index), sc->last_reply_idx[0]);
+
+ threshold_reply_count = 0;
+ }
+ }
+
+ /* No match, just return */
+ if (num_completed == 0)
+ return (DONE);
+
+ /* Clear response interrupt */
+ if (sc->msix_enable) {
+ if ((sc->device_id == MRSAS_INVADER) ||
+ (sc->device_id == MRSAS_FURY)) {
+ mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8],
+ ((MSIxIndex & 0x7) << 24) |
+ sc->last_reply_idx[MSIxIndex]);
+ } else
+ mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
+ sc->last_reply_idx[MSIxIndex]);
+ } else
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set,
+ reply_post_host_index), sc->last_reply_idx[0]);
+
+ return (0);
+}
+
+/*
+ * mrsas_map_mpt_cmd_status: Allocate DMAable memory.
+ * input: Adapter instance soft state
*
* This function is called from mrsas_complete_cmd(), for LD IO and FastPath IO.
- * It checks the command status and maps the appropriate CAM status for the CCB.
- */
-void mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8_t extStatus)
-{
- struct mrsas_softc *sc = cmd->sc;
- u_int8_t *sense_data;
-
- switch (status) {
- case MFI_STAT_OK:
- cmd->ccb_ptr->ccb_h.status = CAM_REQ_CMP;
- break;
- case MFI_STAT_SCSI_IO_FAILED:
- case MFI_STAT_SCSI_DONE_WITH_ERROR:
- cmd->ccb_ptr->ccb_h.status = CAM_SCSI_STATUS_ERROR;
- sense_data = (u_int8_t *)&cmd->ccb_ptr->csio.sense_data;
- if (sense_data) {
- /* For now just copy 18 bytes back */
- memcpy(sense_data, cmd->sense, 18);
- cmd->ccb_ptr->csio.sense_len = 18;
- cmd->ccb_ptr->ccb_h.status |= CAM_AUTOSNS_VALID;
- }
- break;
- case MFI_STAT_LD_OFFLINE:
- case MFI_STAT_DEVICE_NOT_FOUND:
- if (cmd->ccb_ptr->ccb_h.target_lun)
- cmd->ccb_ptr->ccb_h.status |= CAM_LUN_INVALID;
- else
- cmd->ccb_ptr->ccb_h.status |= CAM_DEV_NOT_THERE;
- break;
- case MFI_STAT_CONFIG_SEQ_MISMATCH:
- /*send status to CAM layer to retry sending command without
- * decrementing retry counter*/
- cmd->ccb_ptr->ccb_h.status |= CAM_REQUEUE_REQ;
- break;
- default:
- device_printf(sc->mrsas_dev, "FW cmd complete status %x\n", status);
- cmd->ccb_ptr->ccb_h.status = CAM_REQ_CMP_ERR;
- cmd->ccb_ptr->csio.scsi_status = status;
- }
- return;
-}
-
-/*
- * mrsas_alloc_mem: Allocate DMAable memory.
- * input: Adapter instance soft state
- *
- * This function creates the parent DMA tag and allocates DMAable memory.
- * DMA tag describes constraints of DMA mapping. Memory allocated is mapped
- * into Kernel virtual address. Callback argument is physical memory address.
- */
-static int mrsas_alloc_mem(struct mrsas_softc *sc)
-{
- u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size,
- chain_frame_size, evt_detail_size;
-
- /*
- * Allocate parent DMA tag
- */
- if (bus_dma_tag_create(NULL, /* parent */
- 1, /* alignment */
- 0, /* boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MRSAS_MAX_IO_SIZE,/* maxsize */
- MRSAS_MAX_SGL, /* nsegments */
- MRSAS_MAX_IO_SIZE,/* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->mrsas_parent_tag /* tag */
- )) {
- device_printf(sc->mrsas_dev, "Cannot allocate parent DMA tag\n");
- return(ENOMEM);
- }
-
- /*
- * Allocate for version buffer
- */
- verbuf_size = MRSAS_MAX_NAME_LENGTH*(sizeof(bus_addr_t));
- if (bus_dma_tag_create(sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- verbuf_size, // maxsize
- 1, // msegments
- verbuf_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->verbuf_tag)) {
- device_printf(sc->mrsas_dev, "Cannot allocate verbuf DMA tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->verbuf_tag, (void **)&sc->verbuf_mem,
- BUS_DMA_NOWAIT, &sc->verbuf_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot allocate verbuf memory\n");
- return (ENOMEM);
- }
- bzero(sc->verbuf_mem, verbuf_size);
- if (bus_dmamap_load(sc->verbuf_tag, sc->verbuf_dmamap, sc->verbuf_mem,
- verbuf_size, mrsas_addr_cb, &sc->verbuf_phys_addr, BUS_DMA_NOWAIT)){
- device_printf(sc->mrsas_dev, "Cannot load verbuf DMA map\n");
- return(ENOMEM);
- }
-
- /*
- * Allocate IO Request Frames
- */
- io_req_size = sc->io_frames_alloc_sz;
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 16, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- io_req_size, // maxsize
- 1, // msegments
- io_req_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->io_request_tag)) {
- device_printf(sc->mrsas_dev, "Cannot create IO request tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->io_request_tag, (void **)&sc->io_request_mem,
- BUS_DMA_NOWAIT, &sc->io_request_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot alloc IO request memory\n");
- return (ENOMEM);
- }
- bzero(sc->io_request_mem, io_req_size);
- if (bus_dmamap_load(sc->io_request_tag, sc->io_request_dmamap,
- sc->io_request_mem, io_req_size, mrsas_addr_cb,
- &sc->io_request_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
- return (ENOMEM);
- }
-
- /*
- * Allocate Chain Frames
- */
- chain_frame_size = sc->chain_frames_alloc_sz;
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 4, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- chain_frame_size, // maxsize
- 1, // msegments
- chain_frame_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->chain_frame_tag)) {
- device_printf(sc->mrsas_dev, "Cannot create chain frame tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->chain_frame_tag, (void **)&sc->chain_frame_mem,
- BUS_DMA_NOWAIT, &sc->chain_frame_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot alloc chain frame memory\n");
- return (ENOMEM);
- }
- bzero(sc->chain_frame_mem, chain_frame_size);
- if (bus_dmamap_load(sc->chain_frame_tag, sc->chain_frame_dmamap,
- sc->chain_frame_mem, chain_frame_size, mrsas_addr_cb,
- &sc->chain_frame_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load chain frame memory\n");
- return (ENOMEM);
- }
-
- /*
- * Allocate Reply Descriptor Array
- */
- reply_desc_size = sc->reply_alloc_sz;
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 16, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- reply_desc_size, // maxsize
- 1, // msegments
- reply_desc_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->reply_desc_tag)) {
- device_printf(sc->mrsas_dev, "Cannot create reply descriptor tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->reply_desc_tag, (void **)&sc->reply_desc_mem,
- BUS_DMA_NOWAIT, &sc->reply_desc_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot alloc reply descriptor memory\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(sc->reply_desc_tag, sc->reply_desc_dmamap,
- sc->reply_desc_mem, reply_desc_size, mrsas_addr_cb,
- &sc->reply_desc_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load reply descriptor memory\n");
- return (ENOMEM);
- }
-
- /*
- * Allocate Sense Buffer Array. Keep in lower 4GB
- */
- sense_size = sc->max_fw_cmds * MRSAS_SENSE_LEN;
- if (bus_dma_tag_create(sc->mrsas_parent_tag, // parent
- 64, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- sense_size, // maxsize
- 1, // nsegments
- sense_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->sense_tag)) {
- device_printf(sc->mrsas_dev, "Cannot allocate sense buf tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->sense_tag, (void **)&sc->sense_mem,
- BUS_DMA_NOWAIT, &sc->sense_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot allocate sense buf memory\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(sc->sense_tag, sc->sense_dmamap,
- sc->sense_mem, sense_size, mrsas_addr_cb, &sc->sense_phys_addr,
- BUS_DMA_NOWAIT)){
- device_printf(sc->mrsas_dev, "Cannot load sense buf memory\n");
- return (ENOMEM);
- }
-
- /*
- * Allocate for Event detail structure
- */
- evt_detail_size = sizeof(struct mrsas_evt_detail);
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- evt_detail_size, // maxsize
- 1, // msegments
- evt_detail_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->evt_detail_tag)) {
- device_printf(sc->mrsas_dev, "Cannot create Event detail tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->evt_detail_tag, (void **)&sc->evt_detail_mem,
- BUS_DMA_NOWAIT, &sc->evt_detail_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot alloc Event detail buffer memory\n");
- return (ENOMEM);
- }
- bzero(sc->evt_detail_mem, evt_detail_size);
- if (bus_dmamap_load(sc->evt_detail_tag, sc->evt_detail_dmamap,
- sc->evt_detail_mem, evt_detail_size, mrsas_addr_cb,
- &sc->evt_detail_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load Event detail buffer memory\n");
- return (ENOMEM);
- }
-
-
- /*
- * Create a dma tag for data buffers; size will be the maximum
- * possible I/O size (280kB).
- */
- if (bus_dma_tag_create(sc->mrsas_parent_tag, // parent
- 1, // alignment
- 0, // boundary
- BUS_SPACE_MAXADDR, // lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- MRSAS_MAX_IO_SIZE, // maxsize
- MRSAS_MAX_SGL, // nsegments
- MRSAS_MAX_IO_SIZE, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- busdma_lock_mutex, // lockfunc
- &sc->io_lock, // lockfuncarg
- &sc->data_tag)) {
- device_printf(sc->mrsas_dev, "Cannot create data dma tag\n");
- return(ENOMEM);
- }
-
- return(0);
-}
-
-/*
- * mrsas_addr_cb: Callback function of bus_dmamap_load()
- * input: callback argument,
- * machine dependent type that describes DMA segments,
- * number of segments,
- * error code.
- *
- * This function is for the driver to receive mapping information resultant
- * of the bus_dmamap_load(). The information is actually not being used,
- * but the address is saved anyway.
+ * It checks the command status and maps the appropriate CAM status for the
+ * CCB.
+ */
+void
+mrsas_map_mpt_cmd_status(struct mrsas_mpt_cmd *cmd, u_int8_t status, u_int8_t extStatus)
+{
+ struct mrsas_softc *sc = cmd->sc;
+ u_int8_t *sense_data;
+
+ switch (status) {
+ case MFI_STAT_OK:
+ cmd->ccb_ptr->ccb_h.status = CAM_REQ_CMP;
+ break;
+ case MFI_STAT_SCSI_IO_FAILED:
+ case MFI_STAT_SCSI_DONE_WITH_ERROR:
+ cmd->ccb_ptr->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ sense_data = (u_int8_t *)&cmd->ccb_ptr->csio.sense_data;
+ if (sense_data) {
+ /* For now just copy 18 bytes back */
+ memcpy(sense_data, cmd->sense, 18);
+ cmd->ccb_ptr->csio.sense_len = 18;
+ cmd->ccb_ptr->ccb_h.status |= CAM_AUTOSNS_VALID;
+ }
+ break;
+ case MFI_STAT_LD_OFFLINE:
+ case MFI_STAT_DEVICE_NOT_FOUND:
+ if (cmd->ccb_ptr->ccb_h.target_lun)
+ cmd->ccb_ptr->ccb_h.status |= CAM_LUN_INVALID;
+ else
+ cmd->ccb_ptr->ccb_h.status |= CAM_DEV_NOT_THERE;
+ break;
+ case MFI_STAT_CONFIG_SEQ_MISMATCH:
+ cmd->ccb_ptr->ccb_h.status |= CAM_REQUEUE_REQ;
+ break;
+ default:
+ device_printf(sc->mrsas_dev, "FW cmd complete status %x\n", status);
+ cmd->ccb_ptr->ccb_h.status = CAM_REQ_CMP_ERR;
+ cmd->ccb_ptr->csio.scsi_status = status;
+ }
+ return;
+}
+
+/*
+ * mrsas_alloc_mem: Allocate DMAable memory
+ * input: Adapter instance soft state
+ *
+ * This function creates the parent DMA tag and allocates DMAable memory. DMA
+ * tag describes constraints of DMA mapping. Memory allocated is mapped into
+ * Kernel virtual address. Callback argument is physical memory address.
+ */
+static int
+mrsas_alloc_mem(struct mrsas_softc *sc)
+{
+ u_int32_t verbuf_size, io_req_size, reply_desc_size, sense_size, chain_frame_size,
+ evt_detail_size, count;
+
+ /*
+ * Allocate parent DMA tag
+ */
+ if (bus_dma_tag_create(NULL, /* parent */
+ 1, /* alignment */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MRSAS_MAX_IO_SIZE, /* maxsize */
+ MRSAS_MAX_SGL, /* nsegments */
+ MRSAS_MAX_IO_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->mrsas_parent_tag /* tag */
+ )) {
+ device_printf(sc->mrsas_dev, "Cannot allocate parent DMA tag\n");
+ return (ENOMEM);
+ }
+ /*
+ * Allocate for version buffer
+ */
+ verbuf_size = MRSAS_MAX_NAME_LENGTH * (sizeof(bus_addr_t));
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ verbuf_size,
+ 1,
+ verbuf_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->verbuf_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate verbuf DMA tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->verbuf_tag, (void **)&sc->verbuf_mem,
+ BUS_DMA_NOWAIT, &sc->verbuf_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate verbuf memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->verbuf_mem, verbuf_size);
+ if (bus_dmamap_load(sc->verbuf_tag, sc->verbuf_dmamap, sc->verbuf_mem,
+ verbuf_size, mrsas_addr_cb, &sc->verbuf_phys_addr,
+ BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load verbuf DMA map\n");
+ return (ENOMEM);
+ }
+ /*
+ * Allocate IO Request Frames
+ */
+ io_req_size = sc->io_frames_alloc_sz;
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 16, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ io_req_size,
+ 1,
+ io_req_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->io_request_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot create IO request tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->io_request_tag, (void **)&sc->io_request_mem,
+ BUS_DMA_NOWAIT, &sc->io_request_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot alloc IO request memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->io_request_mem, io_req_size);
+ if (bus_dmamap_load(sc->io_request_tag, sc->io_request_dmamap,
+ sc->io_request_mem, io_req_size, mrsas_addr_cb,
+ &sc->io_request_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
+ return (ENOMEM);
+ }
+ /*
+ * Allocate Chain Frames
+ */
+ chain_frame_size = sc->chain_frames_alloc_sz;
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 4, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ chain_frame_size,
+ 1,
+ chain_frame_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->chain_frame_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot create chain frame tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->chain_frame_tag, (void **)&sc->chain_frame_mem,
+ BUS_DMA_NOWAIT, &sc->chain_frame_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot alloc chain frame memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->chain_frame_mem, chain_frame_size);
+ if (bus_dmamap_load(sc->chain_frame_tag, sc->chain_frame_dmamap,
+ sc->chain_frame_mem, chain_frame_size, mrsas_addr_cb,
+ &sc->chain_frame_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load chain frame memory\n");
+ return (ENOMEM);
+ }
+ count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+ /*
+ * Allocate Reply Descriptor Array
+ */
+ reply_desc_size = sc->reply_alloc_sz * count;
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 16, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ reply_desc_size,
+ 1,
+ reply_desc_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->reply_desc_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot create reply descriptor tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->reply_desc_tag, (void **)&sc->reply_desc_mem,
+ BUS_DMA_NOWAIT, &sc->reply_desc_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot alloc reply descriptor memory\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamap_load(sc->reply_desc_tag, sc->reply_desc_dmamap,
+ sc->reply_desc_mem, reply_desc_size, mrsas_addr_cb,
+ &sc->reply_desc_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load reply descriptor memory\n");
+ return (ENOMEM);
+ }
+ /*
+ * Allocate Sense Buffer Array. Keep in lower 4GB
+ */
+ sense_size = sc->max_fw_cmds * MRSAS_SENSE_LEN;
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 64, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ sense_size,
+ 1,
+ sense_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->sense_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate sense buf tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->sense_tag, (void **)&sc->sense_mem,
+ BUS_DMA_NOWAIT, &sc->sense_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate sense buf memory\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamap_load(sc->sense_tag, sc->sense_dmamap,
+ sc->sense_mem, sense_size, mrsas_addr_cb, &sc->sense_phys_addr,
+ BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load sense buf memory\n");
+ return (ENOMEM);
+ }
+ /*
+ * Allocate for Event detail structure
+ */
+ evt_detail_size = sizeof(struct mrsas_evt_detail);
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ evt_detail_size,
+ 1,
+ evt_detail_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->evt_detail_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot create Event detail tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->evt_detail_tag, (void **)&sc->evt_detail_mem,
+ BUS_DMA_NOWAIT, &sc->evt_detail_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot alloc Event detail buffer memory\n");
+ return (ENOMEM);
+ }
+ bzero(sc->evt_detail_mem, evt_detail_size);
+ if (bus_dmamap_load(sc->evt_detail_tag, sc->evt_detail_dmamap,
+ sc->evt_detail_mem, evt_detail_size, mrsas_addr_cb,
+ &sc->evt_detail_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load Event detail buffer memory\n");
+ return (ENOMEM);
+ }
+ /*
+ * Create a dma tag for data buffers; size will be the maximum
+ * possible I/O size (280kB).
+ */
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1,
+ 0,
+ BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ MRSAS_MAX_IO_SIZE,
+ MRSAS_MAX_SGL,
+ MRSAS_MAX_IO_SIZE,
+ BUS_DMA_ALLOCNOW,
+ busdma_lock_mutex,
+ &sc->io_lock,
+ &sc->data_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot create data dma tag\n");
+ return (ENOMEM);
+ }
+ return (0);
+}
+
+/*
+ * mrsas_addr_cb: Callback function of bus_dmamap_load()
+ * input: callback argument, machine dependent type
+ * that describes DMA segments, number of segments, error code
+ *
+ * This function is for the driver to receive mapping information resultant of
+ * the bus_dmamap_load(). The information is actually not being used, but the
+ * address is saved anyway.
*/
void
mrsas_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
- bus_addr_t *addr;
-
- addr = arg;
- *addr = segs[0].ds_addr;
+ bus_addr_t *addr;
+
+ addr = arg;
+ *addr = segs[0].ds_addr;
}
/*
- * mrsas_setup_raidmap: Set up RAID map.
- * input: Adapter instance soft state
+ * mrsas_setup_raidmap: Set up RAID map.
+ * input: Adapter instance soft state
*
* Allocate DMA memory for the RAID maps and perform setup.
*/
-static int mrsas_setup_raidmap(struct mrsas_softc *sc)
-{
- sc->map_sz = sizeof(MR_FW_RAID_MAP) +
- (sizeof(MR_LD_SPAN_MAP) * (MAX_LOGICAL_DRIVES - 1));
-
- for (int i=0; i < 2; i++)
- {
- if (bus_dma_tag_create(sc->mrsas_parent_tag, // parent
- 4, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- sc->map_sz, // maxsize
- 1, // nsegments
- sc->map_sz, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->raidmap_tag[i])) {
- device_printf(sc->mrsas_dev, "Cannot allocate raid map tag.\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->raidmap_tag[i], (void **)&sc->raidmap_mem[i],
- BUS_DMA_NOWAIT, &sc->raidmap_dmamap[i])) {
- device_printf(sc->mrsas_dev, "Cannot allocate raidmap memory.\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(sc->raidmap_tag[i], sc->raidmap_dmamap[i],
- sc->raidmap_mem[i], sc->map_sz, mrsas_addr_cb, &sc->raidmap_phys_addr[i],
- BUS_DMA_NOWAIT)){
- device_printf(sc->mrsas_dev, "Cannot load raidmap memory.\n");
- return (ENOMEM);
- }
- if (!sc->raidmap_mem[i]) {
- device_printf(sc->mrsas_dev, "Cannot allocate memory for raid map.\n");
- return (ENOMEM);
- }
- }
-
- if (!mrsas_get_map_info(sc))
- mrsas_sync_map_info(sc);
-
- return (0);
-}
-
-/**
- * mrsas_init_fw: Initialize Firmware
- * input: Adapter soft state
- *
- * Calls transition_to_ready() to make sure Firmware is in operational
- * state and calls mrsas_init_adapter() to send IOC_INIT command to
- * Firmware. It issues internal commands to get the controller info
- * after the IOC_INIT command response is received by Firmware.
- * Note: code relating to get_pdlist, get_ld_list and max_sectors
- * are currently not being used, it is left here as placeholder.
- */
-static int mrsas_init_fw(struct mrsas_softc *sc)
-{
- u_int32_t max_sectors_1;
- u_int32_t max_sectors_2;
- u_int32_t tmp_sectors;
- struct mrsas_ctrl_info *ctrl_info;
-
- int ret, ocr = 0;
-
-
- /* Make sure Firmware is ready */
- ret = mrsas_transition_to_ready(sc, ocr);
- if (ret != SUCCESS) {
- return(ret);
- }
-
- /* Get operational params, sge flags, send init cmd to ctlr */
- if (mrsas_init_adapter(sc) != SUCCESS){
- device_printf(sc->mrsas_dev, "Adapter initialize Fail.\n");
- return(1);
- }
-
- /* Allocate internal commands for pass-thru */
- if (mrsas_alloc_mfi_cmds(sc) != SUCCESS){
- device_printf(sc->mrsas_dev, "Allocate MFI cmd failed.\n");
- return(1);
- }
-
- if (mrsas_setup_raidmap(sc) != SUCCESS) {
- device_printf(sc->mrsas_dev, "Set up RAID map failed.\n");
- return(1);
- }
-
- /* For pass-thru, get PD/LD list and controller info */
- memset(sc->pd_list, 0, MRSAS_MAX_PD * sizeof(struct mrsas_pd_list));
- mrsas_get_pd_list(sc);
-
- memset(sc->ld_ids, 0xff, MRSAS_MAX_LD);
- mrsas_get_ld_list(sc);
-
- //memset(sc->log_to_span, 0, MRSAS_MAX_LD * sizeof(LD_SPAN_INFO));
-
- ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT);
-
- /*
- * Compute the max allowed sectors per IO: The controller info has two
- * limits on max sectors. Driver should use the minimum of these two.
- *
- * 1 << stripe_sz_ops.min = max sectors per strip
- *
- * Note that older firmwares ( < FW ver 30) didn't report information
- * to calculate max_sectors_1. So the number ended up as zero always.
- */
- tmp_sectors = 0;
- if (ctrl_info && !mrsas_get_ctrl_info(sc, ctrl_info)) {
- max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
- ctrl_info->max_strips_per_io;
- max_sectors_2 = ctrl_info->max_request_size;
- tmp_sectors = min(max_sectors_1 , max_sectors_2);
- sc->disableOnlineCtrlReset =
- ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
- sc->UnevenSpanSupport =
- ctrl_info->adapterOperations2.supportUnevenSpans;
- if(sc->UnevenSpanSupport) {
- device_printf(sc->mrsas_dev, "FW supports: UnevenSpanSupport=%x\n",
- sc->UnevenSpanSupport);
- if (MR_ValidateMapInfo(sc))
- sc->fast_path_io = 1;
- else
- sc->fast_path_io = 0;
-
- }
- }
- sc->max_sectors_per_req = sc->max_num_sge * MRSAS_PAGE_SIZE / 512;
-
- if (tmp_sectors && (sc->max_sectors_per_req > tmp_sectors))
- sc->max_sectors_per_req = tmp_sectors;
-
- if (ctrl_info)
- free(ctrl_info, M_MRSAS);
-
- return(0);
-}
-
-/**
- * mrsas_init_adapter: Initializes the adapter/controller
- * input: Adapter soft state
- *
- * Prepares for the issuing of the IOC Init cmd to FW for initializing the
- * ROC/controller. The FW register is read to determined the number of
+static int
+mrsas_setup_raidmap(struct mrsas_softc *sc)
+{
+ int i;
+
+ sc->drv_supported_vd_count =
+ MRSAS_MAX_LD_CHANNELS * MRSAS_MAX_DEV_PER_CHANNEL;
+ sc->drv_supported_pd_count =
+ MRSAS_MAX_PD_CHANNELS * MRSAS_MAX_DEV_PER_CHANNEL;
+
+ if (sc->max256vdSupport) {
+ sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
+ sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+ } else {
+ sc->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
+ sc->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+ }
+
+#if VD_EXT_DEBUG
+ device_printf(sc->mrsas_dev, "FW supports: max256vdSupport = %s\n",
+ sc->max256vdSupport ? "YES" : "NO");
+ device_printf(sc->mrsas_dev, "FW supports %dVDs %dPDs\n"
+ "DRIVER supports %dVDs %dPDs \n",
+ sc->fw_supported_vd_count, sc->fw_supported_pd_count,
+ sc->drv_supported_vd_count, sc->drv_supported_pd_count);
+#endif
+
+ sc->old_map_sz = sizeof(MR_FW_RAID_MAP) +
+ (sizeof(MR_LD_SPAN_MAP) * (sc->fw_supported_vd_count - 1));
+ sc->new_map_sz = sizeof(MR_FW_RAID_MAP_EXT);
+ sc->drv_map_sz = sizeof(MR_DRV_RAID_MAP) +
+ (sizeof(MR_LD_SPAN_MAP) * (sc->drv_supported_vd_count - 1));
+
+ for (i = 0; i < 2; i++) {
+ sc->ld_drv_map[i] =
+ (void *)malloc(sc->drv_map_sz, M_MRSAS, M_NOWAIT);
+ /* Do Error handling */
+ if (!sc->ld_drv_map[i]) {
+ device_printf(sc->mrsas_dev, "Could not allocate memory for local map");
+
+ if (i == 1)
+ free(sc->ld_drv_map[0], M_MRSAS);
+ /* ABORT driver initialization */
+ goto ABORT;
+ }
+ }
+
+ sc->max_map_sz = max(sc->old_map_sz, sc->new_map_sz);
+
+ if (sc->max256vdSupport)
+ sc->current_map_sz = sc->new_map_sz;
+ else
+ sc->current_map_sz = sc->old_map_sz;
+
+
+ for (int i = 0; i < 2; i++) {
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 4, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ sc->max_map_sz,
+ 1,
+ sc->max_map_sz,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->raidmap_tag[i])) {
+ device_printf(sc->mrsas_dev,
+ "Cannot allocate raid map tag.\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->raidmap_tag[i],
+ (void **)&sc->raidmap_mem[i],
+ BUS_DMA_NOWAIT, &sc->raidmap_dmamap[i])) {
+ device_printf(sc->mrsas_dev,
+ "Cannot allocate raidmap memory.\n");
+ return (ENOMEM);
+ }
+ bzero(sc->raidmap_mem[i], sc->max_map_sz);
+
+ if (bus_dmamap_load(sc->raidmap_tag[i], sc->raidmap_dmamap[i],
+ sc->raidmap_mem[i], sc->max_map_sz,
+ mrsas_addr_cb, &sc->raidmap_phys_addr[i],
+ BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load raidmap memory.\n");
+ return (ENOMEM);
+ }
+ if (!sc->raidmap_mem[i]) {
+ device_printf(sc->mrsas_dev,
+ "Cannot allocate memory for raid map.\n");
+ return (ENOMEM);
+ }
+ }
+
+ if (!mrsas_get_map_info(sc))
+ mrsas_sync_map_info(sc);
+
+ return (0);
+
+ABORT:
+ return (1);
+}
+
+/*
+ * mrsas_init_fw: Initialize Firmware
+ * input: Adapter soft state
+ *
+ * Calls transition_to_ready() to make sure Firmware is in operational state and
+ * calls mrsas_init_adapter() to send IOC_INIT command to Firmware. It
+ * issues internal commands to get the controller info after the IOC_INIT
+ * command response is received by Firmware. Note: code relating to
+ * get_pdlist, get_ld_list and max_sectors are currently not being used, it
+ * is left here as placeholder.
+ */
+static int
+mrsas_init_fw(struct mrsas_softc *sc)
+{
+
+ int ret, loop, ocr = 0;
+ u_int32_t max_sectors_1;
+ u_int32_t max_sectors_2;
+ u_int32_t tmp_sectors;
+ struct mrsas_ctrl_info *ctrl_info;
+ u_int32_t scratch_pad_2;
+ int msix_enable = 0;
+ int fw_msix_count = 0;
+
+ /* Make sure Firmware is ready */
+ ret = mrsas_transition_to_ready(sc, ocr);
+ if (ret != SUCCESS) {
+ return (ret);
+ }
+ /* MSI-x index 0- reply post host index register */
+ sc->msix_reg_offset[0] = MPI2_REPLY_POST_HOST_INDEX_OFFSET;
+ /* Check if MSI-X is supported while in ready state */
+ msix_enable = (mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)) & 0x4000000) >> 0x1a;
+
+ if (msix_enable) {
+ scratch_pad_2 = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad_2));
+
+ /* Check max MSI-X vectors */
+ if (sc->device_id == MRSAS_TBOLT) {
+ sc->msix_vectors = (scratch_pad_2
+ & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
+ fw_msix_count = sc->msix_vectors;
+ } else {
+ /* Invader/Fury supports 96 MSI-X vectors */
+ sc->msix_vectors = ((scratch_pad_2
+ & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
+ >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
+ fw_msix_count = sc->msix_vectors;
+
+ for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY;
+ loop++) {
+ sc->msix_reg_offset[loop] =
+ MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET +
+ (loop * 0x10);
+ }
+ }
+
+ /* Don't bother allocating more MSI-X vectors than cpus */
+ sc->msix_vectors = min(sc->msix_vectors,
+ mp_ncpus);
+
+ /* Allocate MSI-x vectors */
+ if (mrsas_allocate_msix(sc) == SUCCESS)
+ sc->msix_enable = 1;
+ else
+ sc->msix_enable = 0;
+
+ device_printf(sc->mrsas_dev, "FW supports <%d> MSIX vector,"
+ "Online CPU %d Current MSIX <%d>\n",
+ fw_msix_count, mp_ncpus, sc->msix_vectors);
+ }
+ if (mrsas_init_adapter(sc) != SUCCESS) {
+ device_printf(sc->mrsas_dev, "Adapter initialize Fail.\n");
+ return (1);
+ }
+ /* Allocate internal commands for pass-thru */
+ if (mrsas_alloc_mfi_cmds(sc) != SUCCESS) {
+ device_printf(sc->mrsas_dev, "Allocate MFI cmd failed.\n");
+ return (1);
+ }
+ /*
+ * Get the controller info from FW, so that the MAX VD support
+ * availability can be decided.
+ */
+ ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT);
+ if (!ctrl_info)
+ device_printf(sc->mrsas_dev, "Malloc for ctrl_info failed.\n");
+
+ if (mrsas_get_ctrl_info(sc, ctrl_info)) {
+ device_printf(sc->mrsas_dev, "Unable to get FW ctrl_info.\n");
+ }
+ sc->max256vdSupport =
+ (u_int8_t)ctrl_info->adapterOperations3.supportMaxExtLDs;
+
+ if (ctrl_info->max_lds > 64) {
+ sc->max256vdSupport = 1;
+ }
+ if (mrsas_setup_raidmap(sc) != SUCCESS) {
+ device_printf(sc->mrsas_dev, "Set up RAID map failed.\n");
+ return (1);
+ }
+ /* For pass-thru, get PD/LD list and controller info */
+ memset(sc->pd_list, 0,
+ MRSAS_MAX_PD * sizeof(struct mrsas_pd_list));
+ mrsas_get_pd_list(sc);
+
+ memset(sc->ld_ids, 0xff, MRSAS_MAX_LD_IDS);
+ mrsas_get_ld_list(sc);
+
+ /*
+ * Compute the max allowed sectors per IO: The controller info has
+ * two limits on max sectors. Driver should use the minimum of these
+ * two.
+ *
+ * 1 << stripe_sz_ops.min = max sectors per strip
+ *
+ * Note that older firmwares ( < FW ver 30) didn't report information to
+ * calculate max_sectors_1. So the number ended up as zero always.
+ */
+ tmp_sectors = 0;
+ max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
+ ctrl_info->max_strips_per_io;
+ max_sectors_2 = ctrl_info->max_request_size;
+ tmp_sectors = min(max_sectors_1, max_sectors_2);
+ sc->max_sectors_per_req = sc->max_num_sge * MRSAS_PAGE_SIZE / 512;
+
+ if (tmp_sectors && (sc->max_sectors_per_req > tmp_sectors))
+ sc->max_sectors_per_req = tmp_sectors;
+
+ sc->disableOnlineCtrlReset =
+ ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
+ sc->UnevenSpanSupport =
+ ctrl_info->adapterOperations2.supportUnevenSpans;
+ if (sc->UnevenSpanSupport) {
+ device_printf(sc->mrsas_dev, "FW supports: UnevenSpanSupport=%x\n\n",
+ sc->UnevenSpanSupport);
+
+ if (MR_ValidateMapInfo(sc))
+ sc->fast_path_io = 1;
+ else
+ sc->fast_path_io = 0;
+ }
+ if (ctrl_info)
+ free(ctrl_info, M_MRSAS);
+
+ return (0);
+}
+
+/*
+ * mrsas_init_adapter: Initializes the adapter/controller
+ * input: Adapter soft state
+ *
+ * Prepares for the issuing of the IOC Init cmd to FW for initializing the
+ * ROC/controller. The FW register is read to determined the number of
* commands that is supported. All memory allocations for IO is based on
- * max_cmd. Appropriate calculations are performed in this function.
+ * max_cmd. Appropriate calculations are performed in this function.
*/
-int mrsas_init_adapter(struct mrsas_softc *sc)
+int
+mrsas_init_adapter(struct mrsas_softc *sc)
{
- uint32_t status;
- u_int32_t max_cmd;
- int ret;
+ uint32_t status;
+ u_int32_t max_cmd;
+ int ret;
+ int i = 0;
+
+ /* Read FW status register */
+ status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
- /* Read FW status register */
- status = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
+ /* Get operational params from status register */
+ sc->max_fw_cmds = status & MRSAS_FWSTATE_MAXCMD_MASK;
- /* Get operational params from status register */
- sc->max_fw_cmds = status & MRSAS_FWSTATE_MAXCMD_MASK;
+ /* Decrement the max supported by 1, to correlate with FW */
+ sc->max_fw_cmds = sc->max_fw_cmds - 1;
+ max_cmd = sc->max_fw_cmds;
- /* Decrement the max supported by 1, to correlate with FW */
- sc->max_fw_cmds = sc->max_fw_cmds-1;
- max_cmd = sc->max_fw_cmds;
+ /* Determine allocation size of command frames */
+ sc->reply_q_depth = ((max_cmd + 1 + 15) / 16 * 16);
+ sc->request_alloc_sz = sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * max_cmd;
+ sc->reply_alloc_sz = sizeof(MPI2_REPLY_DESCRIPTORS_UNION) * (sc->reply_q_depth);
+ sc->io_frames_alloc_sz = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * (max_cmd + 1));
+ sc->chain_frames_alloc_sz = 1024 * max_cmd;
+ sc->max_sge_in_main_msg = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
+ offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL)) / 16;
- /* Determine allocation size of command frames */
- sc->reply_q_depth = ((max_cmd *2 +1 +15)/16*16);
- sc->request_alloc_sz = sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * max_cmd;
- sc->reply_alloc_sz = sizeof(MPI2_REPLY_DESCRIPTORS_UNION) * (sc->reply_q_depth);
- sc->io_frames_alloc_sz = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * (max_cmd + 1));
- sc->chain_frames_alloc_sz = 1024 * max_cmd;
- sc->max_sge_in_main_msg = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
- offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL))/16;
+ sc->max_sge_in_chain = MRSAS_MAX_SZ_CHAIN_FRAME / sizeof(MPI2_SGE_IO_UNION);
+ sc->max_num_sge = sc->max_sge_in_main_msg + sc->max_sge_in_chain - 2;
- sc->max_sge_in_chain = MRSAS_MAX_SZ_CHAIN_FRAME / sizeof(MPI2_SGE_IO_UNION);
- sc->max_num_sge = sc->max_sge_in_main_msg + sc->max_sge_in_chain - 2;
+ /* Used for pass thru MFI frame (DCMD) */
+ sc->chain_offset_mfi_pthru = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL) / 16;
- /* Used for pass thru MFI frame (DCMD) */
- sc->chain_offset_mfi_pthru = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL)/16;
+ sc->chain_offset_io_request = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
+ sizeof(MPI2_SGE_IO_UNION)) / 16;
- sc->chain_offset_io_request = (MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
- sizeof(MPI2_SGE_IO_UNION))/16;
+ int count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
- sc->last_reply_idx = 0;
+ for (i = 0; i < count; i++)
+ sc->last_reply_idx[i] = 0;
- ret = mrsas_alloc_mem(sc);
- if (ret != SUCCESS)
- return(ret);
+ ret = mrsas_alloc_mem(sc);
+ if (ret != SUCCESS)
+ return (ret);
- ret = mrsas_alloc_mpt_cmds(sc);
- if (ret != SUCCESS)
- return(ret);
+ ret = mrsas_alloc_mpt_cmds(sc);
+ if (ret != SUCCESS)
+ return (ret);
- ret = mrsas_ioc_init(sc);
- if (ret != SUCCESS)
- return(ret);
-
-
- return(0);
+ ret = mrsas_ioc_init(sc);
+ if (ret != SUCCESS)
+ return (ret);
+
+ return (0);
}
-/**
- * mrsas_alloc_ioc_cmd: Allocates memory for IOC Init command
- * input: Adapter soft state
+/*
+ * mrsas_alloc_ioc_cmd: Allocates memory for IOC Init command
+ * input: Adapter soft state
*
* Allocates for the IOC Init cmd to FW to initialize the ROC/controller.
*/
-int mrsas_alloc_ioc_cmd(struct mrsas_softc *sc)
-{
- int ioc_init_size;
-
- /* Allocate IOC INIT command */
- ioc_init_size = 1024 + sizeof(MPI2_IOC_INIT_REQUEST);
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- ioc_init_size, // maxsize
- 1, // msegments
- ioc_init_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->ioc_init_tag)) {
- device_printf(sc->mrsas_dev, "Cannot allocate ioc init tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->ioc_init_tag, (void **)&sc->ioc_init_mem,
- BUS_DMA_NOWAIT, &sc->ioc_init_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot allocate ioc init cmd mem\n");
- return (ENOMEM);
- }
- bzero(sc->ioc_init_mem, ioc_init_size);
- if (bus_dmamap_load(sc->ioc_init_tag, sc->ioc_init_dmamap,
- sc->ioc_init_mem, ioc_init_size, mrsas_addr_cb,
- &sc->ioc_init_phys_mem, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load ioc init cmd mem\n");
- return (ENOMEM);
- }
-
- return (0);
-}
-
-/**
- * mrsas_free_ioc_cmd: Allocates memory for IOC Init command
- * input: Adapter soft state
+int
+mrsas_alloc_ioc_cmd(struct mrsas_softc *sc)
+{
+ int ioc_init_size;
+
+ /* Allocate IOC INIT command */
+ ioc_init_size = 1024 + sizeof(MPI2_IOC_INIT_REQUEST);
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ ioc_init_size,
+ 1,
+ ioc_init_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->ioc_init_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ioc init tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->ioc_init_tag, (void **)&sc->ioc_init_mem,
+ BUS_DMA_NOWAIT, &sc->ioc_init_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ioc init cmd mem\n");
+ return (ENOMEM);
+ }
+ bzero(sc->ioc_init_mem, ioc_init_size);
+ if (bus_dmamap_load(sc->ioc_init_tag, sc->ioc_init_dmamap,
+ sc->ioc_init_mem, ioc_init_size, mrsas_addr_cb,
+ &sc->ioc_init_phys_mem, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load ioc init cmd mem\n");
+ return (ENOMEM);
+ }
+ return (0);
+}
+
+/*
+ * mrsas_free_ioc_cmd: Allocates memory for IOC Init command
+ * input: Adapter soft state
*
* Deallocates memory of the IOC Init cmd.
*/
-void mrsas_free_ioc_cmd(struct mrsas_softc *sc)
+void
+mrsas_free_ioc_cmd(struct mrsas_softc *sc)
{
- if (sc->ioc_init_phys_mem)
- bus_dmamap_unload(sc->ioc_init_tag, sc->ioc_init_dmamap);
- if (sc->ioc_init_mem != NULL)
- bus_dmamem_free(sc->ioc_init_tag, sc->ioc_init_mem, sc->ioc_init_dmamap);
- if (sc->ioc_init_tag != NULL)
- bus_dma_tag_destroy(sc->ioc_init_tag);
+ if (sc->ioc_init_phys_mem)
+ bus_dmamap_unload(sc->ioc_init_tag, sc->ioc_init_dmamap);
+ if (sc->ioc_init_mem != NULL)
+ bus_dmamem_free(sc->ioc_init_tag, sc->ioc_init_mem, sc->ioc_init_dmamap);
+ if (sc->ioc_init_tag != NULL)
+ bus_dma_tag_destroy(sc->ioc_init_tag);
}
-/**
- * mrsas_ioc_init: Sends IOC Init command to FW
- * input: Adapter soft state
+/*
+ * mrsas_ioc_init: Sends IOC Init command to FW
+ * input: Adapter soft state
*
* Issues the IOC Init cmd to FW to initialize the ROC/controller.
*/
-int mrsas_ioc_init(struct mrsas_softc *sc)
-{
- struct mrsas_init_frame *init_frame;
- pMpi2IOCInitRequest_t IOCInitMsg;
- MRSAS_REQUEST_DESCRIPTOR_UNION req_desc;
- u_int8_t max_wait = MRSAS_IOC_INIT_WAIT_TIME;
- bus_addr_t phys_addr;
- int i, retcode = 0;
-
- /* Allocate memory for the IOC INIT command */
- if (mrsas_alloc_ioc_cmd(sc)) {
- device_printf(sc->mrsas_dev, "Cannot allocate IOC command.\n");
- return(1);
- }
-
- IOCInitMsg = (pMpi2IOCInitRequest_t)(((char *)sc->ioc_init_mem) +1024);
- IOCInitMsg->Function = MPI2_FUNCTION_IOC_INIT;
- IOCInitMsg->WhoInit = MPI2_WHOINIT_HOST_DRIVER;
- IOCInitMsg->MsgVersion = MPI2_VERSION;
- IOCInitMsg->HeaderVersion = MPI2_HEADER_VERSION;
- IOCInitMsg->SystemRequestFrameSize = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4;
- IOCInitMsg->ReplyDescriptorPostQueueDepth = sc->reply_q_depth;
- IOCInitMsg->ReplyDescriptorPostQueueAddress = sc->reply_desc_phys_addr;
- IOCInitMsg->SystemRequestFrameBaseAddress = sc->io_request_phys_addr;
-
- init_frame = (struct mrsas_init_frame *)sc->ioc_init_mem;
- init_frame->cmd = MFI_CMD_INIT;
- init_frame->cmd_status = 0xFF;
- init_frame->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
-
- if (sc->verbuf_mem) {
- snprintf((char *)sc->verbuf_mem, strlen(MRSAS_VERSION)+2,"%s\n",
- MRSAS_VERSION);
- init_frame->driver_ver_lo = (bus_addr_t)sc->verbuf_phys_addr;
- init_frame->driver_ver_hi = 0;
- }
-
- phys_addr = (bus_addr_t)sc->ioc_init_phys_mem + 1024;
- init_frame->queue_info_new_phys_addr_lo = phys_addr;
- init_frame->data_xfer_len = sizeof(Mpi2IOCInitRequest_t);
-
- req_desc.addr.Words = (bus_addr_t)sc->ioc_init_phys_mem;
- req_desc.MFAIo.RequestFlags =
- (MRSAS_REQ_DESCRIPT_FLAGS_MFA << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
-
- mrsas_disable_intr(sc);
- mrsas_dprint(sc, MRSAS_OCR, "Issuing IOC INIT command to FW.\n");
- //device_printf(sc->mrsas_dev, "Issuing IOC INIT command to FW.\n");del?
- mrsas_fire_cmd(sc, req_desc.addr.u.low, req_desc.addr.u.high);
-
- /*
- * Poll response timer to wait for Firmware response. While this
- * timer with the DELAY call could block CPU, the time interval for
- * this is only 1 millisecond.
- */
- if (init_frame->cmd_status == 0xFF) {
- for (i=0; i < (max_wait * 1000); i++){
- if (init_frame->cmd_status == 0xFF)
- DELAY(1000);
- else
- break;
- }
- }
-
- if (init_frame->cmd_status == 0)
- mrsas_dprint(sc, MRSAS_OCR,
- "IOC INIT response received from FW.\n");
- //device_printf(sc->mrsas_dev, "IOC INIT response received from FW.\n");del?
- else
- {
- if (init_frame->cmd_status == 0xFF)
- device_printf(sc->mrsas_dev, "IOC Init timed out after %d seconds.\n", max_wait);
- else
- device_printf(sc->mrsas_dev, "IOC Init failed, status = 0x%x\n", init_frame->cmd_status);
- retcode = 1;
- }
-
- mrsas_free_ioc_cmd(sc);
- return (retcode);
-}
-
-/**
- * mrsas_alloc_mpt_cmds: Allocates the command packets
- * input: Adapter instance soft state
+int
+mrsas_ioc_init(struct mrsas_softc *sc)
+{
+ struct mrsas_init_frame *init_frame;
+ pMpi2IOCInitRequest_t IOCInitMsg;
+ MRSAS_REQUEST_DESCRIPTOR_UNION req_desc;
+ u_int8_t max_wait = MRSAS_IOC_INIT_WAIT_TIME;
+ bus_addr_t phys_addr;
+ int i, retcode = 0;
+
+ /* Allocate memory for the IOC INIT command */
+ if (mrsas_alloc_ioc_cmd(sc)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate IOC command.\n");
+ return (1);
+ }
+ IOCInitMsg = (pMpi2IOCInitRequest_t)(((char *)sc->ioc_init_mem) + 1024);
+ IOCInitMsg->Function = MPI2_FUNCTION_IOC_INIT;
+ IOCInitMsg->WhoInit = MPI2_WHOINIT_HOST_DRIVER;
+ IOCInitMsg->MsgVersion = MPI2_VERSION;
+ IOCInitMsg->HeaderVersion = MPI2_HEADER_VERSION;
+ IOCInitMsg->SystemRequestFrameSize = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4;
+ IOCInitMsg->ReplyDescriptorPostQueueDepth = sc->reply_q_depth;
+ IOCInitMsg->ReplyDescriptorPostQueueAddress = sc->reply_desc_phys_addr;
+ IOCInitMsg->SystemRequestFrameBaseAddress = sc->io_request_phys_addr;
+ IOCInitMsg->HostMSIxVectors = (sc->msix_vectors > 0 ? sc->msix_vectors : 0);
+
+ init_frame = (struct mrsas_init_frame *)sc->ioc_init_mem;
+ init_frame->cmd = MFI_CMD_INIT;
+ init_frame->cmd_status = 0xFF;
+ init_frame->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+ /* driver support Extended MSIX */
+ if ((sc->device_id == MRSAS_INVADER) ||
+ (sc->device_id == MRSAS_FURY)) {
+ init_frame->driver_operations.
+ mfi_capabilities.support_additional_msix = 1;
+ }
+ if (sc->verbuf_mem) {
+ snprintf((char *)sc->verbuf_mem, strlen(MRSAS_VERSION) + 2, "%s\n",
+ MRSAS_VERSION);
+ init_frame->driver_ver_lo = (bus_addr_t)sc->verbuf_phys_addr;
+ init_frame->driver_ver_hi = 0;
+ }
+ init_frame->driver_operations.mfi_capabilities.support_max_255lds = 1;
+ phys_addr = (bus_addr_t)sc->ioc_init_phys_mem + 1024;
+ init_frame->queue_info_new_phys_addr_lo = phys_addr;
+ init_frame->data_xfer_len = sizeof(Mpi2IOCInitRequest_t);
+
+ req_desc.addr.Words = (bus_addr_t)sc->ioc_init_phys_mem;
+ req_desc.MFAIo.RequestFlags =
+ (MRSAS_REQ_DESCRIPT_FLAGS_MFA << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+
+ mrsas_disable_intr(sc);
+ mrsas_dprint(sc, MRSAS_OCR, "Issuing IOC INIT command to FW.\n");
+ mrsas_fire_cmd(sc, req_desc.addr.u.low, req_desc.addr.u.high);
+
+ /*
+ * Poll response timer to wait for Firmware response. While this
+ * timer with the DELAY call could block CPU, the time interval for
+ * this is only 1 millisecond.
+ */
+ if (init_frame->cmd_status == 0xFF) {
+ for (i = 0; i < (max_wait * 1000); i++) {
+ if (init_frame->cmd_status == 0xFF)
+ DELAY(1000);
+ else
+ break;
+ }
+ }
+ if (init_frame->cmd_status == 0)
+ mrsas_dprint(sc, MRSAS_OCR,
+ "IOC INIT response received from FW.\n");
+ else {
+ if (init_frame->cmd_status == 0xFF)
+ device_printf(sc->mrsas_dev, "IOC Init timed out after %d seconds.\n", max_wait);
+ else
+ device_printf(sc->mrsas_dev, "IOC Init failed, status = 0x%x\n", init_frame->cmd_status);
+ retcode = 1;
+ }
+
+ mrsas_free_ioc_cmd(sc);
+ return (retcode);
+}
+
+/*
+ * mrsas_alloc_mpt_cmds: Allocates the command packets
+ * input: Adapter instance soft state
*
* This function allocates the internal commands for IOs. Each command that is
- * issued to FW is wrapped in a local data structure called mrsas_mpt_cmd.
- * An array is allocated with mrsas_mpt_cmd context. The free commands are
+ * issued to FW is wrapped in a local data structure called mrsas_mpt_cmd. An
+ * array is allocated with mrsas_mpt_cmd context. The free commands are
* maintained in a linked list (cmd pool). SMID value range is from 1 to
* max_fw_cmds.
*/
-int mrsas_alloc_mpt_cmds(struct mrsas_softc *sc)
-{
- int i, j;
- u_int32_t max_cmd;
- struct mrsas_mpt_cmd *cmd;
- pMpi2ReplyDescriptorsUnion_t reply_desc;
- u_int32_t offset, chain_offset, sense_offset;
- bus_addr_t io_req_base_phys, chain_frame_base_phys, sense_base_phys;
- u_int8_t *io_req_base, *chain_frame_base, *sense_base;
-
- max_cmd = sc->max_fw_cmds;
-
- sc->req_desc = malloc(sc->request_alloc_sz, M_MRSAS, M_NOWAIT);
- if (!sc->req_desc) {
- device_printf(sc->mrsas_dev, "Out of memory, cannot alloc req desc\n");
- return(ENOMEM);
- }
- memset(sc->req_desc, 0, sc->request_alloc_sz);
-
- /*
- * sc->mpt_cmd_list is an array of struct mrsas_mpt_cmd pointers. Allocate the
- * dynamic array first and then allocate individual commands.
- */
- sc->mpt_cmd_list = malloc(sizeof(struct mrsas_mpt_cmd*)*max_cmd, M_MRSAS, M_NOWAIT);
- if (!sc->mpt_cmd_list) {
- device_printf(sc->mrsas_dev, "Cannot alloc memory for mpt_cmd_list.\n");
- return(ENOMEM);
- }
- memset(sc->mpt_cmd_list, 0, sizeof(struct mrsas_mpt_cmd *)*max_cmd);
- for (i = 0; i < max_cmd; i++) {
- sc->mpt_cmd_list[i] = malloc(sizeof(struct mrsas_mpt_cmd),
- M_MRSAS, M_NOWAIT);
- if (!sc->mpt_cmd_list[i]) {
- for (j = 0; j < i; j++)
- free(sc->mpt_cmd_list[j],M_MRSAS);
- free(sc->mpt_cmd_list, M_MRSAS);
- sc->mpt_cmd_list = NULL;
- return(ENOMEM);
- }
- }
-
- io_req_base = (u_int8_t*)sc->io_request_mem + MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
- io_req_base_phys = (bus_addr_t)sc->io_request_phys_addr + MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
- chain_frame_base = (u_int8_t*)sc->chain_frame_mem;
- chain_frame_base_phys = (bus_addr_t)sc->chain_frame_phys_addr;
- sense_base = (u_int8_t*)sc->sense_mem;
- sense_base_phys = (bus_addr_t)sc->sense_phys_addr;
- for (i = 0; i < max_cmd; i++) {
- cmd = sc->mpt_cmd_list[i];
- offset = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
- chain_offset = 1024 * i;
- sense_offset = MRSAS_SENSE_LEN * i;
- memset(cmd, 0, sizeof(struct mrsas_mpt_cmd));
- cmd->index = i + 1;
- cmd->ccb_ptr = NULL;
- callout_init(&cmd->cm_callout, 0);
- cmd->sync_cmd_idx = (u_int32_t)MRSAS_ULONG_MAX;
- cmd->sc = sc;
- cmd->io_request = (MRSAS_RAID_SCSI_IO_REQUEST *) (io_req_base + offset);
- memset(cmd->io_request, 0, sizeof(MRSAS_RAID_SCSI_IO_REQUEST));
- cmd->io_request_phys_addr = io_req_base_phys + offset;
- cmd->chain_frame = (MPI2_SGE_IO_UNION *) (chain_frame_base + chain_offset);
- cmd->chain_frame_phys_addr = chain_frame_base_phys + chain_offset;
- cmd->sense = sense_base + sense_offset;
- cmd->sense_phys_addr = sense_base_phys + sense_offset;
- if (bus_dmamap_create(sc->data_tag, 0, &cmd->data_dmamap)) {
- return(FAIL);
- }
- TAILQ_INSERT_TAIL(&(sc->mrsas_mpt_cmd_list_head), cmd, next);
- }
-
- /* Initialize reply descriptor array to 0xFFFFFFFF */
- reply_desc = sc->reply_desc_mem;
- for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) {
- reply_desc->Words = MRSAS_ULONG_MAX;
- }
- return(0);
-}
-
-/**
- * mrsas_fire_cmd: Sends command to FW
- * input: Adapter soft state
- * request descriptor address low
- * request descriptor address high
- *
- * This functions fires the command to Firmware by writing to the
- * inbound_low_queue_port and inbound_high_queue_port.
- */
-void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo,
- u_int32_t req_desc_hi)
-{
- mtx_lock(&sc->pci_lock);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, inbound_low_queue_port),
- req_desc_lo);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, inbound_high_queue_port),
- req_desc_hi);
- mtx_unlock(&sc->pci_lock);
-}
-
-/**
- * mrsas_transition_to_ready: Move FW to Ready state
- * input: Adapter instance soft state
- *
- * During the initialization, FW passes can potentially be in any one of
- * several possible states. If the FW in operational, waiting-for-handshake
- * states, driver must take steps to bring it to ready state. Otherwise, it
- * has to wait for the ready state.
- */
-int mrsas_transition_to_ready(struct mrsas_softc *sc, int ocr)
-{
- int i;
- u_int8_t max_wait;
- u_int32_t val, fw_state;
- u_int32_t cur_state;
- u_int32_t abs_state, curr_abs_state;
-
- val = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
- fw_state = val & MFI_STATE_MASK;
- max_wait = MRSAS_RESET_WAIT_TIME;
-
- if (fw_state != MFI_STATE_READY)
- device_printf(sc->mrsas_dev, "Waiting for FW to come to ready state\n");
-
- while (fw_state != MFI_STATE_READY) {
- abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
- switch (fw_state) {
- case MFI_STATE_FAULT:
- device_printf(sc->mrsas_dev, "FW is in FAULT state!!\n");
- if (ocr) {
- cur_state = MFI_STATE_FAULT;
- break;
- }
- else
- return -ENODEV;
- case MFI_STATE_WAIT_HANDSHAKE:
- /* Set the CLR bit in inbound doorbell */
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell),
- MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG);
- cur_state = MFI_STATE_WAIT_HANDSHAKE;
- break;
- case MFI_STATE_BOOT_MESSAGE_PENDING:
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell),
- MFI_INIT_HOTPLUG);
- cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
- break;
- case MFI_STATE_OPERATIONAL:
- /* Bring it to READY state; assuming max wait 10 secs */
- mrsas_disable_intr(sc);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), MFI_RESET_FLAGS);
- for (i=0; i < max_wait * 1000; i++) {
- if (mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell)) & 1)
- DELAY(1000);
- else
- break;
- }
- cur_state = MFI_STATE_OPERATIONAL;
- break;
- case MFI_STATE_UNDEFINED:
- /* This state should not last for more than 2 seconds */
- cur_state = MFI_STATE_UNDEFINED;
- break;
- case MFI_STATE_BB_INIT:
- cur_state = MFI_STATE_BB_INIT;
- break;
- case MFI_STATE_FW_INIT:
- cur_state = MFI_STATE_FW_INIT;
- break;
- case MFI_STATE_FW_INIT_2:
- cur_state = MFI_STATE_FW_INIT_2;
- break;
- case MFI_STATE_DEVICE_SCAN:
- cur_state = MFI_STATE_DEVICE_SCAN;
- break;
- case MFI_STATE_FLUSH_CACHE:
- cur_state = MFI_STATE_FLUSH_CACHE;
- break;
- default:
- device_printf(sc->mrsas_dev, "Unknown state 0x%x\n", fw_state);
- return -ENODEV;
+int
+mrsas_alloc_mpt_cmds(struct mrsas_softc *sc)
+{
+ int i, j;
+ u_int32_t max_cmd, count;
+ struct mrsas_mpt_cmd *cmd;
+ pMpi2ReplyDescriptorsUnion_t reply_desc;
+ u_int32_t offset, chain_offset, sense_offset;
+ bus_addr_t io_req_base_phys, chain_frame_base_phys, sense_base_phys;
+ u_int8_t *io_req_base, *chain_frame_base, *sense_base;
+
+ max_cmd = sc->max_fw_cmds;
+
+ sc->req_desc = malloc(sc->request_alloc_sz, M_MRSAS, M_NOWAIT);
+ if (!sc->req_desc) {
+ device_printf(sc->mrsas_dev, "Out of memory, cannot alloc req desc\n");
+ return (ENOMEM);
}
+ memset(sc->req_desc, 0, sc->request_alloc_sz);
/*
- * The cur_state should not last for more than max_wait secs
+ * sc->mpt_cmd_list is an array of struct mrsas_mpt_cmd pointers.
+ * Allocate the dynamic array first and then allocate individual
+ * commands.
*/
- for (i = 0; i < (max_wait * 1000); i++) {
- fw_state = (mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- outbound_scratch_pad))& MFI_STATE_MASK);
- curr_abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- outbound_scratch_pad));
- if (abs_state == curr_abs_state)
- DELAY(1000);
- else
- break;
+ sc->mpt_cmd_list = malloc(sizeof(struct mrsas_mpt_cmd *) * max_cmd, M_MRSAS, M_NOWAIT);
+ if (!sc->mpt_cmd_list) {
+ device_printf(sc->mrsas_dev, "Cannot alloc memory for mpt_cmd_list.\n");
+ return (ENOMEM);
+ }
+ memset(sc->mpt_cmd_list, 0, sizeof(struct mrsas_mpt_cmd *) * max_cmd);
+ for (i = 0; i < max_cmd; i++) {
+ sc->mpt_cmd_list[i] = malloc(sizeof(struct mrsas_mpt_cmd),
+ M_MRSAS, M_NOWAIT);
+ if (!sc->mpt_cmd_list[i]) {
+ for (j = 0; j < i; j++)
+ free(sc->mpt_cmd_list[j], M_MRSAS);
+ free(sc->mpt_cmd_list, M_MRSAS);
+ sc->mpt_cmd_list = NULL;
+ return (ENOMEM);
+ }
}
- /*
- * Return error if fw_state hasn't changed after max_wait
- */
- if (curr_abs_state == abs_state) {
- device_printf(sc->mrsas_dev, "FW state [%d] hasn't changed "
- "in %d secs\n", fw_state, max_wait);
- return -ENODEV;
+ io_req_base = (u_int8_t *)sc->io_request_mem + MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
+ io_req_base_phys = (bus_addr_t)sc->io_request_phys_addr + MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE;
+ chain_frame_base = (u_int8_t *)sc->chain_frame_mem;
+ chain_frame_base_phys = (bus_addr_t)sc->chain_frame_phys_addr;
+ sense_base = (u_int8_t *)sc->sense_mem;
+ sense_base_phys = (bus_addr_t)sc->sense_phys_addr;
+ for (i = 0; i < max_cmd; i++) {
+ cmd = sc->mpt_cmd_list[i];
+ offset = MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i;
+ chain_offset = 1024 * i;
+ sense_offset = MRSAS_SENSE_LEN * i;
+ memset(cmd, 0, sizeof(struct mrsas_mpt_cmd));
+ cmd->index = i + 1;
+ cmd->ccb_ptr = NULL;
+ callout_init(&cmd->cm_callout, 0);
+ cmd->sync_cmd_idx = (u_int32_t)MRSAS_ULONG_MAX;
+ cmd->sc = sc;
+ cmd->io_request = (MRSAS_RAID_SCSI_IO_REQUEST *) (io_req_base + offset);
+ memset(cmd->io_request, 0, sizeof(MRSAS_RAID_SCSI_IO_REQUEST));
+ cmd->io_request_phys_addr = io_req_base_phys + offset;
+ cmd->chain_frame = (MPI2_SGE_IO_UNION *) (chain_frame_base + chain_offset);
+ cmd->chain_frame_phys_addr = chain_frame_base_phys + chain_offset;
+ cmd->sense = sense_base + sense_offset;
+ cmd->sense_phys_addr = sense_base_phys + sense_offset;
+ if (bus_dmamap_create(sc->data_tag, 0, &cmd->data_dmamap)) {
+ return (FAIL);
+ }
+ TAILQ_INSERT_TAIL(&(sc->mrsas_mpt_cmd_list_head), cmd, next);
}
- }
- mrsas_dprint(sc, MRSAS_OCR, "FW now in Ready state\n");
- //device_printf(sc->mrsas_dev, "FW now in Ready state\n");del?
- return 0;
+
+ /* Initialize reply descriptor array to 0xFFFFFFFF */
+ reply_desc = sc->reply_desc_mem;
+ count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+ for (i = 0; i < sc->reply_q_depth * count; i++, reply_desc++) {
+ reply_desc->Words = MRSAS_ULONG_MAX;
+ }
+ return (0);
}
-/**
- * mrsas_get_mfi_cmd: Get a cmd from free command pool
- * input: Adapter soft state
+/*
+ * mrsas_fire_cmd: Sends command to FW
+ * input: Adapter softstate
+ * request descriptor address low
+ * request descriptor address high
+ *
+ * This functions fires the command to Firmware by writing to the
+ * inbound_low_queue_port and inbound_high_queue_port.
+ */
+void
+mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo,
+ u_int32_t req_desc_hi)
+{
+ mtx_lock(&sc->pci_lock);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, inbound_low_queue_port),
+ req_desc_lo);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, inbound_high_queue_port),
+ req_desc_hi);
+ mtx_unlock(&sc->pci_lock);
+}
+
+/*
+ * mrsas_transition_to_ready: Move FW to Ready state input:
+ * Adapter instance soft state
+ *
+ * During the initialization, FW passes can potentially be in any one of several
+ * possible states. If the FW in operational, waiting-for-handshake states,
+ * driver must take steps to bring it to ready state. Otherwise, it has to
+ * wait for the ready state.
+ */
+int
+mrsas_transition_to_ready(struct mrsas_softc *sc, int ocr)
+{
+ int i;
+ u_int8_t max_wait;
+ u_int32_t val, fw_state;
+ u_int32_t cur_state;
+ u_int32_t abs_state, curr_abs_state;
+
+ val = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
+ fw_state = val & MFI_STATE_MASK;
+ max_wait = MRSAS_RESET_WAIT_TIME;
+
+ if (fw_state != MFI_STATE_READY)
+ device_printf(sc->mrsas_dev, "Waiting for FW to come to ready state\n");
+
+ while (fw_state != MFI_STATE_READY) {
+ abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad));
+ switch (fw_state) {
+ case MFI_STATE_FAULT:
+ device_printf(sc->mrsas_dev, "FW is in FAULT state!!\n");
+ if (ocr) {
+ cur_state = MFI_STATE_FAULT;
+ break;
+ } else
+ return -ENODEV;
+ case MFI_STATE_WAIT_HANDSHAKE:
+ /* Set the CLR bit in inbound doorbell */
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell),
+ MFI_INIT_CLEAR_HANDSHAKE | MFI_INIT_HOTPLUG);
+ cur_state = MFI_STATE_WAIT_HANDSHAKE;
+ break;
+ case MFI_STATE_BOOT_MESSAGE_PENDING:
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell),
+ MFI_INIT_HOTPLUG);
+ cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
+ break;
+ case MFI_STATE_OPERATIONAL:
+ /*
+ * Bring it to READY state; assuming max wait 10
+ * secs
+ */
+ mrsas_disable_intr(sc);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell), MFI_RESET_FLAGS);
+ for (i = 0; i < max_wait * 1000; i++) {
+ if (mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell)) & 1)
+ DELAY(1000);
+ else
+ break;
+ }
+ cur_state = MFI_STATE_OPERATIONAL;
+ break;
+ case MFI_STATE_UNDEFINED:
+ /*
+ * This state should not last for more than 2
+ * seconds
+ */
+ cur_state = MFI_STATE_UNDEFINED;
+ break;
+ case MFI_STATE_BB_INIT:
+ cur_state = MFI_STATE_BB_INIT;
+ break;
+ case MFI_STATE_FW_INIT:
+ cur_state = MFI_STATE_FW_INIT;
+ break;
+ case MFI_STATE_FW_INIT_2:
+ cur_state = MFI_STATE_FW_INIT_2;
+ break;
+ case MFI_STATE_DEVICE_SCAN:
+ cur_state = MFI_STATE_DEVICE_SCAN;
+ break;
+ case MFI_STATE_FLUSH_CACHE:
+ cur_state = MFI_STATE_FLUSH_CACHE;
+ break;
+ default:
+ device_printf(sc->mrsas_dev, "Unknown state 0x%x\n", fw_state);
+ return -ENODEV;
+ }
+
+ /*
+ * The cur_state should not last for more than max_wait secs
+ */
+ for (i = 0; i < (max_wait * 1000); i++) {
+ fw_state = (mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad)) & MFI_STATE_MASK);
+ curr_abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad));
+ if (abs_state == curr_abs_state)
+ DELAY(1000);
+ else
+ break;
+ }
+
+ /*
+ * Return error if fw_state hasn't changed after max_wait
+ */
+ if (curr_abs_state == abs_state) {
+ device_printf(sc->mrsas_dev, "FW state [%d] hasn't changed "
+ "in %d secs\n", fw_state, max_wait);
+ return -ENODEV;
+ }
+ }
+ mrsas_dprint(sc, MRSAS_OCR, "FW now in Ready state\n");
+ return 0;
+}
+
+/*
+ * mrsas_get_mfi_cmd: Get a cmd from free command pool
+ * input: Adapter soft state
*
* This function removes an MFI command from the command list.
*/
-struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc)
+struct mrsas_mfi_cmd *
+mrsas_get_mfi_cmd(struct mrsas_softc *sc)
{
- struct mrsas_mfi_cmd *cmd = NULL;
-
- mtx_lock(&sc->mfi_cmd_pool_lock);
- if (!TAILQ_EMPTY(&sc->mrsas_mfi_cmd_list_head)){
- cmd = TAILQ_FIRST(&sc->mrsas_mfi_cmd_list_head);
- TAILQ_REMOVE(&sc->mrsas_mfi_cmd_list_head, cmd, next);
- }
- mtx_unlock(&sc->mfi_cmd_pool_lock);
-
- return cmd;
+ struct mrsas_mfi_cmd *cmd = NULL;
+
+ mtx_lock(&sc->mfi_cmd_pool_lock);
+ if (!TAILQ_EMPTY(&sc->mrsas_mfi_cmd_list_head)) {
+ cmd = TAILQ_FIRST(&sc->mrsas_mfi_cmd_list_head);
+ TAILQ_REMOVE(&sc->mrsas_mfi_cmd_list_head, cmd, next);
+ }
+ mtx_unlock(&sc->mfi_cmd_pool_lock);
+
+ return cmd;
}
-/**
- * mrsas_ocr_thread Thread to handle OCR/Kill Adapter.
- * input: Adapter Context.
+/*
+ * mrsas_ocr_thread: Thread to handle OCR/Kill Adapter.
+ * input: Adapter Context.
*
- * This function will check FW status register and flag
- * do_timeout_reset flag. It will do OCR/Kill adapter if
- * FW is in fault state or IO timed out has trigger reset.
+ * This function will check FW status register and flag do_timeout_reset flag.
+ * It will do OCR/Kill adapter if FW is in fault state or IO timed out has
+ * trigger reset.
*/
static void
mrsas_ocr_thread(void *arg)
{
- struct mrsas_softc *sc;
- u_int32_t fw_status, fw_state;
-
- sc = (struct mrsas_softc *)arg;
-
- mrsas_dprint(sc, MRSAS_TRACE, "%s\n", __func__);
-
- sc->ocr_thread_active = 1;
- mtx_lock(&sc->sim_lock);
- for (;;) {
- /* Sleep for 1 second and check the queue status*/
- msleep(&sc->ocr_chan, &sc->sim_lock, PRIBIO,
- "mrsas_ocr", sc->mrsas_fw_fault_check_delay * hz);
- if (sc->remove_in_progress) {
- mrsas_dprint(sc, MRSAS_OCR,
- "Exit due to shutdown from %s\n", __func__);
- break;
- }
- fw_status = mrsas_read_reg(sc,
- offsetof(mrsas_reg_set, outbound_scratch_pad));
- fw_state = fw_status & MFI_STATE_MASK;
- if (fw_state == MFI_STATE_FAULT || sc->do_timedout_reset) {
- device_printf(sc->mrsas_dev, "OCR started due to %s!\n",
- sc->do_timedout_reset?"IO Timeout":
- "FW fault detected");
- mtx_lock_spin(&sc->ioctl_lock);
- sc->reset_in_progress = 1;
- sc->reset_count++;
- mtx_unlock_spin(&sc->ioctl_lock);
- mrsas_xpt_freeze(sc);
- mrsas_reset_ctrl(sc);
- mrsas_xpt_release(sc);
- sc->reset_in_progress = 0;
- sc->do_timedout_reset = 0;
- }
- }
- mtx_unlock(&sc->sim_lock);
- sc->ocr_thread_active = 0;
- mrsas_kproc_exit(0);
-}
-
-/**
- * mrsas_reset_reply_desc Reset Reply descriptor as part of OCR.
- * input: Adapter Context.
- *
- * This function will clear reply descriptor so that post OCR
- * driver and FW will lost old history.
- */
-void mrsas_reset_reply_desc(struct mrsas_softc *sc)
-{
- int i;
- pMpi2ReplyDescriptorsUnion_t reply_desc;
-
- sc->last_reply_idx = 0;
- reply_desc = sc->reply_desc_mem;
- for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) {
- reply_desc->Words = MRSAS_ULONG_MAX;
- }
-}
-
-/**
- * mrsas_reset_ctrl Core function to OCR/Kill adapter.
- * input: Adapter Context.
- *
- * This function will run from thread context so that it can sleep.
- * 1. Do not handle OCR if FW is in HW critical error.
- * 2. Wait for outstanding command to complete for 180 seconds.
- * 3. If #2 does not find any outstanding command Controller is in working
- * state, so skip OCR.
- * Otherwise, do OCR/kill Adapter based on flag disableOnlineCtrlReset.
- * 4. Start of the OCR, return all SCSI command back to CAM layer which has
- * ccb_ptr.
- * 5. Post OCR, Re-fire Managment command and move Controller to Operation
- * state.
- */
-int mrsas_reset_ctrl(struct mrsas_softc *sc)
-{
- int retval = SUCCESS, i, j, retry = 0;
- u_int32_t host_diag, abs_state, status_reg, reset_adapter;
- union ccb *ccb;
- struct mrsas_mfi_cmd *mfi_cmd;
- struct mrsas_mpt_cmd *mpt_cmd;
- MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
-
- if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) {
- device_printf(sc->mrsas_dev,
- "mrsas: Hardware critical error, returning FAIL.\n");
- return FAIL;
- }
-
- set_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
- sc->adprecovery = MRSAS_ADPRESET_SM_INFAULT;
- mrsas_disable_intr(sc);
- DELAY(1000 * 1000);
-
- /* First try waiting for commands to complete */
- if (mrsas_wait_for_outstanding(sc)) {
- mrsas_dprint(sc, MRSAS_OCR,
- "resetting adapter from %s.\n",
- __func__);
- /* Now return commands back to the CAM layer */
- for (i = 0 ; i < sc->max_fw_cmds; i++) {
- mpt_cmd = sc->mpt_cmd_list[i];
- if (mpt_cmd->ccb_ptr) {
- ccb = (union ccb *)(mpt_cmd->ccb_ptr);
- ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
- mrsas_cmd_done(sc, mpt_cmd);
- atomic_dec(&sc->fw_outstanding);
- }
- }
-
- status_reg = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- outbound_scratch_pad));
- abs_state = status_reg & MFI_STATE_MASK;
- reset_adapter = status_reg & MFI_RESET_ADAPTER;
- if (sc->disableOnlineCtrlReset ||
- (abs_state == MFI_STATE_FAULT && !reset_adapter)) {
- /* Reset not supported, kill adapter */
- mrsas_dprint(sc, MRSAS_OCR,"Reset not supported, killing adapter.\n");
- mrsas_kill_hba(sc);
- sc->adprecovery = MRSAS_HW_CRITICAL_ERROR;
- retval = FAIL;
- goto out;
- }
-
- /* Now try to reset the chip */
- for (i = 0; i < MRSAS_FUSION_MAX_RESET_TRIES; i++) {
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
- MPI2_WRSEQ_FLUSH_KEY_VALUE);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
- MPI2_WRSEQ_1ST_KEY_VALUE);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
- MPI2_WRSEQ_2ND_KEY_VALUE);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
- MPI2_WRSEQ_3RD_KEY_VALUE);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
- MPI2_WRSEQ_4TH_KEY_VALUE);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
- MPI2_WRSEQ_5TH_KEY_VALUE);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
- MPI2_WRSEQ_6TH_KEY_VALUE);
-
- /* Check that the diag write enable (DRWE) bit is on */
- host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- fusion_host_diag));
- retry = 0;
- while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
- DELAY(100 * 1000);
- host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- fusion_host_diag));
- if (retry++ == 100) {
- mrsas_dprint(sc, MRSAS_OCR,
- "Host diag unlock failed!\n");
- break;
- }
- }
- if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
- continue;
-
- /* Send chip reset command */
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_host_diag),
- host_diag | HOST_DIAG_RESET_ADAPTER);
- DELAY(3000 * 1000);
-
- /* Make sure reset adapter bit is cleared */
- host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- fusion_host_diag));
- retry = 0;
- while (host_diag & HOST_DIAG_RESET_ADAPTER) {
- DELAY(100 * 1000);
- host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- fusion_host_diag));
- if (retry++ == 1000) {
- mrsas_dprint(sc, MRSAS_OCR,
- "Diag reset adapter never cleared!\n");
- break;
- }
- }
- if (host_diag & HOST_DIAG_RESET_ADAPTER)
- continue;
-
- abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- outbound_scratch_pad)) & MFI_STATE_MASK;
- retry = 0;
-
- while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
- DELAY(100 * 1000);
- abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- outbound_scratch_pad)) & MFI_STATE_MASK;
- }
- if (abs_state <= MFI_STATE_FW_INIT) {
- mrsas_dprint(sc, MRSAS_OCR, "firmware state < MFI_STATE_FW_INIT,"
- " state = 0x%x\n", abs_state);
- continue;
- }
-
- /* Wait for FW to become ready */
- if (mrsas_transition_to_ready(sc, 1)) {
- mrsas_dprint(sc, MRSAS_OCR,
- "mrsas: Failed to transition controller to ready.\n");
- continue;
- }
-
- mrsas_reset_reply_desc(sc);
- if (mrsas_ioc_init(sc)) {
- mrsas_dprint(sc, MRSAS_OCR, "mrsas_ioc_init() failed!\n");
- continue;
- }
-
- clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
- mrsas_enable_intr(sc);
- sc->adprecovery = MRSAS_HBA_OPERATIONAL;
-
- /* Re-fire management commands */
- for (j = 0 ; j < sc->max_fw_cmds; j++) {
- mpt_cmd = sc->mpt_cmd_list[j];
- if (mpt_cmd->sync_cmd_idx != (u_int32_t)MRSAS_ULONG_MAX) {
- mfi_cmd = sc->mfi_cmd_list[mpt_cmd->sync_cmd_idx];
- if (mfi_cmd->frame->dcmd.opcode ==
- MR_DCMD_LD_MAP_GET_INFO) {
- mrsas_release_mfi_cmd(mfi_cmd);
- mrsas_release_mpt_cmd(mpt_cmd);
- } else {
- req_desc = mrsas_get_request_desc(sc,
- mfi_cmd->cmd_id.context.smid - 1);
- mrsas_dprint(sc, MRSAS_OCR,
- "Re-fire command DCMD opcode 0x%x index %d\n ",
- mfi_cmd->frame->dcmd.opcode, j);
- if (!req_desc)
- device_printf(sc->mrsas_dev,
- "Cannot build MPT cmd.\n");
- else
- mrsas_fire_cmd(sc, req_desc->addr.u.low,
- req_desc->addr.u.high);
- }
- }
- }
-
- /* Reset load balance info */
- memset(sc->load_balance_info, 0,
- sizeof(LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES);
-
- if (!mrsas_get_map_info(sc))
- mrsas_sync_map_info(sc);
-
- /* Adapter reset completed successfully */
- device_printf(sc->mrsas_dev, "Reset successful\n");
- retval = SUCCESS;
- goto out;
- }
- /* Reset failed, kill the adapter */
- device_printf(sc->mrsas_dev, "Reset failed, killing adapter.\n");
- mrsas_kill_hba(sc);
- retval = FAIL;
- } else {
- clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
- mrsas_enable_intr(sc);
- sc->adprecovery = MRSAS_HBA_OPERATIONAL;
- }
+ struct mrsas_softc *sc;
+ u_int32_t fw_status, fw_state;
+
+ sc = (struct mrsas_softc *)arg;
+
+ mrsas_dprint(sc, MRSAS_TRACE, "%s\n", __func__);
+
+ sc->ocr_thread_active = 1;
+ mtx_lock(&sc->sim_lock);
+ for (;;) {
+ /* Sleep for 1 second and check the queue status */
+ msleep(&sc->ocr_chan, &sc->sim_lock, PRIBIO,
+ "mrsas_ocr", sc->mrsas_fw_fault_check_delay * hz);
+ if (sc->remove_in_progress) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ "Exit due to shutdown from %s\n", __func__);
+ break;
+ }
+ fw_status = mrsas_read_reg(sc,
+ offsetof(mrsas_reg_set, outbound_scratch_pad));
+ fw_state = fw_status & MFI_STATE_MASK;
+ if (fw_state == MFI_STATE_FAULT || sc->do_timedout_reset) {
+ device_printf(sc->mrsas_dev, "OCR started due to %s!\n",
+ sc->do_timedout_reset ? "IO Timeout" :
+ "FW fault detected");
+ mtx_lock_spin(&sc->ioctl_lock);
+ sc->reset_in_progress = 1;
+ sc->reset_count++;
+ mtx_unlock_spin(&sc->ioctl_lock);
+ mrsas_xpt_freeze(sc);
+ mrsas_reset_ctrl(sc);
+ mrsas_xpt_release(sc);
+ sc->reset_in_progress = 0;
+ sc->do_timedout_reset = 0;
+ }
+ }
+ mtx_unlock(&sc->sim_lock);
+ sc->ocr_thread_active = 0;
+ mrsas_kproc_exit(0);
+}
+
+/*
+ * mrsas_reset_reply_desc: Reset Reply descriptor as part of OCR.
+ * input: Adapter Context.
+ *
+ * This function will clear reply descriptor so that post OCR driver and FW will
+ * lost old history.
+ */
+void
+mrsas_reset_reply_desc(struct mrsas_softc *sc)
+{
+ int i, count;
+ pMpi2ReplyDescriptorsUnion_t reply_desc;
+
+ count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+ for (i = 0; i < count; i++)
+ sc->last_reply_idx[i] = 0;
+
+ reply_desc = sc->reply_desc_mem;
+ for (i = 0; i < sc->reply_q_depth; i++, reply_desc++) {
+ reply_desc->Words = MRSAS_ULONG_MAX;
+ }
+}
+
+/*
+ * mrsas_reset_ctrl: Core function to OCR/Kill adapter.
+ * input: Adapter Context.
+ *
+ * This function will run from thread context so that it can sleep. 1. Do not
+ * handle OCR if FW is in HW critical error. 2. Wait for outstanding command
+ * to complete for 180 seconds. 3. If #2 does not find any outstanding
+ * command Controller is in working state, so skip OCR. Otherwise, do
+ * OCR/kill Adapter based on flag disableOnlineCtrlReset. 4. Start of the
+ * OCR, return all SCSI command back to CAM layer which has ccb_ptr. 5. Post
+ * OCR, Re-fire Managment command and move Controller to Operation state.
+ */
+int
+mrsas_reset_ctrl(struct mrsas_softc *sc)
+{
+ int retval = SUCCESS, i, j, retry = 0;
+ u_int32_t host_diag, abs_state, status_reg, reset_adapter;
+ union ccb *ccb;
+ struct mrsas_mfi_cmd *mfi_cmd;
+ struct mrsas_mpt_cmd *mpt_cmd;
+ MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+
+ if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR) {
+ device_printf(sc->mrsas_dev,
+ "mrsas: Hardware critical error, returning FAIL.\n");
+ return FAIL;
+ }
+ set_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
+ sc->adprecovery = MRSAS_ADPRESET_SM_INFAULT;
+ mrsas_disable_intr(sc);
+ DELAY(1000 * 1000);
+
+ /* First try waiting for commands to complete */
+ if (mrsas_wait_for_outstanding(sc)) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ "resetting adapter from %s.\n",
+ __func__);
+ /* Now return commands back to the CAM layer */
+ for (i = 0; i < sc->max_fw_cmds; i++) {
+ mpt_cmd = sc->mpt_cmd_list[i];
+ if (mpt_cmd->ccb_ptr) {
+ ccb = (union ccb *)(mpt_cmd->ccb_ptr);
+ ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
+ mrsas_cmd_done(sc, mpt_cmd);
+ atomic_dec(&sc->fw_outstanding);
+ }
+ }
+
+ status_reg = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad));
+ abs_state = status_reg & MFI_STATE_MASK;
+ reset_adapter = status_reg & MFI_RESET_ADAPTER;
+ if (sc->disableOnlineCtrlReset ||
+ (abs_state == MFI_STATE_FAULT && !reset_adapter)) {
+ /* Reset not supported, kill adapter */
+ mrsas_dprint(sc, MRSAS_OCR, "Reset not supported, killing adapter.\n");
+ mrsas_kill_hba(sc);
+ sc->adprecovery = MRSAS_HW_CRITICAL_ERROR;
+ retval = FAIL;
+ goto out;
+ }
+ /* Now try to reset the chip */
+ for (i = 0; i < MRSAS_FUSION_MAX_RESET_TRIES; i++) {
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
+ MPI2_WRSEQ_FLUSH_KEY_VALUE);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
+ MPI2_WRSEQ_1ST_KEY_VALUE);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
+ MPI2_WRSEQ_2ND_KEY_VALUE);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
+ MPI2_WRSEQ_3RD_KEY_VALUE);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
+ MPI2_WRSEQ_4TH_KEY_VALUE);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
+ MPI2_WRSEQ_5TH_KEY_VALUE);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_seq_offset),
+ MPI2_WRSEQ_6TH_KEY_VALUE);
+
+ /* Check that the diag write enable (DRWE) bit is on */
+ host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ fusion_host_diag));
+ retry = 0;
+ while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
+ DELAY(100 * 1000);
+ host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ fusion_host_diag));
+ if (retry++ == 100) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ "Host diag unlock failed!\n");
+ break;
+ }
+ }
+ if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
+ continue;
+
+ /* Send chip reset command */
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, fusion_host_diag),
+ host_diag | HOST_DIAG_RESET_ADAPTER);
+ DELAY(3000 * 1000);
+
+ /* Make sure reset adapter bit is cleared */
+ host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ fusion_host_diag));
+ retry = 0;
+ while (host_diag & HOST_DIAG_RESET_ADAPTER) {
+ DELAY(100 * 1000);
+ host_diag = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ fusion_host_diag));
+ if (retry++ == 1000) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ "Diag reset adapter never cleared!\n");
+ break;
+ }
+ }
+ if (host_diag & HOST_DIAG_RESET_ADAPTER)
+ continue;
+
+ abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad)) & MFI_STATE_MASK;
+ retry = 0;
+
+ while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
+ DELAY(100 * 1000);
+ abs_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad)) & MFI_STATE_MASK;
+ }
+ if (abs_state <= MFI_STATE_FW_INIT) {
+ mrsas_dprint(sc, MRSAS_OCR, "firmware state < MFI_STATE_FW_INIT,"
+ " state = 0x%x\n", abs_state);
+ continue;
+ }
+ /* Wait for FW to become ready */
+ if (mrsas_transition_to_ready(sc, 1)) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ "mrsas: Failed to transition controller to ready.\n");
+ continue;
+ }
+ mrsas_reset_reply_desc(sc);
+ if (mrsas_ioc_init(sc)) {
+ mrsas_dprint(sc, MRSAS_OCR, "mrsas_ioc_init() failed!\n");
+ continue;
+ }
+ clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
+ mrsas_enable_intr(sc);
+ sc->adprecovery = MRSAS_HBA_OPERATIONAL;
+
+ /* Re-fire management commands */
+ for (j = 0; j < sc->max_fw_cmds; j++) {
+ mpt_cmd = sc->mpt_cmd_list[j];
+ if (mpt_cmd->sync_cmd_idx != (u_int32_t)MRSAS_ULONG_MAX) {
+ mfi_cmd = sc->mfi_cmd_list[mpt_cmd->sync_cmd_idx];
+ if (mfi_cmd->frame->dcmd.opcode ==
+ MR_DCMD_LD_MAP_GET_INFO) {
+ mrsas_release_mfi_cmd(mfi_cmd);
+ mrsas_release_mpt_cmd(mpt_cmd);
+ } else {
+ req_desc = mrsas_get_request_desc(sc,
+ mfi_cmd->cmd_id.context.smid - 1);
+ mrsas_dprint(sc, MRSAS_OCR,
+ "Re-fire command DCMD opcode 0x%x index %d\n ",
+ mfi_cmd->frame->dcmd.opcode, j);
+ if (!req_desc)
+ device_printf(sc->mrsas_dev,
+ "Cannot build MPT cmd.\n");
+ else
+ mrsas_fire_cmd(sc, req_desc->addr.u.low,
+ req_desc->addr.u.high);
+ }
+ }
+ }
+
+ /* Reset load balance info */
+ memset(sc->load_balance_info, 0,
+ sizeof(LD_LOAD_BALANCE_INFO) * MAX_LOGICAL_DRIVES_EXT);
+
+ if (!mrsas_get_map_info(sc))
+ mrsas_sync_map_info(sc);
+
+ /* Adapter reset completed successfully */
+ device_printf(sc->mrsas_dev, "Reset successful\n");
+ retval = SUCCESS;
+ goto out;
+ }
+ /* Reset failed, kill the adapter */
+ device_printf(sc->mrsas_dev, "Reset failed, killing adapter.\n");
+ mrsas_kill_hba(sc);
+ retval = FAIL;
+ } else {
+ clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
+ mrsas_enable_intr(sc);
+ sc->adprecovery = MRSAS_HBA_OPERATIONAL;
+ }
out:
- clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
- mrsas_dprint(sc, MRSAS_OCR,
- "Reset Exit with %d.\n", retval);
- return retval;
+ clear_bit(MRSAS_FUSION_IN_RESET, &sc->reset_flags);
+ mrsas_dprint(sc, MRSAS_OCR,
+ "Reset Exit with %d.\n", retval);
+ return retval;
}
-/**
- * mrsas_kill_hba Kill HBA when OCR is not supported.
- * input: Adapter Context.
+/*
+ * mrsas_kill_hba: Kill HBA when OCR is not supported
+ * input: Adapter Context.
*
* This function will kill HBA when OCR is not supported.
*/
-void mrsas_kill_hba (struct mrsas_softc *sc)
-{
- mrsas_dprint(sc, MRSAS_OCR, "%s\n", __func__);
- mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell),
- MFI_STOP_ADP);
- /* Flush */
- mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell));
-}
-
-/**
- * mrsas_wait_for_outstanding Wait for outstanding commands
- * input: Adapter Context.
- *
- * This function will wait for 180 seconds for outstanding
- * commands to be completed.
- */
-int mrsas_wait_for_outstanding(struct mrsas_softc *sc)
-{
- int i, outstanding, retval = 0;
- u_int32_t fw_state;
-
- for (i = 0; i < MRSAS_RESET_WAIT_TIME; i++) {
- if (sc->remove_in_progress) {
- mrsas_dprint(sc, MRSAS_OCR,
- "Driver remove or shutdown called.\n");
- retval = 1;
- goto out;
- }
- /* Check if firmware is in fault state */
- fw_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
- outbound_scratch_pad)) & MFI_STATE_MASK;
- if (fw_state == MFI_STATE_FAULT) {
- mrsas_dprint(sc, MRSAS_OCR,
- "Found FW in FAULT state, will reset adapter.\n");
- retval = 1;
- goto out;
- }
- outstanding = atomic_read(&sc->fw_outstanding);
- if (!outstanding)
- goto out;
-
- if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
- mrsas_dprint(sc, MRSAS_OCR, "[%2d]waiting for %d "
- "commands to complete\n",i,outstanding);
- mrsas_complete_cmd(sc);
- }
- DELAY(1000 * 1000);
- }
-
- if (atomic_read(&sc->fw_outstanding)) {
- mrsas_dprint(sc, MRSAS_OCR,
- " pending commands remain after waiting,"
- " will reset adapter.\n");
- retval = 1;
- }
+void
+mrsas_kill_hba(struct mrsas_softc *sc)
+{
+ mrsas_dprint(sc, MRSAS_OCR, "%s\n", __func__);
+ mrsas_write_reg(sc, offsetof(mrsas_reg_set, doorbell),
+ MFI_STOP_ADP);
+ /* Flush */
+ mrsas_read_reg(sc, offsetof(mrsas_reg_set, doorbell));
+}
+
+/*
+ * mrsas_wait_for_outstanding: Wait for outstanding commands
+ * input: Adapter Context.
+ *
+ * This function will wait for 180 seconds for outstanding commands to be
+ * completed.
+ */
+int
+mrsas_wait_for_outstanding(struct mrsas_softc *sc)
+{
+ int i, outstanding, retval = 0;
+ u_int32_t fw_state, count, MSIxIndex;
+
+
+ for (i = 0; i < MRSAS_RESET_WAIT_TIME; i++) {
+ if (sc->remove_in_progress) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ "Driver remove or shutdown called.\n");
+ retval = 1;
+ goto out;
+ }
+ /* Check if firmware is in fault state */
+ fw_state = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
+ outbound_scratch_pad)) & MFI_STATE_MASK;
+ if (fw_state == MFI_STATE_FAULT) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ "Found FW in FAULT state, will reset adapter.\n");
+ retval = 1;
+ goto out;
+ }
+ outstanding = atomic_read(&sc->fw_outstanding);
+ if (!outstanding)
+ goto out;
+
+ if (!(i % MRSAS_RESET_NOTICE_INTERVAL)) {
+ mrsas_dprint(sc, MRSAS_OCR, "[%2d]waiting for %d "
+ "commands to complete\n", i, outstanding);
+ count = sc->msix_vectors > 0 ? sc->msix_vectors : 1;
+ for (MSIxIndex = 0; MSIxIndex < count; MSIxIndex++)
+ mrsas_complete_cmd(sc, MSIxIndex);
+ }
+ DELAY(1000 * 1000);
+ }
+
+ if (atomic_read(&sc->fw_outstanding)) {
+ mrsas_dprint(sc, MRSAS_OCR,
+ " pending commands remain after waiting,"
+ " will reset adapter.\n");
+ retval = 1;
+ }
out:
- return retval;
+ return retval;
}
-/**
- * mrsas_release_mfi_cmd: Return a cmd to free command pool
- * input: Command packet for return to free cmd pool
+/*
+ * mrsas_release_mfi_cmd: Return a cmd to free command pool
+ * input: Command packet for return to free cmd pool
*
* This function returns the MFI command to the command list.
*/
-void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd)
+void
+mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd)
{
- struct mrsas_softc *sc = cmd->sc;
+ struct mrsas_softc *sc = cmd->sc;
- mtx_lock(&sc->mfi_cmd_pool_lock);
- cmd->ccb_ptr = NULL;
+ mtx_lock(&sc->mfi_cmd_pool_lock);
+ cmd->ccb_ptr = NULL;
cmd->cmd_id.frame_count = 0;
- TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
- mtx_unlock(&sc->mfi_cmd_pool_lock);
+ TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
+ mtx_unlock(&sc->mfi_cmd_pool_lock);
- return;
+ return;
}
-/**
- * mrsas_get_controller_info - Returns FW's controller structure
- * input: Adapter soft state
- * Controller information structure
+/*
+ * mrsas_get_controller_info: Returns FW's controller structure
+ * input: Adapter soft state
+ * Controller information structure
*
- * Issues an internal command (DCMD) to get the FW's controller structure.
- * This information is mainly used to find out the maximum IO transfer per
- * command supported by the FW.
+ * Issues an internal command (DCMD) to get the FW's controller structure. This
+ * information is mainly used to find out the maximum IO transfer per command
+ * supported by the FW.
*/
-static int mrsas_get_ctrl_info(struct mrsas_softc *sc,
- struct mrsas_ctrl_info *ctrl_info)
+static int
+mrsas_get_ctrl_info(struct mrsas_softc *sc,
+ struct mrsas_ctrl_info *ctrl_info)
{
- int retcode = 0;
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_dcmd_frame *dcmd;
+ int retcode = 0;
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_dcmd_frame *dcmd;
- cmd = mrsas_get_mfi_cmd(sc);
+ cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev, "Failed to get a free cmd\n");
- return -ENOMEM;
- }
- dcmd = &cmd->frame->dcmd;
+ if (!cmd) {
+ device_printf(sc->mrsas_dev, "Failed to get a free cmd\n");
+ return -ENOMEM;
+ }
+ dcmd = &cmd->frame->dcmd;
- if (mrsas_alloc_ctlr_info_cmd(sc) != SUCCESS) {
- device_printf(sc->mrsas_dev, "Cannot allocate get ctlr info cmd\n");
- mrsas_release_mfi_cmd(cmd);
- return -ENOMEM;
- }
- memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+ if (mrsas_alloc_ctlr_info_cmd(sc) != SUCCESS) {
+ device_printf(sc->mrsas_dev, "Cannot allocate get ctlr info cmd\n");
+ mrsas_release_mfi_cmd(cmd);
+ return -ENOMEM;
+ }
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
- dcmd->cmd = MFI_CMD_DCMD;
- dcmd->cmd_status = 0xFF;
- dcmd->sge_count = 1;
- dcmd->flags = MFI_FRAME_DIR_READ;
- dcmd->timeout = 0;
- dcmd->pad_0 = 0;
- dcmd->data_xfer_len = sizeof(struct mrsas_ctrl_info);
- dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
- dcmd->sgl.sge32[0].phys_addr = sc->ctlr_info_phys_addr;
- dcmd->sgl.sge32[0].length = sizeof(struct mrsas_ctrl_info);
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = sizeof(struct mrsas_ctrl_info);
+ dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
+ dcmd->sgl.sge32[0].phys_addr = sc->ctlr_info_phys_addr;
+ dcmd->sgl.sge32[0].length = sizeof(struct mrsas_ctrl_info);
- if (!mrsas_issue_polled(sc, cmd))
- memcpy(ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info));
- else
- retcode = 1;
+ if (!mrsas_issue_polled(sc, cmd))
+ memcpy(ctrl_info, sc->ctlr_info_mem, sizeof(struct mrsas_ctrl_info));
+ else
+ retcode = 1;
- mrsas_free_ctlr_info_cmd(sc);
- mrsas_release_mfi_cmd(cmd);
- return(retcode);
+ mrsas_free_ctlr_info_cmd(sc);
+ mrsas_release_mfi_cmd(cmd);
+ return (retcode);
}
-/**
- * mrsas_alloc_ctlr_info_cmd: Allocates memory for controller info command
- * input: Adapter soft state
+/*
+ * mrsas_alloc_ctlr_info_cmd: Allocates memory for controller info command
+ * input: Adapter soft state
*
* Allocates DMAable memory for the controller info internal command.
*/
-int mrsas_alloc_ctlr_info_cmd(struct mrsas_softc *sc)
-{
- int ctlr_info_size;
-
- /* Allocate get controller info command */
- ctlr_info_size = sizeof(struct mrsas_ctrl_info);
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- ctlr_info_size, // maxsize
- 1, // msegments
- ctlr_info_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->ctlr_info_tag)) {
- device_printf(sc->mrsas_dev, "Cannot allocate ctlr info tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(sc->ctlr_info_tag, (void **)&sc->ctlr_info_mem,
- BUS_DMA_NOWAIT, &sc->ctlr_info_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot allocate ctlr info cmd mem\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(sc->ctlr_info_tag, sc->ctlr_info_dmamap,
- sc->ctlr_info_mem, ctlr_info_size, mrsas_addr_cb,
- &sc->ctlr_info_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load ctlr info cmd mem\n");
- return (ENOMEM);
- }
-
- memset(sc->ctlr_info_mem, 0, ctlr_info_size);
- return (0);
-}
-
-/**
- * mrsas_free_ctlr_info_cmd: Free memory for controller info command
- * input: Adapter soft state
+int
+mrsas_alloc_ctlr_info_cmd(struct mrsas_softc *sc)
+{
+ int ctlr_info_size;
+
+ /* Allocate get controller info command */
+ ctlr_info_size = sizeof(struct mrsas_ctrl_info);
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ ctlr_info_size,
+ 1,
+ ctlr_info_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->ctlr_info_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ctlr info tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(sc->ctlr_info_tag, (void **)&sc->ctlr_info_mem,
+ BUS_DMA_NOWAIT, &sc->ctlr_info_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ctlr info cmd mem\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamap_load(sc->ctlr_info_tag, sc->ctlr_info_dmamap,
+ sc->ctlr_info_mem, ctlr_info_size, mrsas_addr_cb,
+ &sc->ctlr_info_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load ctlr info cmd mem\n");
+ return (ENOMEM);
+ }
+ memset(sc->ctlr_info_mem, 0, ctlr_info_size);
+ return (0);
+}
+
+/*
+ * mrsas_free_ctlr_info_cmd: Free memory for controller info command
+ * input: Adapter soft state
*
* Deallocates memory of the get controller info cmd.
*/
-void mrsas_free_ctlr_info_cmd(struct mrsas_softc *sc)
-{
- if (sc->ctlr_info_phys_addr)
- bus_dmamap_unload(sc->ctlr_info_tag, sc->ctlr_info_dmamap);
- if (sc->ctlr_info_mem != NULL)
- bus_dmamem_free(sc->ctlr_info_tag, sc->ctlr_info_mem, sc->ctlr_info_dmamap);
- if (sc->ctlr_info_tag != NULL)
- bus_dma_tag_destroy(sc->ctlr_info_tag);
-}
-
-/**
- * mrsas_issue_polled: Issues a polling command
- * inputs: Adapter soft state
- * Command packet to be issued
- *
- * This function is for posting of internal commands to Firmware. MFI
- * requires the cmd_status to be set to 0xFF before posting. The maximun
- * wait time of the poll response timer is 180 seconds.
- */
-int mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
-{
- struct mrsas_header *frame_hdr = &cmd->frame->hdr;
- u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME;
- int i, retcode = 0;
-
- frame_hdr->cmd_status = 0xFF;
- frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
-
- /* Issue the frame using inbound queue port */
- if (mrsas_issue_dcmd(sc, cmd)) {
- device_printf(sc->mrsas_dev, "Cannot issue DCMD internal command.\n");
- return(1);
- }
-
- /*
- * Poll response timer to wait for Firmware response. While this
- * timer with the DELAY call could block CPU, the time interval for
- * this is only 1 millisecond.
- */
- if (frame_hdr->cmd_status == 0xFF) {
- for (i=0; i < (max_wait * 1000); i++){
- if (frame_hdr->cmd_status == 0xFF)
- DELAY(1000);
- else
- break;
- }
- }
- if (frame_hdr->cmd_status != 0)
- {
- if (frame_hdr->cmd_status == 0xFF)
- device_printf(sc->mrsas_dev, "DCMD timed out after %d seconds.\n", max_wait);
- else
- device_printf(sc->mrsas_dev, "DCMD failed, status = 0x%x\n", frame_hdr->cmd_status);
- retcode = 1;
- }
- return(retcode);
-}
-
-/**
- * mrsas_issue_dcmd - Issues a MFI Pass thru cmd
- * input: Adapter soft state
- * mfi cmd pointer
+void
+mrsas_free_ctlr_info_cmd(struct mrsas_softc *sc)
+{
+ if (sc->ctlr_info_phys_addr)
+ bus_dmamap_unload(sc->ctlr_info_tag, sc->ctlr_info_dmamap);
+ if (sc->ctlr_info_mem != NULL)
+ bus_dmamem_free(sc->ctlr_info_tag, sc->ctlr_info_mem, sc->ctlr_info_dmamap);
+ if (sc->ctlr_info_tag != NULL)
+ bus_dma_tag_destroy(sc->ctlr_info_tag);
+}
+
+/*
+ * mrsas_issue_polled: Issues a polling command
+ * inputs: Adapter soft state
+ * Command packet to be issued
+ *
+ * This function is for posting of internal commands to Firmware. MFI requires
+ * the cmd_status to be set to 0xFF before posting. The maximun wait time of
+ * the poll response timer is 180 seconds.
+ */
+int
+mrsas_issue_polled(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
+{
+ struct mrsas_header *frame_hdr = &cmd->frame->hdr;
+ u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME;
+ int i, retcode = 0;
+
+ frame_hdr->cmd_status = 0xFF;
+ frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+ /* Issue the frame using inbound queue port */
+ if (mrsas_issue_dcmd(sc, cmd)) {
+ device_printf(sc->mrsas_dev, "Cannot issue DCMD internal command.\n");
+ return (1);
+ }
+ /*
+ * Poll response timer to wait for Firmware response. While this
+ * timer with the DELAY call could block CPU, the time interval for
+ * this is only 1 millisecond.
+ */
+ if (frame_hdr->cmd_status == 0xFF) {
+ for (i = 0; i < (max_wait * 1000); i++) {
+ if (frame_hdr->cmd_status == 0xFF)
+ DELAY(1000);
+ else
+ break;
+ }
+ }
+ if (frame_hdr->cmd_status != 0) {
+ if (frame_hdr->cmd_status == 0xFF)
+ device_printf(sc->mrsas_dev, "DCMD timed out after %d seconds.\n", max_wait);
+ else
+ device_printf(sc->mrsas_dev, "DCMD failed, status = 0x%x\n", frame_hdr->cmd_status);
+ retcode = 1;
+ }
+ return (retcode);
+}
+
+/*
+ * mrsas_issue_dcmd: Issues a MFI Pass thru cmd
+ * input: Adapter soft state mfi cmd pointer
*
* This function is called by mrsas_issued_blocked_cmd() and
- * mrsas_issued_polled(), to build the MPT command and then fire the
- * command to Firmware.
+ * mrsas_issued_polled(), to build the MPT command and then fire the command
+ * to Firmware.
*/
int
mrsas_issue_dcmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
- MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
-
- req_desc = mrsas_build_mpt_cmd(sc, cmd);
- if (!req_desc) {
- device_printf(sc->mrsas_dev, "Cannot build MPT cmd.\n");
- return(1);
- }
+ MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
- mrsas_fire_cmd(sc, req_desc->addr.u.low, req_desc->addr.u.high);
+ req_desc = mrsas_build_mpt_cmd(sc, cmd);
+ if (!req_desc) {
+ device_printf(sc->mrsas_dev, "Cannot build MPT cmd.\n");
+ return (1);
+ }
+ mrsas_fire_cmd(sc, req_desc->addr.u.low, req_desc->addr.u.high);
- return(0);
+ return (0);
}
-/**
- * mrsas_build_mpt_cmd - Calls helper function to build Passthru cmd
- * input: Adapter soft state
- * mfi cmd to build
+/*
+ * mrsas_build_mpt_cmd: Calls helper function to build Passthru cmd
+ * input: Adapter soft state mfi cmd to build
*
- * This function is called by mrsas_issue_cmd() to build the MPT-MFI
- * passthru command and prepares the MPT command to send to Firmware.
+ * This function is called by mrsas_issue_cmd() to build the MPT-MFI passthru
+ * command and prepares the MPT command to send to Firmware.
*/
MRSAS_REQUEST_DESCRIPTOR_UNION *
mrsas_build_mpt_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
- MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
- u_int16_t index;
-
- if (mrsas_build_mptmfi_passthru(sc, cmd)) {
- device_printf(sc->mrsas_dev, "Cannot build MPT-MFI passthru cmd.\n");
- return NULL;
- }
+ MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+ u_int16_t index;
- index = cmd->cmd_id.context.smid;
+ if (mrsas_build_mptmfi_passthru(sc, cmd)) {
+ device_printf(sc->mrsas_dev, "Cannot build MPT-MFI passthru cmd.\n");
+ return NULL;
+ }
+ index = cmd->cmd_id.context.smid;
- req_desc = mrsas_get_request_desc(sc, index-1);
- if(!req_desc)
- return NULL;
+ req_desc = mrsas_get_request_desc(sc, index - 1);
+ if (!req_desc)
+ return NULL;
- req_desc->addr.Words = 0;
- req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ req_desc->addr.Words = 0;
+ req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- req_desc->SCSIIO.SMID = index;
+ req_desc->SCSIIO.SMID = index;
- return(req_desc);
+ return (req_desc);
}
-/**
- * mrsas_build_mptmfi_passthru - Builds a MPT MFI Passthru command
- * input: Adapter soft state
- * mfi cmd pointer
+/*
+ * mrsas_build_mptmfi_passthru: Builds a MPT MFI Passthru command
+ * input: Adapter soft state mfi cmd pointer
*
- * The MPT command and the io_request are setup as a passthru command.
- * The SGE chain address is set to frame_phys_addr of the MFI command.
+ * The MPT command and the io_request are setup as a passthru command. The SGE
+ * chain address is set to frame_phys_addr of the MFI command.
*/
u_int8_t
mrsas_build_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *mfi_cmd)
{
- MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
- PTR_MRSAS_RAID_SCSI_IO_REQUEST io_req;
- struct mrsas_mpt_cmd *mpt_cmd;
- struct mrsas_header *frame_hdr = &mfi_cmd->frame->hdr;
+ MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
+ PTR_MRSAS_RAID_SCSI_IO_REQUEST io_req;
+ struct mrsas_mpt_cmd *mpt_cmd;
+ struct mrsas_header *frame_hdr = &mfi_cmd->frame->hdr;
- mpt_cmd = mrsas_get_mpt_cmd(sc);
- if (!mpt_cmd)
- return(1);
+ mpt_cmd = mrsas_get_mpt_cmd(sc);
+ if (!mpt_cmd)
+ return (1);
- /* Save the smid. To be used for returning the cmd */
- mfi_cmd->cmd_id.context.smid = mpt_cmd->index;
+ /* Save the smid. To be used for returning the cmd */
+ mfi_cmd->cmd_id.context.smid = mpt_cmd->index;
- mpt_cmd->sync_cmd_idx = mfi_cmd->index;
+ mpt_cmd->sync_cmd_idx = mfi_cmd->index;
- /*
- * For cmds where the flag is set, store the flag and check
- * on completion. For cmds with this flag, don't call
- * mrsas_complete_cmd.
- */
+ /*
+ * For cmds where the flag is set, store the flag and check on
+ * completion. For cmds with this flag, don't call
+ * mrsas_complete_cmd.
+ */
- if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
- mpt_cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+ if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
+ mpt_cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
- io_req = mpt_cmd->io_request;
+ io_req = mpt_cmd->io_request;
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
- pMpi25IeeeSgeChain64_t sgl_ptr_end = (pMpi25IeeeSgeChain64_t) &io_req->SGL;
- sgl_ptr_end += sc->max_sge_in_main_msg - 1;
- sgl_ptr_end->Flags = 0;
- }
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
+ pMpi25IeeeSgeChain64_t sgl_ptr_end = (pMpi25IeeeSgeChain64_t)&io_req->SGL;
- mpi25_ieee_chain = (MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
+ sgl_ptr_end += sc->max_sge_in_main_msg - 1;
+ sgl_ptr_end->Flags = 0;
+ }
+ mpi25_ieee_chain = (MPI25_IEEE_SGE_CHAIN64 *) & io_req->SGL.IeeeChain;
- io_req->Function = MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
- io_req->SGLOffset0 = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL) / 4;
- io_req->ChainOffset = sc->chain_offset_mfi_pthru;
+ io_req->Function = MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
+ io_req->SGLOffset0 = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL) / 4;
+ io_req->ChainOffset = sc->chain_offset_mfi_pthru;
- mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr;
+ mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr;
- mpi25_ieee_chain->Flags= IEEE_SGE_FLAGS_CHAIN_ELEMENT |
- MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
+ mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+ MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
- mpi25_ieee_chain->Length = MRSAS_MAX_SZ_CHAIN_FRAME;
+ mpi25_ieee_chain->Length = MRSAS_MAX_SZ_CHAIN_FRAME;
- return(0);
+ return (0);
}
-/**
- * mrsas_issue_blocked_cmd - Synchronous wrapper around regular FW cmds
- * input: Adapter soft state
- * Command to be issued
+/*
+ * mrsas_issue_blocked_cmd: Synchronous wrapper around regular FW cmds
+ * input: Adapter soft state Command to be issued
*
- * This function waits on an event for the command to be returned
- * from the ISR. Max wait time is MRSAS_INTERNAL_CMD_WAIT_TIME secs.
- * Used for issuing internal and ioctl commands.
+ * This function waits on an event for the command to be returned from the ISR.
+ * Max wait time is MRSAS_INTERNAL_CMD_WAIT_TIME secs. Used for issuing
+ * internal and ioctl commands.
*/
-int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
+int
+mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
- u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME;
- unsigned long total_time = 0;
- int retcode = 0;
-
- /* Initialize cmd_status */
- cmd->cmd_status = ECONNREFUSED;
-
- /* Build MPT-MFI command for issue to FW */
- if (mrsas_issue_dcmd(sc, cmd)){
- device_printf(sc->mrsas_dev, "Cannot issue DCMD internal command.\n");
- return(1);
- }
-
- sc->chan = (void*)&cmd;
+ u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME;
+ unsigned long total_time = 0;
+ int retcode = 0;
- /* The following is for debug only... */
- //device_printf(sc->mrsas_dev,"DCMD issued to FW, about to sleep-wait...\n");
- //device_printf(sc->mrsas_dev,"sc->chan = %p\n", sc->chan);
+ /* Initialize cmd_status */
+ cmd->cmd_status = ECONNREFUSED;
- while (1) {
- if (cmd->cmd_status == ECONNREFUSED){
- tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz);
- }
- else
- break;
- total_time++;
- if (total_time >= max_wait) {
- device_printf(sc->mrsas_dev, "Internal command timed out after %d seconds.\n", max_wait);
- retcode = 1;
- break;
- }
- }
- return(retcode);
+ /* Build MPT-MFI command for issue to FW */
+ if (mrsas_issue_dcmd(sc, cmd)) {
+ device_printf(sc->mrsas_dev, "Cannot issue DCMD internal command.\n");
+ return (1);
+ }
+ sc->chan = (void *)&cmd;
+
+ while (1) {
+ if (cmd->cmd_status == ECONNREFUSED) {
+ tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz);
+ } else
+ break;
+ total_time++;
+ if (total_time >= max_wait) {
+ device_printf(sc->mrsas_dev,
+ "Internal command timed out after %d seconds.\n", max_wait);
+ retcode = 1;
+ break;
+ }
+ }
+ return (retcode);
}
-/**
- * mrsas_complete_mptmfi_passthru - Completes a command
- * input: sc: Adapter soft state
- * cmd: Command to be completed
- * status: cmd completion status
+/*
+ * mrsas_complete_mptmfi_passthru: Completes a command
+ * input: @sc: Adapter soft state
+ * @cmd: Command to be completed
+ * @status: cmd completion status
*
- * This function is called from mrsas_complete_cmd() after an interrupt
- * is received from Firmware, and io_request->Function is
+ * This function is called from mrsas_complete_cmd() after an interrupt is
+ * received from Firmware, and io_request->Function is
* MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST.
*/
void
mrsas_complete_mptmfi_passthru(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd,
- u_int8_t status)
-{
- struct mrsas_header *hdr = &cmd->frame->hdr;
- u_int8_t cmd_status = cmd->frame->hdr.cmd_status;
-
- /* Reset the retry counter for future re-tries */
- cmd->retry_for_fw_reset = 0;
-
- if (cmd->ccb_ptr)
- cmd->ccb_ptr = NULL;
-
- switch (hdr->cmd) {
- case MFI_CMD_INVALID:
- device_printf(sc->mrsas_dev, "MFI_CMD_INVALID command.\n");
- break;
- case MFI_CMD_PD_SCSI_IO:
- case MFI_CMD_LD_SCSI_IO:
- /*
- * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been
- * issued either through an IO path or an IOCTL path. If it
- * was via IOCTL, we will send it to internal completion.
- */
- if (cmd->sync_cmd) {
- cmd->sync_cmd = 0;
- mrsas_wakeup(sc, cmd);
- break;
- }
- case MFI_CMD_SMP:
- case MFI_CMD_STP:
- case MFI_CMD_DCMD:
- /* Check for LD map update */
- if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) &&
- (cmd->frame->dcmd.mbox.b[1] == 1)) {
- sc->fast_path_io = 0;
- mtx_lock(&sc->raidmap_lock);
- if (cmd_status != 0) {
- if (cmd_status != MFI_STAT_NOT_FOUND)
- device_printf(sc->mrsas_dev, "map sync failed, status=%x\n",cmd_status);
- else {
- mrsas_release_mfi_cmd(cmd);
- mtx_unlock(&sc->raidmap_lock);
- break;
- }
- }
- else
- sc->map_id++;
- mrsas_release_mfi_cmd(cmd);
- if (MR_ValidateMapInfo(sc))
- sc->fast_path_io = 0;
- else
- sc->fast_path_io = 1;
- mrsas_sync_map_info(sc);
- mtx_unlock(&sc->raidmap_lock);
- break;
- }
-#if 0 //currently not supporting event handling, so commenting out
- if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
- cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
- mrsas_poll_wait_aen = 0;
- }
-#endif
- /* See if got an event notification */
- if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT)
- mrsas_complete_aen(sc, cmd);
- else
- mrsas_wakeup(sc, cmd);
- break;
- case MFI_CMD_ABORT:
- /* Command issued to abort another cmd return */
- mrsas_complete_abort(sc, cmd);
- break;
- default:
- device_printf(sc->mrsas_dev,"Unknown command completed! [0x%X]\n", hdr->cmd);
- break;
- }
+ u_int8_t status)
+{
+ struct mrsas_header *hdr = &cmd->frame->hdr;
+ u_int8_t cmd_status = cmd->frame->hdr.cmd_status;
+
+ /* Reset the retry counter for future re-tries */
+ cmd->retry_for_fw_reset = 0;
+
+ if (cmd->ccb_ptr)
+ cmd->ccb_ptr = NULL;
+
+ switch (hdr->cmd) {
+ case MFI_CMD_INVALID:
+ device_printf(sc->mrsas_dev, "MFI_CMD_INVALID command.\n");
+ break;
+ case MFI_CMD_PD_SCSI_IO:
+ case MFI_CMD_LD_SCSI_IO:
+ /*
+ * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been
+ * issued either through an IO path or an IOCTL path. If it
+ * was via IOCTL, we will send it to internal completion.
+ */
+ if (cmd->sync_cmd) {
+ cmd->sync_cmd = 0;
+ mrsas_wakeup(sc, cmd);
+ break;
+ }
+ case MFI_CMD_SMP:
+ case MFI_CMD_STP:
+ case MFI_CMD_DCMD:
+ /* Check for LD map update */
+ if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) &&
+ (cmd->frame->dcmd.mbox.b[1] == 1)) {
+ sc->fast_path_io = 0;
+ mtx_lock(&sc->raidmap_lock);
+ if (cmd_status != 0) {
+ if (cmd_status != MFI_STAT_NOT_FOUND)
+ device_printf(sc->mrsas_dev, "map sync failed, status=%x\n", cmd_status);
+ else {
+ mrsas_release_mfi_cmd(cmd);
+ mtx_unlock(&sc->raidmap_lock);
+ break;
+ }
+ } else
+ sc->map_id++;
+ mrsas_release_mfi_cmd(cmd);
+ if (MR_ValidateMapInfo(sc))
+ sc->fast_path_io = 0;
+ else
+ sc->fast_path_io = 1;
+ mrsas_sync_map_info(sc);
+ mtx_unlock(&sc->raidmap_lock);
+ break;
+ }
+ if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
+ cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
+ sc->mrsas_aen_triggered = 0;
+ }
+ /* See if got an event notification */
+ if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT)
+ mrsas_complete_aen(sc, cmd);
+ else
+ mrsas_wakeup(sc, cmd);
+ break;
+ case MFI_CMD_ABORT:
+ /* Command issued to abort another cmd return */
+ mrsas_complete_abort(sc, cmd);
+ break;
+ default:
+ device_printf(sc->mrsas_dev, "Unknown command completed! [0x%X]\n", hdr->cmd);
+ break;
+ }
}
-/**
- * mrsas_wakeup - Completes an internal command
- * input: Adapter soft state
- * Command to be completed
+/*
+ * mrsas_wakeup: Completes an internal command
+ * input: Adapter soft state
+ * Command to be completed
*
- * In mrsas_issue_blocked_cmd(), after a command is issued to Firmware,
- * a wait timer is started. This function is called from
- * mrsas_complete_mptmfi_passthru() as it completes the command,
- * to wake up from the command wait.
+ * In mrsas_issue_blocked_cmd(), after a command is issued to Firmware, a wait
+ * timer is started. This function is called from
+ * mrsas_complete_mptmfi_passthru() as it completes the command, to wake up
+ * from the command wait.
*/
-void mrsas_wakeup(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
+void
+mrsas_wakeup(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
- cmd->cmd_status = cmd->frame->io.cmd_status;
+ cmd->cmd_status = cmd->frame->io.cmd_status;
- if (cmd->cmd_status == ECONNREFUSED)
- cmd->cmd_status = 0;
+ if (cmd->cmd_status == ECONNREFUSED)
+ cmd->cmd_status = 0;
- /* For debug only ... */
- //device_printf(sc->mrsas_dev,"DCMD rec'd for wakeup, sc->chan=%p\n", sc->chan);
-
- sc->chan = (void*)&cmd;
- wakeup_one((void *)&sc->chan);
- return;
+ sc->chan = (void *)&cmd;
+ wakeup_one((void *)&sc->chan);
+ return;
}
-/**
- * mrsas_shutdown_ctlr: Instructs FW to shutdown the controller
- * input: Adapter soft state
- * Shutdown/Hibernate
+/*
+ * mrsas_shutdown_ctlr: Instructs FW to shutdown the controller input:
+ * Adapter soft state Shutdown/Hibernate
*
- * This function issues a DCMD internal command to Firmware to initiate
- * shutdown of the controller.
+ * This function issues a DCMD internal command to Firmware to initiate shutdown
+ * of the controller.
*/
-static void mrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode)
+static void
+mrsas_shutdown_ctlr(struct mrsas_softc *sc, u_int32_t opcode)
{
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_dcmd_frame *dcmd;
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_dcmd_frame *dcmd;
- if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR)
- return;
+ if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR)
+ return;
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev,"Cannot allocate for shutdown cmd.\n");
- return;
- }
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev, "Cannot allocate for shutdown cmd.\n");
+ return;
+ }
+ if (sc->aen_cmd)
+ mrsas_issue_blocked_abort_cmd(sc, sc->aen_cmd);
- if (sc->aen_cmd)
- mrsas_issue_blocked_abort_cmd(sc, sc->aen_cmd);
-
if (sc->map_update_cmd)
- mrsas_issue_blocked_abort_cmd(sc, sc->map_update_cmd);
+ mrsas_issue_blocked_abort_cmd(sc, sc->map_update_cmd);
- dcmd = &cmd->frame->dcmd;
- memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+ dcmd = &cmd->frame->dcmd;
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
- dcmd->cmd = MFI_CMD_DCMD;
- dcmd->cmd_status = 0x0;
- dcmd->sge_count = 0;
- dcmd->flags = MFI_FRAME_DIR_NONE;
- dcmd->timeout = 0;
- dcmd->pad_0 = 0;
- dcmd->data_xfer_len = 0;
- dcmd->opcode = opcode;
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0x0;
+ dcmd->sge_count = 0;
+ dcmd->flags = MFI_FRAME_DIR_NONE;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = 0;
+ dcmd->opcode = opcode;
- device_printf(sc->mrsas_dev,"Preparing to shut down controller.\n");
+ device_printf(sc->mrsas_dev, "Preparing to shut down controller.\n");
- mrsas_issue_blocked_cmd(sc, cmd);
- mrsas_release_mfi_cmd(cmd);
+ mrsas_issue_blocked_cmd(sc, cmd);
+ mrsas_release_mfi_cmd(cmd);
- return;
+ return;
}
-/**
- * mrsas_flush_cache: Requests FW to flush all its caches
- * input: Adapter soft state
+/*
+ * mrsas_flush_cache: Requests FW to flush all its caches input:
+ * Adapter soft state
*
* This function is issues a DCMD internal command to Firmware to initiate
* flushing of all caches.
*/
-static void mrsas_flush_cache(struct mrsas_softc *sc)
-{
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_dcmd_frame *dcmd;
-
- if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR)
- return;
-
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev,"Cannot allocate for flush cache cmd.\n");
- return;
- }
-
- dcmd = &cmd->frame->dcmd;
- memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
- dcmd->cmd = MFI_CMD_DCMD;
- dcmd->cmd_status = 0x0;
- dcmd->sge_count = 0;
- dcmd->flags = MFI_FRAME_DIR_NONE;
- dcmd->timeout = 0;
- dcmd->pad_0 = 0;
- dcmd->data_xfer_len = 0;
- dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
- dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
-
- mrsas_issue_blocked_cmd(sc, cmd);
- mrsas_release_mfi_cmd(cmd);
-
- return;
-}
-
-/**
- * mrsas_get_map_info: Load and validate RAID map
- * input: Adapter instance soft state
- *
- * This function calls mrsas_get_ld_map_info() and MR_ValidateMapInfo()
- * to load and validate RAID map. It returns 0 if successful, 1 other-
- * wise.
- */
-static int mrsas_get_map_info(struct mrsas_softc *sc)
-{
- uint8_t retcode = 0;
-
- sc->fast_path_io = 0;
- if (!mrsas_get_ld_map_info(sc)) {
- retcode = MR_ValidateMapInfo(sc);
- if (retcode == 0) {
- sc->fast_path_io = 1;
- return 0;
- }
- }
- return 1;
-}
-
-/**
- * mrsas_get_ld_map_info: Get FW's ld_map structure
- * input: Adapter instance soft state
- *
- * Issues an internal command (DCMD) to get the FW's controller PD
- * list structure.
- */
-static int mrsas_get_ld_map_info(struct mrsas_softc *sc)
-{
- int retcode = 0;
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_dcmd_frame *dcmd;
- MR_FW_RAID_MAP_ALL *map;
- bus_addr_t map_phys_addr = 0;
-
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev, "Cannot alloc for ld map info cmd.\n");
- return 1;
- }
-
- dcmd = &cmd->frame->dcmd;
-
- map = sc->raidmap_mem[(sc->map_id & 1)];
- map_phys_addr = sc->raidmap_phys_addr[(sc->map_id & 1)];
- if (!map) {
- device_printf(sc->mrsas_dev, "Failed to alloc mem for ld map info.\n");
- mrsas_release_mfi_cmd(cmd);
- return (ENOMEM);
- }
- memset(map, 0, sizeof(*map));
- memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
- dcmd->cmd = MFI_CMD_DCMD;
- dcmd->cmd_status = 0xFF;
- dcmd->sge_count = 1;
- dcmd->flags = MFI_FRAME_DIR_READ;
- dcmd->timeout = 0;
- dcmd->pad_0 = 0;
- dcmd->data_xfer_len = sc->map_sz;
- dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
- dcmd->sgl.sge32[0].phys_addr = map_phys_addr;
- dcmd->sgl.sge32[0].length = sc->map_sz;
- if (!mrsas_issue_polled(sc, cmd))
- retcode = 0;
- else
- {
- device_printf(sc->mrsas_dev, "Fail to send get LD map info cmd.\n");
- retcode = 1;
- }
- mrsas_release_mfi_cmd(cmd);
- return(retcode);
-}
-
-/**
- * mrsas_sync_map_info: Get FW's ld_map structure
- * input: Adapter instance soft state
- *
- * Issues an internal command (DCMD) to get the FW's controller PD
- * list structure.
- */
-static int mrsas_sync_map_info(struct mrsas_softc *sc)
-{
- int retcode = 0, i;
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_dcmd_frame *dcmd;
- uint32_t size_sync_info, num_lds;
- MR_LD_TARGET_SYNC *target_map = NULL;
- MR_FW_RAID_MAP_ALL *map;
- MR_LD_RAID *raid;
- MR_LD_TARGET_SYNC *ld_sync;
- bus_addr_t map_phys_addr = 0;
-
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev, "Cannot alloc for sync map info cmd\n");
- return 1;
- }
-
- map = sc->raidmap_mem[sc->map_id & 1];
- num_lds = map->raidMap.ldCount;
-
- dcmd = &cmd->frame->dcmd;
- size_sync_info = sizeof(MR_LD_TARGET_SYNC) * num_lds;
- memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
- target_map = (MR_LD_TARGET_SYNC *)sc->raidmap_mem[(sc->map_id - 1) & 1];
- memset(target_map, 0, sizeof(MR_FW_RAID_MAP_ALL));
-
- map_phys_addr = sc->raidmap_phys_addr[(sc->map_id - 1) & 1];
-
- ld_sync = (MR_LD_TARGET_SYNC *)target_map;
-
- for (i = 0; i < num_lds; i++, ld_sync++) {
- raid = MR_LdRaidGet(i, map);
- ld_sync->targetId = MR_GetLDTgtId(i, map);
- ld_sync->seqNum = raid->seqNum;
- }
-
- dcmd->cmd = MFI_CMD_DCMD;
- dcmd->cmd_status = 0xFF;
- dcmd->sge_count = 1;
- dcmd->flags = MFI_FRAME_DIR_WRITE;
- dcmd->timeout = 0;
- dcmd->pad_0 = 0;
- dcmd->data_xfer_len = sc->map_sz;
- dcmd->mbox.b[0] = num_lds;
- dcmd->mbox.b[1] = MRSAS_DCMD_MBOX_PEND_FLAG;
- dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
- dcmd->sgl.sge32[0].phys_addr = map_phys_addr;
- dcmd->sgl.sge32[0].length = sc->map_sz;
-
- sc->map_update_cmd = cmd;
- if (mrsas_issue_dcmd(sc, cmd)) {
- device_printf(sc->mrsas_dev, "Fail to send sync map info command.\n");
- return(1);
- }
- return(retcode);
-}
-
-/**
- * mrsas_get_pd_list: Returns FW's PD list structure
- * input: Adapter soft state
- *
- * Issues an internal command (DCMD) to get the FW's controller PD
- * list structure. This information is mainly used to find out about
- * system supported by Firmware.
- */
-static int mrsas_get_pd_list(struct mrsas_softc *sc)
-{
- int retcode = 0, pd_index = 0, pd_count=0, pd_list_size;
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_dcmd_frame *dcmd;
- struct MR_PD_LIST *pd_list_mem;
- struct MR_PD_ADDRESS *pd_addr;
- bus_addr_t pd_list_phys_addr = 0;
- struct mrsas_tmp_dcmd *tcmd;
-
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev, "Cannot alloc for get PD list cmd\n");
- return 1;
- }
-
- dcmd = &cmd->frame->dcmd;
-
- tcmd = malloc(sizeof(struct mrsas_tmp_dcmd), M_MRSAS, M_NOWAIT);
- pd_list_size = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST);
- if (mrsas_alloc_tmp_dcmd(sc, tcmd, pd_list_size) != SUCCESS) {
- device_printf(sc->mrsas_dev, "Cannot alloc dmamap for get PD list cmd\n");
- mrsas_release_mfi_cmd(cmd);
- return(ENOMEM);
- }
- else {
- pd_list_mem = tcmd->tmp_dcmd_mem;
- pd_list_phys_addr = tcmd->tmp_dcmd_phys_addr;
- }
- memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
- dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
- dcmd->mbox.b[1] = 0;
- dcmd->cmd = MFI_CMD_DCMD;
- dcmd->cmd_status = 0xFF;
- dcmd->sge_count = 1;
- dcmd->flags = MFI_FRAME_DIR_READ;
- dcmd->timeout = 0;
- dcmd->pad_0 = 0;
- dcmd->data_xfer_len = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST);
- dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
- dcmd->sgl.sge32[0].phys_addr = pd_list_phys_addr;
- dcmd->sgl.sge32[0].length = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST);
-
- if (!mrsas_issue_polled(sc, cmd))
- retcode = 0;
- else
- retcode = 1;
-
- /* Get the instance PD list */
- pd_count = MRSAS_MAX_PD;
- pd_addr = pd_list_mem->addr;
- if (retcode == 0 && pd_list_mem->count < pd_count) {
- memset(sc->local_pd_list, 0, MRSAS_MAX_PD * sizeof(struct mrsas_pd_list));
- for (pd_index = 0; pd_index < pd_list_mem->count; pd_index++) {
- sc->local_pd_list[pd_addr->deviceId].tid = pd_addr->deviceId;
- sc->local_pd_list[pd_addr->deviceId].driveType = pd_addr->scsiDevType;
- sc->local_pd_list[pd_addr->deviceId].driveState = MR_PD_STATE_SYSTEM;
- pd_addr++;
- }
- }
-
- /* Use mutext/spinlock if pd_list component size increase more than 32 bit. */
- memcpy(sc->pd_list, sc->local_pd_list, sizeof(sc->local_pd_list));
- mrsas_free_tmp_dcmd(tcmd);
- mrsas_release_mfi_cmd(cmd);
- free(tcmd, M_MRSAS);
- return(retcode);
-}
-
-/**
- * mrsas_get_ld_list: Returns FW's LD list structure
- * input: Adapter soft state
- *
- * Issues an internal command (DCMD) to get the FW's controller PD
- * list structure. This information is mainly used to find out about
- * supported by the FW.
+static void
+mrsas_flush_cache(struct mrsas_softc *sc)
+{
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_dcmd_frame *dcmd;
+
+ if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR)
+ return;
+
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev, "Cannot allocate for flush cache cmd.\n");
+ return;
+ }
+ dcmd = &cmd->frame->dcmd;
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0x0;
+ dcmd->sge_count = 0;
+ dcmd->flags = MFI_FRAME_DIR_NONE;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = 0;
+ dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
+ dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
+
+ mrsas_issue_blocked_cmd(sc, cmd);
+ mrsas_release_mfi_cmd(cmd);
+
+ return;
+}
+
+/*
+ * mrsas_get_map_info: Load and validate RAID map input:
+ * Adapter instance soft state
+ *
+ * This function calls mrsas_get_ld_map_info() and MR_ValidateMapInfo() to load
+ * and validate RAID map. It returns 0 if successful, 1 other- wise.
*/
-static int mrsas_get_ld_list(struct mrsas_softc *sc)
-{
- int ld_list_size, retcode = 0, ld_index = 0, ids = 0;
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_dcmd_frame *dcmd;
- struct MR_LD_LIST *ld_list_mem;
- bus_addr_t ld_list_phys_addr = 0;
- struct mrsas_tmp_dcmd *tcmd;
-
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev, "Cannot alloc for get LD list cmd\n");
- return 1;
- }
-
- dcmd = &cmd->frame->dcmd;
-
- tcmd = malloc(sizeof(struct mrsas_tmp_dcmd), M_MRSAS, M_NOWAIT);
- ld_list_size = sizeof(struct MR_LD_LIST);
- if (mrsas_alloc_tmp_dcmd(sc, tcmd, ld_list_size) != SUCCESS) {
- device_printf(sc->mrsas_dev, "Cannot alloc dmamap for get LD list cmd\n");
- mrsas_release_mfi_cmd(cmd);
- return(ENOMEM);
- }
- else {
- ld_list_mem = tcmd->tmp_dcmd_mem;
- ld_list_phys_addr = tcmd->tmp_dcmd_phys_addr;
- }
- memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
-
- dcmd->cmd = MFI_CMD_DCMD;
- dcmd->cmd_status = 0xFF;
- dcmd->sge_count = 1;
- dcmd->flags = MFI_FRAME_DIR_READ;
- dcmd->timeout = 0;
- dcmd->data_xfer_len = sizeof(struct MR_LD_LIST);
- dcmd->opcode = MR_DCMD_LD_GET_LIST;
- dcmd->sgl.sge32[0].phys_addr = ld_list_phys_addr;
- dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
- dcmd->pad_0 = 0;
-
- if (!mrsas_issue_polled(sc, cmd))
- retcode = 0;
- else
- retcode = 1;
-
- /* Get the instance LD list */
- if ((retcode == 0) && (ld_list_mem->ldCount <= (MAX_LOGICAL_DRIVES))){
- sc->CurLdCount = ld_list_mem->ldCount;
- memset(sc->ld_ids, 0xff, MRSAS_MAX_LD);
- for (ld_index = 0; ld_index < ld_list_mem->ldCount; ld_index++) {
- if (ld_list_mem->ldList[ld_index].state != 0) {
- ids = ld_list_mem->ldList[ld_index].ref.ld_context.targetId;
- sc->ld_ids[ids] = ld_list_mem->ldList[ld_index].ref.ld_context.targetId;
- }
- }
- }
-
- mrsas_free_tmp_dcmd(tcmd);
- mrsas_release_mfi_cmd(cmd);
- free(tcmd, M_MRSAS);
- return(retcode);
-}
-
-/**
- * mrsas_alloc_tmp_dcmd: Allocates memory for temporary command
- * input: Adapter soft state
- * Temp command
- * Size of alloction
+static int
+mrsas_get_map_info(struct mrsas_softc *sc)
+{
+ uint8_t retcode = 0;
+
+ sc->fast_path_io = 0;
+ if (!mrsas_get_ld_map_info(sc)) {
+ retcode = MR_ValidateMapInfo(sc);
+ if (retcode == 0) {
+ sc->fast_path_io = 1;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * mrsas_get_ld_map_info: Get FW's ld_map structure input:
+ * Adapter instance soft state
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD list
+ * structure.
+ */
+static int
+mrsas_get_ld_map_info(struct mrsas_softc *sc)
+{
+ int retcode = 0;
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_dcmd_frame *dcmd;
+ void *map;
+ bus_addr_t map_phys_addr = 0;
+
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev,
+ "Cannot alloc for ld map info cmd.\n");
+ return 1;
+ }
+ dcmd = &cmd->frame->dcmd;
+
+ map = (void *)sc->raidmap_mem[(sc->map_id & 1)];
+ map_phys_addr = sc->raidmap_phys_addr[(sc->map_id & 1)];
+ if (!map) {
+ device_printf(sc->mrsas_dev,
+ "Failed to alloc mem for ld map info.\n");
+ mrsas_release_mfi_cmd(cmd);
+ return (ENOMEM);
+ }
+ memset(map, 0, sizeof(sc->max_map_sz));
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = sc->current_map_sz;
+ dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
+ dcmd->sgl.sge32[0].phys_addr = map_phys_addr;
+ dcmd->sgl.sge32[0].length = sc->current_map_sz;
+
+ if (!mrsas_issue_polled(sc, cmd))
+ retcode = 0;
+ else {
+ device_printf(sc->mrsas_dev,
+ "Fail to send get LD map info cmd.\n");
+ retcode = 1;
+ }
+ mrsas_release_mfi_cmd(cmd);
+
+ return (retcode);
+}
+
+/*
+ * mrsas_sync_map_info: Get FW's ld_map structure input:
+ * Adapter instance soft state
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD list
+ * structure.
+ */
+static int
+mrsas_sync_map_info(struct mrsas_softc *sc)
+{
+ int retcode = 0, i;
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_dcmd_frame *dcmd;
+ uint32_t size_sync_info, num_lds;
+ MR_LD_TARGET_SYNC *target_map = NULL;
+ MR_DRV_RAID_MAP_ALL *map;
+ MR_LD_RAID *raid;
+ MR_LD_TARGET_SYNC *ld_sync;
+ bus_addr_t map_phys_addr = 0;
+
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev,
+ "Cannot alloc for sync map info cmd\n");
+ return 1;
+ }
+ map = sc->ld_drv_map[sc->map_id & 1];
+ num_lds = map->raidMap.ldCount;
+
+ dcmd = &cmd->frame->dcmd;
+ size_sync_info = sizeof(MR_LD_TARGET_SYNC) * num_lds;
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ target_map = (MR_LD_TARGET_SYNC *) sc->raidmap_mem[(sc->map_id - 1) & 1];
+ memset(target_map, 0, sc->max_map_sz);
+
+ map_phys_addr = sc->raidmap_phys_addr[(sc->map_id - 1) & 1];
+
+ ld_sync = (MR_LD_TARGET_SYNC *) target_map;
+
+ for (i = 0; i < num_lds; i++, ld_sync++) {
+ raid = MR_LdRaidGet(i, map);
+ ld_sync->targetId = MR_GetLDTgtId(i, map);
+ ld_sync->seqNum = raid->seqNum;
+ }
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_WRITE;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = sc->current_map_sz;
+ dcmd->mbox.b[0] = num_lds;
+ dcmd->mbox.b[1] = MRSAS_DCMD_MBOX_PEND_FLAG;
+ dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO;
+ dcmd->sgl.sge32[0].phys_addr = map_phys_addr;
+ dcmd->sgl.sge32[0].length = sc->current_map_sz;
+
+ sc->map_update_cmd = cmd;
+ if (mrsas_issue_dcmd(sc, cmd)) {
+ device_printf(sc->mrsas_dev,
+ "Fail to send sync map info command.\n");
+ return (1);
+ }
+ return (retcode);
+}
+
+/*
+ * mrsas_get_pd_list: Returns FW's PD list structure input:
+ * Adapter soft state
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD list
+ * structure. This information is mainly used to find out about system
+ * supported by Firmware.
+ */
+static int
+mrsas_get_pd_list(struct mrsas_softc *sc)
+{
+ int retcode = 0, pd_index = 0, pd_count = 0, pd_list_size;
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_dcmd_frame *dcmd;
+ struct MR_PD_LIST *pd_list_mem;
+ struct MR_PD_ADDRESS *pd_addr;
+ bus_addr_t pd_list_phys_addr = 0;
+ struct mrsas_tmp_dcmd *tcmd;
+
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev,
+ "Cannot alloc for get PD list cmd\n");
+ return 1;
+ }
+ dcmd = &cmd->frame->dcmd;
+
+ tcmd = malloc(sizeof(struct mrsas_tmp_dcmd), M_MRSAS, M_NOWAIT);
+ pd_list_size = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST);
+ if (mrsas_alloc_tmp_dcmd(sc, tcmd, pd_list_size) != SUCCESS) {
+ device_printf(sc->mrsas_dev,
+ "Cannot alloc dmamap for get PD list cmd\n");
+ mrsas_release_mfi_cmd(cmd);
+ return (ENOMEM);
+ } else {
+ pd_list_mem = tcmd->tmp_dcmd_mem;
+ pd_list_phys_addr = tcmd->tmp_dcmd_phys_addr;
+ }
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
+ dcmd->mbox.b[1] = 0;
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->pad_0 = 0;
+ dcmd->data_xfer_len = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST);
+ dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
+ dcmd->sgl.sge32[0].phys_addr = pd_list_phys_addr;
+ dcmd->sgl.sge32[0].length = MRSAS_MAX_PD * sizeof(struct MR_PD_LIST);
+
+ if (!mrsas_issue_polled(sc, cmd))
+ retcode = 0;
+ else
+ retcode = 1;
+
+ /* Get the instance PD list */
+ pd_count = MRSAS_MAX_PD;
+ pd_addr = pd_list_mem->addr;
+ if (retcode == 0 && pd_list_mem->count < pd_count) {
+ memset(sc->local_pd_list, 0,
+ MRSAS_MAX_PD * sizeof(struct mrsas_pd_list));
+ for (pd_index = 0; pd_index < pd_list_mem->count; pd_index++) {
+ sc->local_pd_list[pd_addr->deviceId].tid = pd_addr->deviceId;
+ sc->local_pd_list[pd_addr->deviceId].driveType =
+ pd_addr->scsiDevType;
+ sc->local_pd_list[pd_addr->deviceId].driveState =
+ MR_PD_STATE_SYSTEM;
+ pd_addr++;
+ }
+ }
+ /*
+ * Use mutext/spinlock if pd_list component size increase more than
+ * 32 bit.
+ */
+ memcpy(sc->pd_list, sc->local_pd_list, sizeof(sc->local_pd_list));
+ mrsas_free_tmp_dcmd(tcmd);
+ mrsas_release_mfi_cmd(cmd);
+ free(tcmd, M_MRSAS);
+ return (retcode);
+}
+
+/*
+ * mrsas_get_ld_list: Returns FW's LD list structure input:
+ * Adapter soft state
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD list
+ * structure. This information is mainly used to find out about supported by
+ * the FW.
+ */
+static int
+mrsas_get_ld_list(struct mrsas_softc *sc)
+{
+ int ld_list_size, retcode = 0, ld_index = 0, ids = 0;
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_dcmd_frame *dcmd;
+ struct MR_LD_LIST *ld_list_mem;
+ bus_addr_t ld_list_phys_addr = 0;
+ struct mrsas_tmp_dcmd *tcmd;
+
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev,
+ "Cannot alloc for get LD list cmd\n");
+ return 1;
+ }
+ dcmd = &cmd->frame->dcmd;
+
+ tcmd = malloc(sizeof(struct mrsas_tmp_dcmd), M_MRSAS, M_NOWAIT);
+ ld_list_size = sizeof(struct MR_LD_LIST);
+ if (mrsas_alloc_tmp_dcmd(sc, tcmd, ld_list_size) != SUCCESS) {
+ device_printf(sc->mrsas_dev,
+ "Cannot alloc dmamap for get LD list cmd\n");
+ mrsas_release_mfi_cmd(cmd);
+ return (ENOMEM);
+ } else {
+ ld_list_mem = tcmd->tmp_dcmd_mem;
+ ld_list_phys_addr = tcmd->tmp_dcmd_phys_addr;
+ }
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ if (sc->max256vdSupport)
+ dcmd->mbox.b[0] = 1;
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->data_xfer_len = sizeof(struct MR_LD_LIST);
+ dcmd->opcode = MR_DCMD_LD_GET_LIST;
+ dcmd->sgl.sge32[0].phys_addr = ld_list_phys_addr;
+ dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
+ dcmd->pad_0 = 0;
+
+ if (!mrsas_issue_polled(sc, cmd))
+ retcode = 0;
+ else
+ retcode = 1;
+
+#if VD_EXT_DEBUG
+ printf("Number of LDs %d\n", ld_list_mem->ldCount);
+#endif
+
+ /* Get the instance LD list */
+ if ((retcode == 0) &&
+ (ld_list_mem->ldCount <= sc->fw_supported_vd_count)) {
+ sc->CurLdCount = ld_list_mem->ldCount;
+ memset(sc->ld_ids, 0xff, MAX_LOGICAL_DRIVES_EXT);
+ for (ld_index = 0; ld_index < ld_list_mem->ldCount; ld_index++) {
+ if (ld_list_mem->ldList[ld_index].state != 0) {
+ ids = ld_list_mem->ldList[ld_index].ref.ld_context.targetId;
+ sc->ld_ids[ids] = ld_list_mem->ldList[ld_index].ref.ld_context.targetId;
+ }
+ }
+ }
+ mrsas_free_tmp_dcmd(tcmd);
+ mrsas_release_mfi_cmd(cmd);
+ free(tcmd, M_MRSAS);
+ return (retcode);
+}
+
+/*
+ * mrsas_alloc_tmp_dcmd: Allocates memory for temporary command input:
+ * Adapter soft state Temp command Size of alloction
*
* Allocates DMAable memory for a temporary internal command. The allocated
- * memory is initialized to all zeros upon successful loading of the dma
+ * memory is initialized to all zeros upon successful loading of the dma
* mapped memory.
*/
-int mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc, struct mrsas_tmp_dcmd *tcmd,
- int size)
-{
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- size, // maxsize
- 1, // msegments
- size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &tcmd->tmp_dcmd_tag)) {
- device_printf(sc->mrsas_dev, "Cannot allocate tmp dcmd tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(tcmd->tmp_dcmd_tag, (void **)&tcmd->tmp_dcmd_mem,
- BUS_DMA_NOWAIT, &tcmd->tmp_dcmd_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot allocate tmp dcmd mem\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(tcmd->tmp_dcmd_tag, tcmd->tmp_dcmd_dmamap,
- tcmd->tmp_dcmd_mem, size, mrsas_addr_cb,
- &tcmd->tmp_dcmd_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load tmp dcmd mem\n");
- return (ENOMEM);
- }
-
- memset(tcmd->tmp_dcmd_mem, 0, size);
- return (0);
-}
-
-/**
- * mrsas_free_tmp_dcmd: Free memory for temporary command
- * input: temporary dcmd pointer
- *
- * Deallocates memory of the temporary command for use in the construction
- * of the internal DCMD.
- */
-void mrsas_free_tmp_dcmd(struct mrsas_tmp_dcmd *tmp)
-{
- if (tmp->tmp_dcmd_phys_addr)
- bus_dmamap_unload(tmp->tmp_dcmd_tag, tmp->tmp_dcmd_dmamap);
- if (tmp->tmp_dcmd_mem != NULL)
- bus_dmamem_free(tmp->tmp_dcmd_tag, tmp->tmp_dcmd_mem, tmp->tmp_dcmd_dmamap);
- if (tmp->tmp_dcmd_tag != NULL)
- bus_dma_tag_destroy(tmp->tmp_dcmd_tag);
-}
-
-/**
- * mrsas_issue_blocked_abort_cmd: Aborts previously issued cmd
- * input: Adapter soft state
- * Previously issued cmd to be aborted
- *
- * This function is used to abort previously issued commands, such as AEN and
- * RAID map sync map commands. The abort command is sent as a DCMD internal
- * command and subsequently the driver will wait for a return status. The
- * max wait time is MRSAS_INTERNAL_CMD_WAIT_TIME seconds.
- */
-static int mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc,
- struct mrsas_mfi_cmd *cmd_to_abort)
-{
- struct mrsas_mfi_cmd *cmd;
- struct mrsas_abort_frame *abort_fr;
- u_int8_t retcode = 0;
- unsigned long total_time = 0;
- u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME;
-
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev, "Cannot alloc for abort cmd\n");
- return(1);
- }
-
- abort_fr = &cmd->frame->abort;
-
- /* Prepare and issue the abort frame */
- abort_fr->cmd = MFI_CMD_ABORT;
- abort_fr->cmd_status = 0xFF;
- abort_fr->flags = 0;
- abort_fr->abort_context = cmd_to_abort->index;
- abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
- abort_fr->abort_mfi_phys_addr_hi = 0;
-
- cmd->sync_cmd = 1;
- cmd->cmd_status = 0xFF;
-
- if (mrsas_issue_dcmd(sc, cmd)) {
- device_printf(sc->mrsas_dev, "Fail to send abort command.\n");
- return(1);
- }
-
- /* Wait for this cmd to complete */
- sc->chan = (void*)&cmd;
- while (1) {
- if (cmd->cmd_status == 0xFF){
- tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz);
- }
- else
- break;
- total_time++;
- if (total_time >= max_wait) {
- device_printf(sc->mrsas_dev, "Abort cmd timed out after %d sec.\n", max_wait);
- retcode = 1;
- break;
- }
- }
-
- cmd->sync_cmd = 0;
- mrsas_release_mfi_cmd(cmd);
- return(retcode);
-}
-
-/**
- * mrsas_complete_abort: Completes aborting a command
- * input: Adapter soft state
- * Cmd that was issued to abort another cmd
- *
- * The mrsas_issue_blocked_abort_cmd() function waits for the command status
- * to change after sending the command. This function is called from
+int
+mrsas_alloc_tmp_dcmd(struct mrsas_softc *sc,
+ struct mrsas_tmp_dcmd *tcmd, int size)
+{
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ size,
+ 1,
+ size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &tcmd->tmp_dcmd_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate tmp dcmd tag\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamem_alloc(tcmd->tmp_dcmd_tag, (void **)&tcmd->tmp_dcmd_mem,
+ BUS_DMA_NOWAIT, &tcmd->tmp_dcmd_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate tmp dcmd mem\n");
+ return (ENOMEM);
+ }
+ if (bus_dmamap_load(tcmd->tmp_dcmd_tag, tcmd->tmp_dcmd_dmamap,
+ tcmd->tmp_dcmd_mem, size, mrsas_addr_cb,
+ &tcmd->tmp_dcmd_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load tmp dcmd mem\n");
+ return (ENOMEM);
+ }
+ memset(tcmd->tmp_dcmd_mem, 0, size);
+ return (0);
+}
+
+/*
+ * mrsas_free_tmp_dcmd: Free memory for temporary command input:
+ * temporary dcmd pointer
+ *
+ * Deallocates memory of the temporary command for use in the construction of
+ * the internal DCMD.
+ */
+void
+mrsas_free_tmp_dcmd(struct mrsas_tmp_dcmd *tmp)
+{
+ if (tmp->tmp_dcmd_phys_addr)
+ bus_dmamap_unload(tmp->tmp_dcmd_tag, tmp->tmp_dcmd_dmamap);
+ if (tmp->tmp_dcmd_mem != NULL)
+ bus_dmamem_free(tmp->tmp_dcmd_tag, tmp->tmp_dcmd_mem, tmp->tmp_dcmd_dmamap);
+ if (tmp->tmp_dcmd_tag != NULL)
+ bus_dma_tag_destroy(tmp->tmp_dcmd_tag);
+}
+
+/*
+ * mrsas_issue_blocked_abort_cmd: Aborts previously issued cmd input:
+ * Adapter soft state Previously issued cmd to be aborted
+ *
+ * This function is used to abort previously issued commands, such as AEN and
+ * RAID map sync map commands. The abort command is sent as a DCMD internal
+ * command and subsequently the driver will wait for a return status. The
+ * max wait time is MRSAS_INTERNAL_CMD_WAIT_TIME seconds.
+ */
+static int
+mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc,
+ struct mrsas_mfi_cmd *cmd_to_abort)
+{
+ struct mrsas_mfi_cmd *cmd;
+ struct mrsas_abort_frame *abort_fr;
+ u_int8_t retcode = 0;
+ unsigned long total_time = 0;
+ u_int8_t max_wait = MRSAS_INTERNAL_CMD_WAIT_TIME;
+
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev, "Cannot alloc for abort cmd\n");
+ return (1);
+ }
+ abort_fr = &cmd->frame->abort;
+
+ /* Prepare and issue the abort frame */
+ abort_fr->cmd = MFI_CMD_ABORT;
+ abort_fr->cmd_status = 0xFF;
+ abort_fr->flags = 0;
+ abort_fr->abort_context = cmd_to_abort->index;
+ abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr;
+ abort_fr->abort_mfi_phys_addr_hi = 0;
+
+ cmd->sync_cmd = 1;
+ cmd->cmd_status = 0xFF;
+
+ if (mrsas_issue_dcmd(sc, cmd)) {
+ device_printf(sc->mrsas_dev, "Fail to send abort command.\n");
+ return (1);
+ }
+ /* Wait for this cmd to complete */
+ sc->chan = (void *)&cmd;
+ while (1) {
+ if (cmd->cmd_status == 0xFF) {
+ tsleep((void *)&sc->chan, 0, "mrsas_sleep", hz);
+ } else
+ break;
+ total_time++;
+ if (total_time >= max_wait) {
+ device_printf(sc->mrsas_dev, "Abort cmd timed out after %d sec.\n", max_wait);
+ retcode = 1;
+ break;
+ }
+ }
+
+ cmd->sync_cmd = 0;
+ mrsas_release_mfi_cmd(cmd);
+ return (retcode);
+}
+
+/*
+ * mrsas_complete_abort: Completes aborting a command input:
+ * Adapter soft state Cmd that was issued to abort another cmd
+ *
+ * The mrsas_issue_blocked_abort_cmd() function waits for the command status to
+ * change after sending the command. This function is called from
* mrsas_complete_mptmfi_passthru() to wake up the sleep thread associated.
*/
-void mrsas_complete_abort(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
+void
+mrsas_complete_abort(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
- if (cmd->sync_cmd) {
- cmd->sync_cmd = 0;
- cmd->cmd_status = 0;
- sc->chan = (void*)&cmd;
- wakeup_one((void *)&sc->chan);
- }
- return;
+ if (cmd->sync_cmd) {
+ cmd->sync_cmd = 0;
+ cmd->cmd_status = 0;
+ sc->chan = (void *)&cmd;
+ wakeup_one((void *)&sc->chan);
+ }
+ return;
}
-/**
- * mrsas_aen_handler: Callback function for AEN processing from thread context.
- * input: Adapter soft state
+/*
+ * mrsas_aen_handler: AEN processing callback function from thread context
+ * input: Adapter soft state
*
+ * Asynchronous event handler
*/
-void mrsas_aen_handler(struct mrsas_softc *sc)
+void
+mrsas_aen_handler(struct mrsas_softc *sc)
{
union mrsas_evt_class_locale class_locale;
- int doscan = 0;
+ int doscan = 0;
u_int32_t seq_num;
int error;
@@ -3553,38 +3912,37 @@ void mrsas_aen_handler(struct mrsas_softc *sc)
device_printf(sc->mrsas_dev, "invalid instance!\n");
return;
}
-
if (sc->evt_detail_mem) {
switch (sc->evt_detail_mem->code) {
- case MR_EVT_PD_INSERTED:
- mrsas_get_pd_list(sc);
- mrsas_bus_scan_sim(sc, sc->sim_1);
- doscan = 0;
- break;
- case MR_EVT_PD_REMOVED:
- mrsas_get_pd_list(sc);
- mrsas_bus_scan_sim(sc, sc->sim_1);
- doscan = 0;
- break;
- case MR_EVT_LD_OFFLINE:
- case MR_EVT_CFG_CLEARED:
- case MR_EVT_LD_DELETED:
- mrsas_bus_scan_sim(sc, sc->sim_0);
- doscan = 0;
- break;
- case MR_EVT_LD_CREATED:
- mrsas_get_ld_list(sc);
- mrsas_bus_scan_sim(sc, sc->sim_0);
- doscan = 0;
- break;
- case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
- case MR_EVT_FOREIGN_CFG_IMPORTED:
- case MR_EVT_LD_STATE_CHANGE:
- doscan = 1;
- break;
- default:
- doscan = 0;
- break;
+ case MR_EVT_PD_INSERTED:
+ mrsas_get_pd_list(sc);
+ mrsas_bus_scan_sim(sc, sc->sim_1);
+ doscan = 0;
+ break;
+ case MR_EVT_PD_REMOVED:
+ mrsas_get_pd_list(sc);
+ mrsas_bus_scan_sim(sc, sc->sim_1);
+ doscan = 0;
+ break;
+ case MR_EVT_LD_OFFLINE:
+ case MR_EVT_CFG_CLEARED:
+ case MR_EVT_LD_DELETED:
+ mrsas_bus_scan_sim(sc, sc->sim_0);
+ doscan = 0;
+ break;
+ case MR_EVT_LD_CREATED:
+ mrsas_get_ld_list(sc);
+ mrsas_bus_scan_sim(sc, sc->sim_0);
+ doscan = 0;
+ break;
+ case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
+ case MR_EVT_FOREIGN_CFG_IMPORTED:
+ case MR_EVT_LD_STATE_CHANGE:
+ doscan = 1;
+ break;
+ default:
+ doscan = 0;
+ break;
}
} else {
device_printf(sc->mrsas_dev, "invalid evt_detail\n");
@@ -3598,20 +3956,19 @@ void mrsas_aen_handler(struct mrsas_softc *sc)
mrsas_dprint(sc, MRSAS_AEN, "scanning ...sim 0\n");
mrsas_bus_scan_sim(sc, sc->sim_0);
}
-
seq_num = sc->evt_detail_mem->seq_num + 1;
- // Register AEN with FW for latest sequence number plus 1
+ /* Register AEN with FW for latest sequence number plus 1 */
class_locale.members.reserved = 0;
class_locale.members.locale = MR_EVT_LOCALE_ALL;
class_locale.members.class = MR_EVT_CLASS_DEBUG;
-
- if (sc->aen_cmd != NULL )
- return ;
+
+ if (sc->aen_cmd != NULL)
+ return;
mtx_lock(&sc->aen_lock);
error = mrsas_register_aen(sc, seq_num,
- class_locale.word);
+ class_locale.word);
mtx_unlock(&sc->aen_lock);
if (error)
@@ -3620,24 +3977,29 @@ void mrsas_aen_handler(struct mrsas_softc *sc)
}
-/**
- * mrsas_complete_aen: Completes AEN command
- * input: Adapter soft state
- * Cmd that was issued to abort another cmd
+/*
+ * mrsas_complete_aen: Completes AEN command
+ * input: Adapter soft state
+ * Cmd that was issued to abort another cmd
*
- * This function will be called from ISR and will continue
- * event processing from thread context by enqueuing task
- * in ev_tq (callback function "mrsas_aen_handler").
+ * This function will be called from ISR and will continue event processing from
+ * thread context by enqueuing task in ev_tq (callback function
+ * "mrsas_aen_handler").
*/
-void mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
+void
+mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
/*
- * Don't signal app if it is just an aborted previously registered aen
- */
+ * Don't signal app if it is just an aborted previously registered
+ * aen
+ */
if ((!cmd->abort_aen) && (sc->remove_in_progress == 0)) {
- /* TO DO (?) */
- }
- else
+ sc->mrsas_aen_triggered = 1;
+ if (sc->mrsas_poll_waiting) {
+ sc->mrsas_poll_waiting = 0;
+ selwakeup(&sc->mrsas_select);
+ }
+ } else
cmd->abort_aen = 0;
sc->aen_cmd = NULL;
@@ -3650,23 +4012,23 @@ void mrsas_complete_aen(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
}
static device_method_t mrsas_methods[] = {
- DEVMETHOD(device_probe, mrsas_probe),
- DEVMETHOD(device_attach, mrsas_attach),
- DEVMETHOD(device_detach, mrsas_detach),
- DEVMETHOD(device_suspend, mrsas_suspend),
- DEVMETHOD(device_resume, mrsas_resume),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
- { 0, 0 }
+ DEVMETHOD(device_probe, mrsas_probe),
+ DEVMETHOD(device_attach, mrsas_attach),
+ DEVMETHOD(device_detach, mrsas_detach),
+ DEVMETHOD(device_suspend, mrsas_suspend),
+ DEVMETHOD(device_resume, mrsas_resume),
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ {0, 0}
};
static driver_t mrsas_driver = {
- "mrsas",
- mrsas_methods,
- sizeof(struct mrsas_softc)
+ "mrsas",
+ mrsas_methods,
+ sizeof(struct mrsas_softc)
};
-static devclass_t mrsas_devclass;
-DRIVER_MODULE(mrsas, pci, mrsas_driver, mrsas_devclass, 0, 0);
-MODULE_DEPEND(mrsas, cam, 1,1,1);
+static devclass_t mrsas_devclass;
+DRIVER_MODULE(mrsas, pci, mrsas_driver, mrsas_devclass, 0, 0);
+MODULE_DEPEND(mrsas, cam, 1, 1, 1);
diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h
index af43daa..87f73a9 100644
--- a/sys/dev/mrsas/mrsas.h
+++ b/sys/dev/mrsas/mrsas.h
@@ -1,43 +1,38 @@
/*
- * Copyright (c) 2014, LSI Corp.
- * All rights reserved.
- * Authors: Marian Choy
+ * Copyright (c) 2014, LSI Corp. All rights reserved. Authors: Marian Choy
* Support: freebsdraid@lsi.com
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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 <ORGANIZATION> nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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
+ * <ORGANIZATION> 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 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 HOLDER 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
+ * 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 HOLDER 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.
*
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing
* official policies,either expressed or implied, of the FreeBSD Project.
*
- * Send feedback to: <megaraidfbsd@lsi.com>
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: MegaRaid FreeBSD
+ * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621
+ * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
*
*/
@@ -45,92 +40,103 @@
__FBSDID("$FreeBSD$");
#ifndef MRSAS_H
-#define MRSAS_H
+#define MRSAS_H
-#include <sys/param.h> /* defines used in kernel.h */
+#include <sys/param.h> /* defines used in kernel.h */
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/errno.h>
-#include <sys/kernel.h> /* types used in module initialization */
-#include <sys/conf.h> /* cdevsw struct */
-#include <sys/uio.h> /* uio struct */
+#include <sys/kernel.h> /* types used in module initialization */
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/uio.h> /* uio struct */
#include <sys/malloc.h>
-#include <sys/bus.h> /* structs, prototypes for pci bus stuff */
-
-#include <machine/bus.h>
+#include <sys/bus.h> /* structs, prototypes for pci bus
+ * stuff */
#include <sys/rman.h>
-#include <machine/resource.h>
-#include <machine/atomic.h>
-
-#include <dev/pci/pcivar.h> /* For pci_get macros! */
-#include <dev/pci/pcireg.h>
-
#include <sys/types.h>
+#include <sys/lock.h>
+#include <sys/sema.h>
#include <sys/sysctl.h>
#include <sys/stat.h>
#include <sys/taskqueue.h>
#include <sys/poll.h>
#include <sys/selinfo.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/atomic.h>
+
+#include <dev/pci/pcivar.h> /* For pci_get macros! */
+#include <dev/pci/pcireg.h>
+
+
+#define IOCTL_SEMA_DESCRIPTION "mrsas semaphore for MFI pool"
+
/*
* Device IDs and PCI
*/
-#define MRSAS_TBOLT 0x005b
-#define MRSAS_INVADER 0x005d
-#define MRSAS_FURY 0x005f
-#define MRSAS_PCI_BAR0 0x10
-#define MRSAS_PCI_BAR1 0x14
-#define MRSAS_PCI_BAR2 0x1C
+#define MRSAS_TBOLT 0x005b
+#define MRSAS_INVADER 0x005d
+#define MRSAS_FURY 0x005f
+#define MRSAS_PCI_BAR0 0x10
+#define MRSAS_PCI_BAR1 0x14
+#define MRSAS_PCI_BAR2 0x1C
/*
- * Firmware State Defines
+ * Firmware State Defines
*/
-#define MRSAS_FWSTATE_MAXCMD_MASK 0x0000FFFF
-#define MRSAS_FWSTATE_SGE_MASK 0x00FF0000
-#define MRSAS_FW_STATE_CHNG_INTERRUPT 1
+#define MRSAS_FWSTATE_MAXCMD_MASK 0x0000FFFF
+#define MRSAS_FWSTATE_SGE_MASK 0x00FF0000
+#define MRSAS_FW_STATE_CHNG_INTERRUPT 1
/*
* Message Frame Defines
*/
-#define MRSAS_SENSE_LEN 96
-#define MRSAS_FUSION_MAX_RESET_TRIES 3
+#define MRSAS_SENSE_LEN 96
+#define MRSAS_FUSION_MAX_RESET_TRIES 3
+
+/*
+ * Miscellaneous Defines
+ */
+#define BYTE_ALIGNMENT 1
+#define MRSAS_MAX_NAME_LENGTH 32
+#define MRSAS_VERSION "06.705.10.01-fbsd"
+#define MRSAS_ULONG_MAX 0xFFFFFFFFFFFFFFFF
+#define MRSAS_DEFAULT_TIMEOUT 0x14 /* Temporarily set */
+#define DONE 0
+#define MRSAS_PAGE_SIZE 4096
+#define MRSAS_RESET_NOTICE_INTERVAL 5
+#define MRSAS_IO_TIMEOUT 180000 /* 180 second timeout */
+#define MRSAS_LDIO_QUEUE_DEPTH 70 /* 70 percent as default */
+#define THRESHOLD_REPLY_COUNT 50
+#define MAX_MSIX_COUNT 128
/*
- * Miscellaneous Defines
+ * Boolean types
*/
-#define BYTE_ALIGNMENT 1
-#define MRSAS_MAX_NAME_LENGTH 32
-#define MRSAS_VERSION "06.704.01.01-fbsd"
-#define MRSAS_ULONG_MAX 0xFFFFFFFFFFFFFFFF
-#define MRSAS_DEFAULT_TIMEOUT 0x14 //temp
-#define DONE 0
-#define MRSAS_PAGE_SIZE 4096
-#define MRSAS_RESET_NOTICE_INTERVAL 5
-#define MRSAS_IO_TIMEOUT 180000 /* 180 second timeout */
-#define MRSAS_LDIO_QUEUE_DEPTH 70 /* 70 percent as default */
-#define THRESHOLD_REPLY_COUNT 50
-
-/*
- Boolean types
-*/
#if (__FreeBSD_version < 901000)
- typedef enum _boolean { false, true } boolean;
+typedef enum _boolean {
+ false, true
+} boolean;
+
#endif
-enum err { SUCCESS, FAIL };
+enum err {
+ SUCCESS, FAIL
+};
MALLOC_DECLARE(M_MRSAS);
SYSCTL_DECL(_hw_mrsas);
-#define MRSAS_INFO (1 << 0)
-#define MRSAS_TRACE (1 << 1)
-#define MRSAS_FAULT (1 << 2)
-#define MRSAS_OCR (1 << 3)
-#define MRSAS_TOUT MRSAS_OCR
-#define MRSAS_AEN (1 << 4)
-#define MRSAS_PRL11 (1 << 5)
+#define MRSAS_INFO (1 << 0)
+#define MRSAS_TRACE (1 << 1)
+#define MRSAS_FAULT (1 << 2)
+#define MRSAS_OCR (1 << 3)
+#define MRSAS_TOUT MRSAS_OCR
+#define MRSAS_AEN (1 << 4)
+#define MRSAS_PRL11 (1 << 5)
-#define mrsas_dprint(sc, level, msg, args...) \
+#define mrsas_dprint(sc, level, msg, args...) \
do { \
if (sc->mrsas_debug & level) \
device_printf(sc->mrsas_dev, msg, ##args); \
@@ -143,75 +149,75 @@ do { \
****************************************************************************/
typedef struct _RAID_CONTEXT {
- u_int8_t Type:4; // 0x00
- u_int8_t nseg:4; // 0x00
- u_int8_t resvd0; // 0x01
- u_int16_t timeoutValue; // 0x02 -0x03
- u_int8_t regLockFlags; // 0x04
- u_int8_t resvd1; // 0x05
- u_int16_t VirtualDiskTgtId; // 0x06 -0x07
- u_int64_t regLockRowLBA; // 0x08 - 0x0F
- u_int32_t regLockLength; // 0x10 - 0x13
- u_int16_t nextLMId; // 0x14 - 0x15
- u_int8_t exStatus; // 0x16
- u_int8_t status; // 0x17 status
- u_int8_t RAIDFlags; // 0x18 resvd[7:6],ioSubType[5:4],resvd[3:1],preferredCpu[0]
- u_int8_t numSGE; // 0x19 numSge; not including chain entries
- u_int16_t configSeqNum; // 0x1A -0x1B
- u_int8_t spanArm; // 0x1C span[7:5], arm[4:0]
- u_int8_t resvd2[3]; // 0x1D-0x1f
-} RAID_CONTEXT;
+ u_int8_t Type:4;
+ u_int8_t nseg:4;
+ u_int8_t resvd0;
+ u_int16_t timeoutValue;
+ u_int8_t regLockFlags;
+ u_int8_t resvd1;
+ u_int16_t VirtualDiskTgtId;
+ u_int64_t regLockRowLBA;
+ u_int32_t regLockLength;
+ u_int16_t nextLMId;
+ u_int8_t exStatus;
+ u_int8_t status;
+ u_int8_t RAIDFlags;
+ u_int8_t numSGE;
+ u_int16_t configSeqNum;
+ u_int8_t spanArm;
+ u_int8_t resvd2[3];
+} RAID_CONTEXT;
/*************************************************************************
* MPI2 Defines
************************************************************************/
-#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */
-#define MPI2_WHOINIT_HOST_DRIVER (0x04)
-#define MPI2_VERSION_MAJOR (0x02)
-#define MPI2_VERSION_MINOR (0x00)
-#define MPI2_VERSION_MAJOR_MASK (0xFF00)
-#define MPI2_VERSION_MAJOR_SHIFT (8)
-#define MPI2_VERSION_MINOR_MASK (0x00FF)
-#define MPI2_VERSION_MINOR_SHIFT (0)
-#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
+#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */
+#define MPI2_WHOINIT_HOST_DRIVER (0x04)
+#define MPI2_VERSION_MAJOR (0x02)
+#define MPI2_VERSION_MINOR (0x00)
+#define MPI2_VERSION_MAJOR_MASK (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT (8)
+#define MPI2_VERSION_MINOR_MASK (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT (0)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
MPI2_VERSION_MINOR)
-#define MPI2_HEADER_VERSION_UNIT (0x10)
-#define MPI2_HEADER_VERSION_DEV (0x00)
-#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
-#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
-#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF)
-#define MPI2_HEADER_VERSION_DEV_SHIFT (0)
-#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV)
-#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
-#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
-#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
-#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
-#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
-#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
-#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
-#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
-#define MPI2_SCSIIO_CONTROL_READ (0x02000000)
-#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
-#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
-#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
-#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F)
-#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0)
-#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004)
-#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF)
-#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4)
-#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB)
-#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2)
-#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7)
-#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD)
+#define MPI2_HEADER_VERSION_UNIT (0x10)
+#define MPI2_HEADER_VERSION_DEV (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
+#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
+#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
+#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
+#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ (0x02000000)
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F)
+#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0)
+#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004)
+#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF)
+#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4)
+#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB)
+#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2)
+#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7)
+#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD)
#ifndef MPI2_POINTER
-#define MPI2_POINTER *
+#define MPI2_POINTER *
#endif
@@ -219,642 +225,725 @@ typedef struct _RAID_CONTEXT {
* MPI2 Structures
***************************************/
-typedef struct _MPI25_IEEE_SGE_CHAIN64
-{
- u_int64_t Address;
- u_int32_t Length;
- u_int16_t Reserved1;
- u_int8_t NextChainOffset;
- u_int8_t Flags;
-} MPI25_IEEE_SGE_CHAIN64, MPI2_POINTER PTR_MPI25_IEEE_SGE_CHAIN64,
- Mpi25IeeeSgeChain64_t, MPI2_POINTER pMpi25IeeeSgeChain64_t;
-
-typedef struct _MPI2_SGE_SIMPLE_UNION
-{
- u_int32_t FlagsLength;
- union
- {
- u_int32_t Address32;
- u_int64_t Address64;
- } u;
-} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION,
- Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t;
-
-typedef struct
-{
- u_int8_t CDB[20]; /* 0x00 */
- u_int32_t PrimaryReferenceTag; /* 0x14 */
- u_int16_t PrimaryApplicationTag; /* 0x18 */
- u_int16_t PrimaryApplicationTagMask; /* 0x1A */
- u_int32_t TransferLength; /* 0x1C */
-} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32,
- Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t;
-
-typedef struct _MPI2_SGE_CHAIN_UNION
-{
- u_int16_t Length;
- u_int8_t NextChainOffset;
- u_int8_t Flags;
- union
- {
- u_int32_t Address32;
- u_int64_t Address64;
- } u;
-} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION,
- Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t;
-
-typedef struct _MPI2_IEEE_SGE_SIMPLE32
-{
- u_int32_t Address;
- u_int32_t FlagsLength;
-} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32,
- Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t;
-typedef struct _MPI2_IEEE_SGE_SIMPLE64
-{
- u_int64_t Address;
- u_int32_t Length;
- u_int16_t Reserved1;
- u_int8_t Reserved2;
- u_int8_t Flags;
-} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64,
- Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t;
-
-typedef union _MPI2_IEEE_SGE_SIMPLE_UNION
-{
- MPI2_IEEE_SGE_SIMPLE32 Simple32;
- MPI2_IEEE_SGE_SIMPLE64 Simple64;
-} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
- Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t;
-
-typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32;
-typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64;
-
-typedef union _MPI2_IEEE_SGE_CHAIN_UNION
-{
- MPI2_IEEE_SGE_CHAIN32 Chain32;
- MPI2_IEEE_SGE_CHAIN64 Chain64;
-} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION,
- Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t;
+typedef struct _MPI25_IEEE_SGE_CHAIN64 {
+ u_int64_t Address;
+ u_int32_t Length;
+ u_int16_t Reserved1;
+ u_int8_t NextChainOffset;
+ u_int8_t Flags;
+} MPI25_IEEE_SGE_CHAIN64, MPI2_POINTER PTR_MPI25_IEEE_SGE_CHAIN64,
+Mpi25IeeeSgeChain64_t, MPI2_POINTER pMpi25IeeeSgeChain64_t;
+
+typedef struct _MPI2_SGE_SIMPLE_UNION {
+ u_int32_t FlagsLength;
+ union {
+ u_int32_t Address32;
+ u_int64_t Address64;
+ } u;
+} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION,
+Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t;
-typedef union _MPI2_SGE_IO_UNION
-{
- MPI2_SGE_SIMPLE_UNION MpiSimple;
- MPI2_SGE_CHAIN_UNION MpiChain;
- MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
- MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
-} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION,
- Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t;
-
-typedef union
-{
- u_int8_t CDB32[32];
- MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
- MPI2_SGE_SIMPLE_UNION SGE;
-} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION,
- Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t;
+typedef struct {
+ u_int8_t CDB[20]; /* 0x00 */
+ u_int32_t PrimaryReferenceTag; /* 0x14 */
+ u_int16_t PrimaryApplicationTag;/* 0x18 */
+ u_int16_t PrimaryApplicationTagMask; /* 0x1A */
+ u_int32_t TransferLength; /* 0x1C */
+} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32,
+Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t;
+
+typedef struct _MPI2_SGE_CHAIN_UNION {
+ u_int16_t Length;
+ u_int8_t NextChainOffset;
+ u_int8_t Flags;
+ union {
+ u_int32_t Address32;
+ u_int64_t Address64;
+ } u;
+} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION,
+Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t;
+
+typedef struct _MPI2_IEEE_SGE_SIMPLE32 {
+ u_int32_t Address;
+ u_int32_t FlagsLength;
+} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32,
+Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t;
+typedef struct _MPI2_IEEE_SGE_SIMPLE64 {
+ u_int64_t Address;
+ u_int32_t Length;
+ u_int16_t Reserved1;
+ u_int8_t Reserved2;
+ u_int8_t Flags;
+} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64,
+Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t;
+
+typedef union _MPI2_IEEE_SGE_SIMPLE_UNION {
+ MPI2_IEEE_SGE_SIMPLE32 Simple32;
+ MPI2_IEEE_SGE_SIMPLE64 Simple64;
+} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
+Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t;
+
+typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32;
+typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64;
+
+typedef union _MPI2_IEEE_SGE_CHAIN_UNION {
+ MPI2_IEEE_SGE_CHAIN32 Chain32;
+ MPI2_IEEE_SGE_CHAIN64 Chain64;
+} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION,
+Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t;
+
+typedef union _MPI2_SGE_IO_UNION {
+ MPI2_SGE_SIMPLE_UNION MpiSimple;
+ MPI2_SGE_CHAIN_UNION MpiChain;
+ MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
+ MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
+} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION,
+Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t;
+
+typedef union {
+ u_int8_t CDB32[32];
+ MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+ MPI2_SGE_SIMPLE_UNION SGE;
+} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION,
+Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t;
/*
- * RAID SCSI IO Request Message
- * Total SGE count will be one less than _MPI2_SCSI_IO_REQUEST
+ * RAID SCSI IO Request Message Total SGE count will be one less than
+ * _MPI2_SCSI_IO_REQUEST
*/
-typedef struct _MPI2_RAID_SCSI_IO_REQUEST
-{
- u_int16_t DevHandle; /* 0x00 */
- u_int8_t ChainOffset; /* 0x02 */
- u_int8_t Function; /* 0x03 */
- u_int16_t Reserved1; /* 0x04 */
- u_int8_t Reserved2; /* 0x06 */
- u_int8_t MsgFlags; /* 0x07 */
- u_int8_t VP_ID; /* 0x08 */
- u_int8_t VF_ID; /* 0x09 */
- u_int16_t Reserved3; /* 0x0A */
- u_int32_t SenseBufferLowAddress; /* 0x0C */
- u_int16_t SGLFlags; /* 0x10 */
- u_int8_t SenseBufferLength; /* 0x12 */
- u_int8_t Reserved4; /* 0x13 */
- u_int8_t SGLOffset0; /* 0x14 */
- u_int8_t SGLOffset1; /* 0x15 */
- u_int8_t SGLOffset2; /* 0x16 */
- u_int8_t SGLOffset3; /* 0x17 */
- u_int32_t SkipCount; /* 0x18 */
- u_int32_t DataLength; /* 0x1C */
- u_int32_t BidirectionalDataLength; /* 0x20 */
- u_int16_t IoFlags; /* 0x24 */
- u_int16_t EEDPFlags; /* 0x26 */
- u_int32_t EEDPBlockSize; /* 0x28 */
- u_int32_t SecondaryReferenceTag; /* 0x2C */
- u_int16_t SecondaryApplicationTag; /* 0x30 */
- u_int16_t ApplicationTagTranslationMask; /* 0x32 */
- u_int8_t LUN[8]; /* 0x34 */
- u_int32_t Control; /* 0x3C */
- MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
- RAID_CONTEXT RaidContext; /* 0x60 */
- MPI2_SGE_IO_UNION SGL; /* 0x80 */
-} MRSAS_RAID_SCSI_IO_REQUEST, MPI2_POINTER PTR_MRSAS_RAID_SCSI_IO_REQUEST,
- MRSASRaidSCSIIORequest_t, MPI2_POINTER pMRSASRaidSCSIIORequest_t;
+typedef struct _MPI2_RAID_SCSI_IO_REQUEST {
+ u_int16_t DevHandle; /* 0x00 */
+ u_int8_t ChainOffset; /* 0x02 */
+ u_int8_t Function; /* 0x03 */
+ u_int16_t Reserved1; /* 0x04 */
+ u_int8_t Reserved2; /* 0x06 */
+ u_int8_t MsgFlags; /* 0x07 */
+ u_int8_t VP_ID; /* 0x08 */
+ u_int8_t VF_ID; /* 0x09 */
+ u_int16_t Reserved3; /* 0x0A */
+ u_int32_t SenseBufferLowAddress;/* 0x0C */
+ u_int16_t SGLFlags; /* 0x10 */
+ u_int8_t SenseBufferLength; /* 0x12 */
+ u_int8_t Reserved4; /* 0x13 */
+ u_int8_t SGLOffset0; /* 0x14 */
+ u_int8_t SGLOffset1; /* 0x15 */
+ u_int8_t SGLOffset2; /* 0x16 */
+ u_int8_t SGLOffset3; /* 0x17 */
+ u_int32_t SkipCount; /* 0x18 */
+ u_int32_t DataLength; /* 0x1C */
+ u_int32_t BidirectionalDataLength; /* 0x20 */
+ u_int16_t IoFlags; /* 0x24 */
+ u_int16_t EEDPFlags; /* 0x26 */
+ u_int32_t EEDPBlockSize; /* 0x28 */
+ u_int32_t SecondaryReferenceTag;/* 0x2C */
+ u_int16_t SecondaryApplicationTag; /* 0x30 */
+ u_int16_t ApplicationTagTranslationMask; /* 0x32 */
+ u_int8_t LUN[8]; /* 0x34 */
+ u_int32_t Control; /* 0x3C */
+ MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
+ RAID_CONTEXT RaidContext; /* 0x60 */
+ MPI2_SGE_IO_UNION SGL; /* 0x80 */
+} MRSAS_RAID_SCSI_IO_REQUEST, MPI2_POINTER PTR_MRSAS_RAID_SCSI_IO_REQUEST,
+MRSASRaidSCSIIORequest_t, MPI2_POINTER pMRSASRaidSCSIIORequest_t;
/*
* MPT RAID MFA IO Descriptor.
*/
typedef struct _MRSAS_RAID_MFA_IO_DESCRIPTOR {
- u_int32_t RequestFlags : 8;
- u_int32_t MessageAddress1 : 24; /* bits 31:8*/
- u_int32_t MessageAddress2; /* bits 61:32 */
-} MRSAS_RAID_MFA_IO_REQUEST_DESCRIPTOR,*PMRSAS_RAID_MFA_IO_REQUEST_DESCRIPTOR;
+ u_int32_t RequestFlags:8;
+ u_int32_t MessageAddress1:24; /* bits 31:8 */
+ u_int32_t MessageAddress2; /* bits 61:32 */
+} MRSAS_RAID_MFA_IO_REQUEST_DESCRIPTOR, *PMRSAS_RAID_MFA_IO_REQUEST_DESCRIPTOR;
/* Default Request Descriptor */
-typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
-{
- u_int8_t RequestFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int16_t LMID; /* 0x04 */
- u_int16_t DescriptorTypeDependent; /* 0x06 */
-} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
- Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t;
-
+typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR {
+ u_int8_t RequestFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int16_t LMID; /* 0x04 */
+ u_int16_t DescriptorTypeDependent; /* 0x06 */
+} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t;
+
/* High Priority Request Descriptor */
-typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
-{
- u_int8_t RequestFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int16_t LMID; /* 0x04 */
- u_int16_t Reserved1; /* 0x06 */
-} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
- Mpi2HighPriorityRequestDescriptor_t,
- MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t;
-
+typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR {
+ u_int8_t RequestFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int16_t LMID; /* 0x04 */
+ u_int16_t Reserved1; /* 0x06 */
+} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+Mpi2HighPriorityRequestDescriptor_t, MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t;
+
/* SCSI IO Request Descriptor */
-typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
-{
- u_int8_t RequestFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int16_t LMID; /* 0x04 */
- u_int16_t DevHandle; /* 0x06 */
-} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
- Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t;
+typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR {
+ u_int8_t RequestFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int16_t LMID; /* 0x04 */
+ u_int16_t DevHandle; /* 0x06 */
+} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t;
/* SCSI Target Request Descriptor */
-typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
-{
- u_int8_t RequestFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int16_t LMID; /* 0x04 */
- u_int16_t IoIndex; /* 0x06 */
-} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
- Mpi2SCSITargetRequestDescriptor_t,
- MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t;
+typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR {
+ u_int8_t RequestFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int16_t LMID; /* 0x04 */
+ u_int16_t IoIndex; /* 0x06 */
+} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+Mpi2SCSITargetRequestDescriptor_t, MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t;
/* RAID Accelerator Request Descriptor */
-typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR
-{
- u_int8_t RequestFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int16_t LMID; /* 0x04 */
- u_int16_t Reserved; /* 0x06 */
-} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
- Mpi2RAIDAcceleratorRequestDescriptor_t,
- MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t;
+typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
+ u_int8_t RequestFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int16_t LMID; /* 0x04 */
+ u_int16_t Reserved; /* 0x06 */
+} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
+Mpi2RAIDAcceleratorRequestDescriptor_t, MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t;
/* union of Request Descriptors */
-typedef union _MRSAS_REQUEST_DESCRIPTOR_UNION
-{
- MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
- MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
- MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
- MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
- MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
- MRSAS_RAID_MFA_IO_REQUEST_DESCRIPTOR MFAIo;
- union {
- struct {
- u_int32_t low;
- u_int32_t high;
- } u;
- u_int64_t Words;
- } addr;
-} MRSAS_REQUEST_DESCRIPTOR_UNION;
+typedef union _MRSAS_REQUEST_DESCRIPTOR_UNION {
+ MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
+ MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
+ MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
+ MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
+ MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
+ MRSAS_RAID_MFA_IO_REQUEST_DESCRIPTOR MFAIo;
+ union {
+ struct {
+ u_int32_t low;
+ u_int32_t high;
+ } u;
+ u_int64_t Words;
+ } addr;
+} MRSAS_REQUEST_DESCRIPTOR_UNION;
/* Default Reply Descriptor */
-typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
-{
- u_int8_t ReplyFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t DescriptorTypeDependent1; /* 0x02 */
- u_int32_t DescriptorTypeDependent2; /* 0x04 */
-} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
- Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t;
+typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR {
+ u_int8_t ReplyFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t DescriptorTypeDependent1; /* 0x02 */
+ u_int32_t DescriptorTypeDependent2; /* 0x04 */
+} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
+Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t;
/* Address Reply Descriptor */
-typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
-{
- u_int8_t ReplyFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int32_t ReplyFrameAddress; /* 0x04 */
-} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
- Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t;
+typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR {
+ u_int8_t ReplyFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int32_t ReplyFrameAddress; /* 0x04 */
+} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
+Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t;
/* SCSI IO Success Reply Descriptor */
-typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
-{
- u_int8_t ReplyFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int16_t TaskTag; /* 0x04 */
- u_int16_t Reserved1; /* 0x06 */
-} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
- Mpi2SCSIIOSuccessReplyDescriptor_t,
- MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t;
+typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR {
+ u_int8_t ReplyFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int16_t TaskTag; /* 0x04 */
+ u_int16_t Reserved1; /* 0x06 */
+} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+Mpi2SCSIIOSuccessReplyDescriptor_t, MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t;
/* TargetAssist Success Reply Descriptor */
-typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
-{
- u_int8_t ReplyFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int8_t SequenceNumber; /* 0x04 */
- u_int8_t Reserved1; /* 0x05 */
- u_int16_t IoIndex; /* 0x06 */
-} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
- Mpi2TargetAssistSuccessReplyDescriptor_t,
- MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t;
+typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR {
+ u_int8_t ReplyFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int8_t SequenceNumber; /* 0x04 */
+ u_int8_t Reserved1; /* 0x05 */
+ u_int16_t IoIndex; /* 0x06 */
+} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+Mpi2TargetAssistSuccessReplyDescriptor_t, MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t;
/* Target Command Buffer Reply Descriptor */
-typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
-{
- u_int8_t ReplyFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int8_t VP_ID; /* 0x02 */
- u_int8_t Flags; /* 0x03 */
- u_int16_t InitiatorDevHandle; /* 0x04 */
- u_int16_t IoIndex; /* 0x06 */
-} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
- Mpi2TargetCommandBufferReplyDescriptor_t,
- MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t;
+typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR {
+ u_int8_t ReplyFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int8_t VP_ID; /* 0x02 */
+ u_int8_t Flags; /* 0x03 */
+ u_int16_t InitiatorDevHandle; /* 0x04 */
+ u_int16_t IoIndex; /* 0x06 */
+} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+Mpi2TargetCommandBufferReplyDescriptor_t, MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t;
/* RAID Accelerator Success Reply Descriptor */
-typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR
-{
- u_int8_t ReplyFlags; /* 0x00 */
- u_int8_t MSIxIndex; /* 0x01 */
- u_int16_t SMID; /* 0x02 */
- u_int32_t Reserved; /* 0x04 */
-} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
- MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
- Mpi2RAIDAcceleratorSuccessReplyDescriptor_t,
- MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t;
+typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
+ u_int8_t ReplyFlags; /* 0x00 */
+ u_int8_t MSIxIndex; /* 0x01 */
+ u_int16_t SMID; /* 0x02 */
+ u_int32_t Reserved; /* 0x04 */
+} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+
+ MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
+Mpi2RAIDAcceleratorSuccessReplyDescriptor_t, MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t;
/* union of Reply Descriptors */
-typedef union _MPI2_REPLY_DESCRIPTORS_UNION
-{
- MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
- MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
- MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
- MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
- MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
- MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
- u_int64_t Words;
-} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
- Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
+typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
+ MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
+ MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
+ MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
+ MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
+ MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
+ MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
+ u_int64_t Words;
+} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
+Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
typedef struct {
- volatile unsigned int val;
+ volatile unsigned int val;
} atomic_t;
-#define atomic_read(v) atomic_load_acq_int(&(v)->val)
-#define atomic_set(v,i) atomic_store_rel_int(&(v)->val, i)
-#define atomic_dec(v) atomic_fetchadd_int(&(v)->val, -1)
-#define atomic_inc(v) atomic_fetchadd_int(&(v)->val, 1)
+#define atomic_read(v) atomic_load_acq_int(&(v)->val)
+#define atomic_set(v,i) atomic_store_rel_int(&(v)->val, i)
+#define atomic_dec(v) atomic_fetchadd_int(&(v)->val, -1)
+#define atomic_inc(v) atomic_fetchadd_int(&(v)->val, 1)
/* IOCInit Request message */
-typedef struct _MPI2_IOC_INIT_REQUEST
-{
- u_int8_t WhoInit; /* 0x00 */
- u_int8_t Reserved1; /* 0x01 */
- u_int8_t ChainOffset; /* 0x02 */
- u_int8_t Function; /* 0x03 */
- u_int16_t Reserved2; /* 0x04 */
- u_int8_t Reserved3; /* 0x06 */
- u_int8_t MsgFlags; /* 0x07 */
- u_int8_t VP_ID; /* 0x08 */
- u_int8_t VF_ID; /* 0x09 */
- u_int16_t Reserved4; /* 0x0A */
- u_int16_t MsgVersion; /* 0x0C */
- u_int16_t HeaderVersion; /* 0x0E */
- u_int32_t Reserved5; /* 0x10 */
- u_int16_t Reserved6; /* 0x14 */
- u_int8_t Reserved7; /* 0x16 */
- u_int8_t HostMSIxVectors; /* 0x17 */
- u_int16_t Reserved8; /* 0x18 */
- u_int16_t SystemRequestFrameSize; /* 0x1A */
- u_int16_t ReplyDescriptorPostQueueDepth; /* 0x1C */
- u_int16_t ReplyFreeQueueDepth; /* 0x1E */
- u_int32_t SenseBufferAddressHigh; /* 0x20 */
- u_int32_t SystemReplyAddressHigh; /* 0x24 */
- u_int64_t SystemRequestFrameBaseAddress; /* 0x28 */
- u_int64_t ReplyDescriptorPostQueueAddress;/* 0x30 */
- u_int64_t ReplyFreeQueueAddress; /* 0x38 */
- u_int64_t TimeStamp; /* 0x40 */
-} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST,
- Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t;
+typedef struct _MPI2_IOC_INIT_REQUEST {
+ u_int8_t WhoInit; /* 0x00 */
+ u_int8_t Reserved1; /* 0x01 */
+ u_int8_t ChainOffset; /* 0x02 */
+ u_int8_t Function; /* 0x03 */
+ u_int16_t Reserved2; /* 0x04 */
+ u_int8_t Reserved3; /* 0x06 */
+ u_int8_t MsgFlags; /* 0x07 */
+ u_int8_t VP_ID; /* 0x08 */
+ u_int8_t VF_ID; /* 0x09 */
+ u_int16_t Reserved4; /* 0x0A */
+ u_int16_t MsgVersion; /* 0x0C */
+ u_int16_t HeaderVersion; /* 0x0E */
+ u_int32_t Reserved5; /* 0x10 */
+ u_int16_t Reserved6; /* 0x14 */
+ u_int8_t Reserved7; /* 0x16 */
+ u_int8_t HostMSIxVectors; /* 0x17 */
+ u_int16_t Reserved8; /* 0x18 */
+ u_int16_t SystemRequestFrameSize; /* 0x1A */
+ u_int16_t ReplyDescriptorPostQueueDepth; /* 0x1C */
+ u_int16_t ReplyFreeQueueDepth; /* 0x1E */
+ u_int32_t SenseBufferAddressHigh; /* 0x20 */
+ u_int32_t SystemReplyAddressHigh; /* 0x24 */
+ u_int64_t SystemRequestFrameBaseAddress; /* 0x28 */
+ u_int64_t ReplyDescriptorPostQueueAddress; /* 0x30 */
+ u_int64_t ReplyFreeQueueAddress;/* 0x38 */
+ u_int64_t TimeStamp; /* 0x40 */
+} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST,
+Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t;
/*
* MR private defines
*/
-#define MR_PD_INVALID 0xFFFF
-#define MAX_SPAN_DEPTH 8
-#define MAX_QUAD_DEPTH MAX_SPAN_DEPTH
-#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
-#define MAX_ROW_SIZE 32
-#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
-#define MAX_LOGICAL_DRIVES 64
-#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
-#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
-#define MAX_ARRAYS 128
-#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
-#define MAX_PHYSICAL_DEVICES 256
-#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
-#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 // get the mapping information of this LD
-
-
-/*******************************************************************
- * RAID map related structures
+#define MR_PD_INVALID 0xFFFF
+#define MAX_SPAN_DEPTH 8
+#define MAX_QUAD_DEPTH MAX_SPAN_DEPTH
+#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
+#define MAX_ROW_SIZE 32
+#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
+#define MAX_LOGICAL_DRIVES 64
+#define MAX_LOGICAL_DRIVES_EXT 256
+
+#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
+#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
+
+#define MAX_ARRAYS 128
+#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
+
+#define MAX_ARRAYS_EXT 256
+#define MAX_API_ARRAYS_EXT MAX_ARRAYS_EXT
+
+#define MAX_PHYSICAL_DEVICES 256
+#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
+#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101
+
+
+#define MRSAS_MAX_PD_CHANNELS 1
+#define MRSAS_MAX_LD_CHANNELS 1
+#define MRSAS_MAX_DEV_PER_CHANNEL 256
+#define MRSAS_DEFAULT_INIT_ID -1
+#define MRSAS_MAX_LUN 8
+#define MRSAS_DEFAULT_CMD_PER_LUN 256
+#define MRSAS_MAX_PD (MRSAS_MAX_PD_CHANNELS * \
+ MRSAS_MAX_DEV_PER_CHANNEL)
+#define MRSAS_MAX_LD_IDS (MRSAS_MAX_LD_CHANNELS * \
+ MRSAS_MAX_DEV_PER_CHANNEL)
+
+
+#define VD_EXT_DEBUG 0
+
+
+/*******************************************************************
+ * RAID map related structures
********************************************************************/
-
+#pragma pack(1)
typedef struct _MR_DEV_HANDLE_INFO {
- u_int16_t curDevHdl; // the device handle currently used by fw to issue the command.
- u_int8_t validHandles; // bitmap of valid device handles.
- u_int8_t reserved;
- u_int16_t devHandle[2]; // 0x04 dev handles for all the paths.
-} MR_DEV_HANDLE_INFO;
-
+ u_int16_t curDevHdl;
+ u_int8_t validHandles;
+ u_int8_t reserved;
+ u_int16_t devHandle[2];
+} MR_DEV_HANDLE_INFO;
+
+#pragma pack()
+
typedef struct _MR_ARRAY_INFO {
- u_int16_t pd[MAX_RAIDMAP_ROW_SIZE];
-} MR_ARRAY_INFO; // 0x40, Total Size
-
+ u_int16_t pd[MAX_RAIDMAP_ROW_SIZE];
+} MR_ARRAY_INFO;
+
typedef struct _MR_QUAD_ELEMENT {
- u_int64_t logStart; // 0x00
- u_int64_t logEnd; // 0x08
- u_int64_t offsetInSpan; // 0x10
- u_int32_t diff; // 0x18
- u_int32_t reserved1; // 0x1C
-} MR_QUAD_ELEMENT; // 0x20, Total size
-
+ u_int64_t logStart;
+ u_int64_t logEnd;
+ u_int64_t offsetInSpan;
+ u_int32_t diff;
+ u_int32_t reserved1;
+} MR_QUAD_ELEMENT;
+
typedef struct _MR_SPAN_INFO {
- u_int32_t noElements; // 0x00
- u_int32_t reserved1; // 0x04
- MR_QUAD_ELEMENT quad[MAX_RAIDMAP_SPAN_DEPTH]; // 0x08
-} MR_SPAN_INFO; // 0x108, Total size
-
-typedef struct _MR_LD_SPAN_ { // SPAN structure
- u_int64_t startBlk; // 0x00, starting block number in array
- u_int64_t numBlks; // 0x08, number of blocks
- u_int16_t arrayRef; // 0x10, array reference
- u_int8_t spanRowSize; // 0x11, span row size
- u_int8_t spanRowDataSize; // 0x12, span row data size
- u_int8_t reserved[4]; // 0x13, reserved
-} MR_LD_SPAN; // 0x18, Total Size
+ u_int32_t noElements;
+ u_int32_t reserved1;
+ MR_QUAD_ELEMENT quad[MAX_RAIDMAP_SPAN_DEPTH];
+} MR_SPAN_INFO;
+
+typedef struct _MR_LD_SPAN_ {
+ u_int64_t startBlk;
+ u_int64_t numBlks;
+ u_int16_t arrayRef;
+ u_int8_t spanRowSize;
+ u_int8_t spanRowDataSize;
+ u_int8_t reserved[4];
+} MR_LD_SPAN;
typedef struct _MR_SPAN_BLOCK_INFO {
- u_int64_t num_rows; // number of rows/span
- MR_LD_SPAN span; // 0x08
- MR_SPAN_INFO block_span_info; // 0x20
-} MR_SPAN_BLOCK_INFO;
+ u_int64_t num_rows;
+ MR_LD_SPAN span;
+ MR_SPAN_INFO block_span_info;
+} MR_SPAN_BLOCK_INFO;
typedef struct _MR_LD_RAID {
- struct {
- u_int32_t fpCapable :1;
- u_int32_t reserved5 :3;
- u_int32_t ldPiMode :4;
- u_int32_t pdPiMode :4; // Every Pd has to be same.
- u_int32_t encryptionType :8; // FDE or ctlr encryption (MR_LD_ENCRYPTION_TYPE)
- u_int32_t fpWriteCapable :1;
- u_int32_t fpReadCapable :1;
- u_int32_t fpWriteAcrossStripe :1;
- u_int32_t fpReadAcrossStripe :1;
- u_int32_t fpNonRWCapable :1; // TRUE if supporting Non RW IO
- u_int32_t reserved4 :7;
- } capability; // 0x00
- u_int32_t reserved6;
- u_int64_t size; // 0x08, LD size in blocks
-
- u_int8_t spanDepth; // 0x10, Total Number of Spans
- u_int8_t level; // 0x11, RAID level
- u_int8_t stripeShift; // 0x12, shift-count to get stripe size (0=512, 1=1K, 7=64K, etc.)
- u_int8_t rowSize; // 0x13, number of disks in a row
-
- u_int8_t rowDataSize; // 0x14, number of data disks in a row
- u_int8_t writeMode; // 0x15, WRITE_THROUGH or WRITE_BACK
- u_int8_t PRL; // 0x16, To differentiate between RAID1 and RAID1E
- u_int8_t SRL; // 0x17
-
- u_int16_t targetId; // 0x18, ld Target Id.
- u_int8_t ldState; // 0x1a, state of ld, state corresponds to MR_LD_STATE
- u_int8_t regTypeReqOnWrite;// 0x1b, Pre calculate region type requests based on MFC etc..
- u_int8_t modFactor; // 0x1c, same as rowSize,
- u_int8_t regTypeReqOnRead; // 0x1d, region lock type used for read, valid only if regTypeOnReadIsValid=1
- u_int16_t seqNum; // 0x1e, LD sequence number
-
- struct {
- u_int32_t ldSyncRequired:1; // This LD requires sync command before completing
- u_int32_t regTypeReqOnReadLsValid:1; // Qualifier for regTypeOnRead
- u_int32_t reserved:30;
- } flags; // 0x20
-
- u_int8_t LUN[8]; // 0x24, 8 byte LUN field used for SCSI
- u_int8_t fpIoTimeoutForLd; // 0x2C, timeout value for FP IOs
- u_int8_t reserved2[3]; // 0x2D
- u_int32_t logicalBlockLength; // 0x30 Logical block size for the LD
- struct {
- u_int32_t LdPiExp:4; // 0x34, P_I_EXPONENT for ReadCap 16
- u_int32_t LdLogicalBlockExp:4; // 0x34, LOGICAL BLOCKS PER PHYS BLOCK
- u_int32_t reserved1:24; // 0x34
- } exponent;
- u_int8_t reserved3[0x80-0x38]; // 0x38
-} MR_LD_RAID; // 0x80, Total Size
+ struct {
+ u_int32_t fpCapable:1;
+ u_int32_t reserved5:3;
+ u_int32_t ldPiMode:4;
+ u_int32_t pdPiMode:4;
+ u_int32_t encryptionType:8;
+ u_int32_t fpWriteCapable:1;
+ u_int32_t fpReadCapable:1;
+ u_int32_t fpWriteAcrossStripe:1;
+ u_int32_t fpReadAcrossStripe:1;
+ u_int32_t fpNonRWCapable:1;
+ u_int32_t reserved4:7;
+ } capability;
+ u_int32_t reserved6;
+ u_int64_t size;
+
+ u_int8_t spanDepth;
+ u_int8_t level;
+ u_int8_t stripeShift;
+ u_int8_t rowSize;
+
+ u_int8_t rowDataSize;
+ u_int8_t writeMode;
+ u_int8_t PRL;
+ u_int8_t SRL;
+
+ u_int16_t targetId;
+ u_int8_t ldState;
+ u_int8_t regTypeReqOnWrite;
+ u_int8_t modFactor;
+ u_int8_t regTypeReqOnRead;
+ u_int16_t seqNum;
+
+ struct {
+ u_int32_t ldSyncRequired:1;
+ u_int32_t regTypeReqOnReadLsValid:1;
+ u_int32_t reserved:30;
+ } flags;
+
+ u_int8_t LUN[8];
+ u_int8_t fpIoTimeoutForLd;
+ u_int8_t reserved2[3];
+ u_int32_t logicalBlockLength;
+ struct {
+ u_int32_t LdPiExp:4;
+ u_int32_t LdLogicalBlockExp:4;
+ u_int32_t reserved1:24;
+ } exponent;
+ u_int8_t reserved3[0x80 - 0x38];
+} MR_LD_RAID;
typedef struct _MR_LD_SPAN_MAP {
- MR_LD_RAID ldRaid; // 0x00
- u_int8_t dataArmMap[MAX_RAIDMAP_ROW_SIZE]; // 0x80, needed for GET_ARM() - R0/1/5 only.
- MR_SPAN_BLOCK_INFO spanBlock[MAX_RAIDMAP_SPAN_DEPTH]; // 0xA0
-} MR_LD_SPAN_MAP; // 0x9E0
+ MR_LD_RAID ldRaid;
+ u_int8_t dataArmMap[MAX_RAIDMAP_ROW_SIZE];
+ MR_SPAN_BLOCK_INFO spanBlock[MAX_RAIDMAP_SPAN_DEPTH];
+} MR_LD_SPAN_MAP;
typedef struct _MR_FW_RAID_MAP {
- u_int32_t totalSize; // total size of this structure, including this field.
- union {
- struct { // Simple method of version checking variables
- u_int32_t maxLd;
- u_int32_t maxSpanDepth;
- u_int32_t maxRowSize;
- u_int32_t maxPdCount;
- u_int32_t maxArrays;
- } validationInfo;
- u_int32_t version[5];
- u_int32_t reserved1[5];
- } raid_desc;
- u_int32_t ldCount; // count of lds.
- u_int32_t Reserved1;
- u_int8_t ldTgtIdToLd[MAX_RAIDMAP_LOGICAL_DRIVES+MAX_RAIDMAP_VIEWS]; // 0x20
- // This doesn't correspond to
- // FW Ld Tgt Id to LD, but will purge. For example: if tgt Id is 4
- // and FW LD is 2, and there is only one LD, FW will populate the
- // array like this. [0xFF, 0xFF, 0xFF, 0xFF, 0x0,.....]. This is to
- // help reduce the entire strcture size if there are few LDs or
- // driver is looking info for 1 LD only.
- u_int8_t fpPdIoTimeoutSec; // timeout value used by driver in FP IOs
- u_int8_t reserved2[7];
- MR_ARRAY_INFO arMapInfo[MAX_RAIDMAP_ARRAYS]; // 0x00a8
- MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES]; // 0x20a8
- MR_LD_SPAN_MAP ldSpanMap[1]; // 0x28a8-[0-MAX_RAIDMAP_LOGICAL_DRIVES+MAX_RAIDMAP_VIEWS+1];
-} MR_FW_RAID_MAP; // 0x3288, Total Size
-
-typedef struct _LD_LOAD_BALANCE_INFO
-{
- u_int8_t loadBalanceFlag;
- u_int8_t reserved1;
- u_int16_t raid1DevHandle[2];
- atomic_t scsi_pending_cmds[2];
- u_int64_t last_accessed_block[2];
-} LD_LOAD_BALANCE_INFO, *PLD_LOAD_BALANCE_INFO;
+ u_int32_t totalSize;
+ union {
+ struct {
+ u_int32_t maxLd;
+ u_int32_t maxSpanDepth;
+ u_int32_t maxRowSize;
+ u_int32_t maxPdCount;
+ u_int32_t maxArrays;
+ } validationInfo;
+ u_int32_t version[5];
+ u_int32_t reserved1[5];
+ } raid_desc;
+ u_int32_t ldCount;
+ u_int32_t Reserved1;
+
+ /*
+ * This doesn't correspond to FW Ld Tgt Id to LD, but will purge. For
+ * example: if tgt Id is 4 and FW LD is 2, and there is only one LD,
+ * FW will populate the array like this. [0xFF, 0xFF, 0xFF, 0xFF,
+ * 0x0,.....]. This is to help reduce the entire strcture size if
+ * there are few LDs or driver is looking info for 1 LD only.
+ */
+ u_int8_t ldTgtIdToLd[MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS];
+ u_int8_t fpPdIoTimeoutSec;
+ u_int8_t reserved2[7];
+ MR_ARRAY_INFO arMapInfo[MAX_RAIDMAP_ARRAYS];
+ MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
+ MR_LD_SPAN_MAP ldSpanMap[1];
+} MR_FW_RAID_MAP;
+
+
+typedef struct _MR_FW_RAID_MAP_EXT {
+ /* Not used in new map */
+ u_int32_t reserved;
+
+ union {
+ struct {
+ u_int32_t maxLd;
+ u_int32_t maxSpanDepth;
+ u_int32_t maxRowSize;
+ u_int32_t maxPdCount;
+ u_int32_t maxArrays;
+ } validationInfo;
+ u_int32_t version[5];
+ u_int32_t reserved1[5];
+ } fw_raid_desc;
+
+ u_int8_t fpPdIoTimeoutSec;
+ u_int8_t reserved2[7];
+
+ u_int16_t ldCount;
+ u_int16_t arCount;
+ u_int16_t spanCount;
+ u_int16_t reserve3;
+
+ MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
+ u_int8_t ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT];
+ MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_EXT];
+ MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT];
+} MR_FW_RAID_MAP_EXT;
+
+
+typedef struct _MR_DRV_RAID_MAP {
+ /*
+ * Total size of this structure, including this field. This feild
+ * will be manupulated by driver for ext raid map, else pick the
+ * value from firmware raid map.
+ */
+ u_int32_t totalSize;
+
+ union {
+ struct {
+ u_int32_t maxLd;
+ u_int32_t maxSpanDepth;
+ u_int32_t maxRowSize;
+ u_int32_t maxPdCount;
+ u_int32_t maxArrays;
+ } validationInfo;
+ u_int32_t version[5];
+ u_int32_t reserved1[5];
+ } drv_raid_desc;
+
+ /* timeout value used by driver in FP IOs */
+ u_int8_t fpPdIoTimeoutSec;
+ u_int8_t reserved2[7];
+
+ u_int16_t ldCount;
+ u_int16_t arCount;
+ u_int16_t spanCount;
+ u_int16_t reserve3;
+
+ MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES];
+ u_int8_t ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT];
+ MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_EXT];
+ MR_LD_SPAN_MAP ldSpanMap[1];
+
+} MR_DRV_RAID_MAP;
+
+/*
+ * Driver raid map size is same as raid map ext MR_DRV_RAID_MAP_ALL is
+ * created to sync with old raid. And it is mainly for code re-use purpose.
+ */
+
+#pragma pack(1)
+typedef struct _MR_DRV_RAID_MAP_ALL {
+
+ MR_DRV_RAID_MAP raidMap;
+ MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT - 1];
+} MR_DRV_RAID_MAP_ALL;
+
+#pragma pack()
+
+typedef struct _LD_LOAD_BALANCE_INFO {
+ u_int8_t loadBalanceFlag;
+ u_int8_t reserved1;
+ u_int16_t raid1DevHandle[2];
+ atomic_t scsi_pending_cmds[2];
+ u_int64_t last_accessed_block[2];
+} LD_LOAD_BALANCE_INFO, *PLD_LOAD_BALANCE_INFO;
/* SPAN_SET is info caclulated from span info from Raid map per ld */
typedef struct _LD_SPAN_SET {
- u_int64_t log_start_lba;
- u_int64_t log_end_lba;
- u_int64_t span_row_start;
- u_int64_t span_row_end;
- u_int64_t data_strip_start;
- u_int64_t data_strip_end;
- u_int64_t data_row_start;
- u_int64_t data_row_end;
- u_int8_t strip_offset[MAX_SPAN_DEPTH];
- u_int32_t span_row_data_width;
- u_int32_t diff;
- u_int32_t reserved[2];
-}LD_SPAN_SET, *PLD_SPAN_SET;
+ u_int64_t log_start_lba;
+ u_int64_t log_end_lba;
+ u_int64_t span_row_start;
+ u_int64_t span_row_end;
+ u_int64_t data_strip_start;
+ u_int64_t data_strip_end;
+ u_int64_t data_row_start;
+ u_int64_t data_row_end;
+ u_int8_t strip_offset[MAX_SPAN_DEPTH];
+ u_int32_t span_row_data_width;
+ u_int32_t diff;
+ u_int32_t reserved[2];
+} LD_SPAN_SET, *PLD_SPAN_SET;
typedef struct LOG_BLOCK_SPAN_INFO {
- LD_SPAN_SET span_set[MAX_SPAN_DEPTH];
-}LD_SPAN_INFO, *PLD_SPAN_INFO;
+ LD_SPAN_SET span_set[MAX_SPAN_DEPTH];
+} LD_SPAN_INFO, *PLD_SPAN_INFO;
#pragma pack(1)
typedef struct _MR_FW_RAID_MAP_ALL {
- MR_FW_RAID_MAP raidMap;
- MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
-} MR_FW_RAID_MAP_ALL;
+ MR_FW_RAID_MAP raidMap;
+ MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1];
+} MR_FW_RAID_MAP_ALL;
+
#pragma pack()
struct IO_REQUEST_INFO {
- u_int64_t ldStartBlock;
- u_int32_t numBlocks;
- u_int16_t ldTgtId;
- u_int8_t isRead;
- u_int16_t devHandle;
- u_int64_t pdBlock;
- u_int8_t fpOkForIo;
+ u_int64_t ldStartBlock;
+ u_int32_t numBlocks;
+ u_int16_t ldTgtId;
+ u_int8_t isRead;
+ u_int16_t devHandle;
+ u_int64_t pdBlock;
+ u_int8_t fpOkForIo;
u_int8_t IoforUnevenSpan;
- u_int8_t start_span;
- u_int8_t reserved;
- u_int64_t start_row;
+ u_int8_t start_span;
+ u_int8_t reserved;
+ u_int64_t start_row;
};
typedef struct _MR_LD_TARGET_SYNC {
- u_int8_t targetId;
- u_int8_t reserved;
- u_int16_t seqNum;
-} MR_LD_TARGET_SYNC;
-
-#define IEEE_SGE_FLAGS_ADDR_MASK (0x03)
-#define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
-#define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
-#define IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
-#define IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
-#define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
-#define IEEE_SGE_FLAGS_END_OF_LIST (0x40)
+ u_int8_t targetId;
+ u_int8_t reserved;
+ u_int16_t seqNum;
+} MR_LD_TARGET_SYNC;
+
+#define IEEE_SGE_FLAGS_ADDR_MASK (0x03)
+#define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
+#define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
+#define IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
+#define IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
+#define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
+#define IEEE_SGE_FLAGS_END_OF_LIST (0x40)
union desc_value {
- u_int64_t word;
- struct {
- u_int32_t low;
- u_int32_t high;
- } u;
+ u_int64_t word;
+ struct {
+ u_int32_t low;
+ u_int32_t high;
+ } u;
};
-/*******************************************************************
- * Temporary command
+/*******************************************************************
+ * Temporary command
********************************************************************/
struct mrsas_tmp_dcmd {
- bus_dma_tag_t tmp_dcmd_tag; // tag for tmp DMCD cmd
- bus_dmamap_t tmp_dcmd_dmamap; // dmamap for tmp DCMD cmd
- void *tmp_dcmd_mem; // virtual addr of tmp DCMD cmd
- bus_addr_t tmp_dcmd_phys_addr; //physical addr of tmp DCMD
+ bus_dma_tag_t tmp_dcmd_tag;
+ bus_dmamap_t tmp_dcmd_dmamap;
+ void *tmp_dcmd_mem;
+ bus_addr_t tmp_dcmd_phys_addr;
};
-/*******************************************************************
- * Register set, included legacy controllers 1068 and 1078,
+/*******************************************************************
+ * Register set, included legacy controllers 1068 and 1078,
* structure extended for 1078 registers
- ********************************************************************/
+ *******************************************************************/
#pragma pack(1)
typedef struct _mrsas_register_set {
- u_int32_t doorbell; /*0000h*/
- u_int32_t fusion_seq_offset; /*0004h*/
- u_int32_t fusion_host_diag; /*0008h*/
- u_int32_t reserved_01; /*000Ch*/
+ u_int32_t doorbell; /* 0000h */
+ u_int32_t fusion_seq_offset; /* 0004h */
+ u_int32_t fusion_host_diag; /* 0008h */
+ u_int32_t reserved_01; /* 000Ch */
- u_int32_t inbound_msg_0; /*0010h*/
- u_int32_t inbound_msg_1; /*0014h*/
- u_int32_t outbound_msg_0; /*0018h*/
- u_int32_t outbound_msg_1; /*001Ch*/
+ u_int32_t inbound_msg_0; /* 0010h */
+ u_int32_t inbound_msg_1; /* 0014h */
+ u_int32_t outbound_msg_0; /* 0018h */
+ u_int32_t outbound_msg_1; /* 001Ch */
- u_int32_t inbound_doorbell; /*0020h*/
- u_int32_t inbound_intr_status; /*0024h*/
- u_int32_t inbound_intr_mask; /*0028h*/
+ u_int32_t inbound_doorbell; /* 0020h */
+ u_int32_t inbound_intr_status; /* 0024h */
+ u_int32_t inbound_intr_mask; /* 0028h */
- u_int32_t outbound_doorbell; /*002Ch*/
- u_int32_t outbound_intr_status; /*0030h*/
- u_int32_t outbound_intr_mask; /*0034h*/
+ u_int32_t outbound_doorbell; /* 002Ch */
+ u_int32_t outbound_intr_status; /* 0030h */
+ u_int32_t outbound_intr_mask; /* 0034h */
- u_int32_t reserved_1[2]; /*0038h*/
+ u_int32_t reserved_1[2]; /* 0038h */
- u_int32_t inbound_queue_port; /*0040h*/
- u_int32_t outbound_queue_port; /*0044h*/
+ u_int32_t inbound_queue_port; /* 0040h */
+ u_int32_t outbound_queue_port; /* 0044h */
- u_int32_t reserved_2[9]; /*0048h*/
- u_int32_t reply_post_host_index; /*006Ch*/
- u_int32_t reserved_2_2[12]; /*0070h*/
+ u_int32_t reserved_2[9]; /* 0048h */
+ u_int32_t reply_post_host_index;/* 006Ch */
+ u_int32_t reserved_2_2[12]; /* 0070h */
- u_int32_t outbound_doorbell_clear; /*00A0h*/
+ u_int32_t outbound_doorbell_clear; /* 00A0h */
- u_int32_t reserved_3[3]; /*00A4h*/
+ u_int32_t reserved_3[3]; /* 00A4h */
- u_int32_t outbound_scratch_pad ; /*00B0h*/
- u_int32_t outbound_scratch_pad_2; /*00B4h*/
+ u_int32_t outbound_scratch_pad; /* 00B0h */
+ u_int32_t outbound_scratch_pad_2; /* 00B4h */
- u_int32_t reserved_4[2]; /*00B8h*/
+ u_int32_t reserved_4[2]; /* 00B8h */
- u_int32_t inbound_low_queue_port ; /*00C0h*/
+ u_int32_t inbound_low_queue_port; /* 00C0h */
- u_int32_t inbound_high_queue_port ; /*00C4h*/
+ u_int32_t inbound_high_queue_port; /* 00C4h */
- u_int32_t reserved_5; /*00C8h*/
- u_int32_t res_6[11]; /*CCh*/
- u_int32_t host_diag;
- u_int32_t seq_offset;
- u_int32_t index_registers[807]; /*00CCh*/
+ u_int32_t reserved_5; /* 00C8h */
+ u_int32_t res_6[11]; /* CCh */
+ u_int32_t host_diag;
+ u_int32_t seq_offset;
+ u_int32_t index_registers[807]; /* 00CCh */
+} mrsas_reg_set;
-} mrsas_reg_set;
#pragma pack()
/*******************************************************************
@@ -867,454 +956,437 @@ typedef struct _mrsas_register_set {
/*
* FW posts its state in upper 4 bits of outbound_msg_0 register
*/
-#define MFI_STATE_MASK 0xF0000000
-#define MFI_STATE_UNDEFINED 0x00000000
-#define MFI_STATE_BB_INIT 0x10000000
-#define MFI_STATE_FW_INIT 0x40000000
-#define MFI_STATE_WAIT_HANDSHAKE 0x60000000
-#define MFI_STATE_FW_INIT_2 0x70000000
-#define MFI_STATE_DEVICE_SCAN 0x80000000
-#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000
-#define MFI_STATE_FLUSH_CACHE 0xA0000000
-#define MFI_STATE_READY 0xB0000000
-#define MFI_STATE_OPERATIONAL 0xC0000000
-#define MFI_STATE_FAULT 0xF0000000
-#define MFI_RESET_REQUIRED 0x00000001
-#define MFI_RESET_ADAPTER 0x00000002
-#define MEGAMFI_FRAME_SIZE 64
-#define MRSAS_MFI_FRAME_SIZE 1024
-#define MRSAS_MFI_SENSE_SIZE 128
+#define MFI_STATE_MASK 0xF0000000
+#define MFI_STATE_UNDEFINED 0x00000000
+#define MFI_STATE_BB_INIT 0x10000000
+#define MFI_STATE_FW_INIT 0x40000000
+#define MFI_STATE_WAIT_HANDSHAKE 0x60000000
+#define MFI_STATE_FW_INIT_2 0x70000000
+#define MFI_STATE_DEVICE_SCAN 0x80000000
+#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000
+#define MFI_STATE_FLUSH_CACHE 0xA0000000
+#define MFI_STATE_READY 0xB0000000
+#define MFI_STATE_OPERATIONAL 0xC0000000
+#define MFI_STATE_FAULT 0xF0000000
+#define MFI_RESET_REQUIRED 0x00000001
+#define MFI_RESET_ADAPTER 0x00000002
+#define MEGAMFI_FRAME_SIZE 64
+#define MRSAS_MFI_FRAME_SIZE 1024
+#define MRSAS_MFI_SENSE_SIZE 128
/*
* During FW init, clear pending cmds & reset state using inbound_msg_0
*
- * ABORT : Abort all pending cmds
- * READY : Move from OPERATIONAL to READY state; discard queue info
- * MFIMODE : Discard (possible) low MFA posted in 64-bit mode (??)
- * CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver
- * HOTPLUG : Resume from Hotplug
- * MFI_STOP_ADP : Send signal to FW to stop processing
+ * ABORT : Abort all pending cmds READY : Move from OPERATIONAL to
+ * READY state; discard queue info MFIMODE : Discard (possible) low MFA
+ * posted in 64-bit mode (??) CLR_HANDSHAKE: FW is waiting for HANDSHAKE from
+ * BIOS or Driver HOTPLUG : Resume from Hotplug MFI_STOP_ADP : Send
+ * signal to FW to stop processing
*/
-#define WRITE_SEQUENCE_OFFSET (0x0000000FC) // I20
-#define HOST_DIAGNOSTIC_OFFSET (0x000000F8) // I20
-#define DIAG_WRITE_ENABLE (0x00000080)
-#define DIAG_RESET_ADAPTER (0x00000004)
-
-#define MFI_ADP_RESET 0x00000040
-#define MFI_INIT_ABORT 0x00000001
-#define MFI_INIT_READY 0x00000002
-#define MFI_INIT_MFIMODE 0x00000004
-#define MFI_INIT_CLEAR_HANDSHAKE 0x00000008
-#define MFI_INIT_HOTPLUG 0x00000010
-#define MFI_STOP_ADP 0x00000020
-#define MFI_RESET_FLAGS MFI_INIT_READY| \
- MFI_INIT_MFIMODE| \
- MFI_INIT_ABORT
+#define WRITE_SEQUENCE_OFFSET (0x0000000FC)
+#define HOST_DIAGNOSTIC_OFFSET (0x000000F8)
+#define DIAG_WRITE_ENABLE (0x00000080)
+#define DIAG_RESET_ADAPTER (0x00000004)
+
+#define MFI_ADP_RESET 0x00000040
+#define MFI_INIT_ABORT 0x00000001
+#define MFI_INIT_READY 0x00000002
+#define MFI_INIT_MFIMODE 0x00000004
+#define MFI_INIT_CLEAR_HANDSHAKE 0x00000008
+#define MFI_INIT_HOTPLUG 0x00000010
+#define MFI_STOP_ADP 0x00000020
+#define MFI_RESET_FLAGS MFI_INIT_READY| \
+ MFI_INIT_MFIMODE| \
+ MFI_INIT_ABORT
/*
- * MFI frame flags
+ * MFI frame flags
*/
-#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000
-#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001
-#define MFI_FRAME_SGL32 0x0000
-#define MFI_FRAME_SGL64 0x0002
-#define MFI_FRAME_SENSE32 0x0000
-#define MFI_FRAME_SENSE64 0x0004
-#define MFI_FRAME_DIR_NONE 0x0000
-#define MFI_FRAME_DIR_WRITE 0x0008
-#define MFI_FRAME_DIR_READ 0x0010
-#define MFI_FRAME_DIR_BOTH 0x0018
-#define MFI_FRAME_IEEE 0x0020
+#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000
+#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001
+#define MFI_FRAME_SGL32 0x0000
+#define MFI_FRAME_SGL64 0x0002
+#define MFI_FRAME_SENSE32 0x0000
+#define MFI_FRAME_SENSE64 0x0004
+#define MFI_FRAME_DIR_NONE 0x0000
+#define MFI_FRAME_DIR_WRITE 0x0008
+#define MFI_FRAME_DIR_READ 0x0010
+#define MFI_FRAME_DIR_BOTH 0x0018
+#define MFI_FRAME_IEEE 0x0020
/*
* Definition for cmd_status
*/
-#define MFI_CMD_STATUS_POLL_MODE 0xFF
+#define MFI_CMD_STATUS_POLL_MODE 0xFF
/*
* MFI command opcodes
*/
-#define MFI_CMD_INIT 0x00
-#define MFI_CMD_LD_READ 0x01
-#define MFI_CMD_LD_WRITE 0x02
-#define MFI_CMD_LD_SCSI_IO 0x03
-#define MFI_CMD_PD_SCSI_IO 0x04
-#define MFI_CMD_DCMD 0x05
-#define MFI_CMD_ABORT 0x06
-#define MFI_CMD_SMP 0x07
-#define MFI_CMD_STP 0x08
-#define MFI_CMD_INVALID 0xff
-
-#define MR_DCMD_CTRL_GET_INFO 0x01010000
-#define MR_DCMD_LD_GET_LIST 0x03010000
-#define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000
-#define MR_FLUSH_CTRL_CACHE 0x01
-#define MR_FLUSH_DISK_CACHE 0x02
-
-#define MR_DCMD_CTRL_SHUTDOWN 0x01050000
-#define MR_DCMD_HIBERNATE_SHUTDOWN 0x01060000
-#define MR_ENABLE_DRIVE_SPINDOWN 0x01
-
-#define MR_DCMD_CTRL_EVENT_GET_INFO 0x01040100
-#define MR_DCMD_CTRL_EVENT_GET 0x01040300
-#define MR_DCMD_CTRL_EVENT_WAIT 0x01040500
-#define MR_DCMD_LD_GET_PROPERTIES 0x03030000
-
-#define MR_DCMD_CLUSTER 0x08000000
-#define MR_DCMD_CLUSTER_RESET_ALL 0x08010100
-#define MR_DCMD_CLUSTER_RESET_LD 0x08010200
-#define MR_DCMD_PD_LIST_QUERY 0x02010100
-
-#define MR_DCMD_CTRL_MISC_CPX 0x0100e200
-#define MR_DCMD_CTRL_MISC_CPX_INIT_DATA_GET 0x0100e201
-#define MR_DCMD_CTRL_MISC_CPX_QUEUE_DATA 0x0100e202
-#define MR_DCMD_CTRL_MISC_CPX_UNREGISTER 0x0100e203
-#define MAX_MR_ROW_SIZE 32
-#define MR_CPX_DIR_WRITE 1
-#define MR_CPX_DIR_READ 0
-#define MR_CPX_VERSION 1
-
-#define MR_DCMD_CTRL_IO_METRICS_GET 0x01170200 // get IO metrics
-
-#define MR_EVT_CFG_CLEARED 0x0004
-
-#define MR_EVT_LD_STATE_CHANGE 0x0051
-#define MR_EVT_PD_INSERTED 0x005b
-#define MR_EVT_PD_REMOVED 0x0070
-#define MR_EVT_LD_CREATED 0x008a
-#define MR_EVT_LD_DELETED 0x008b
-#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
-#define MR_EVT_LD_OFFLINE 0x00fc
-#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
-#define MR_EVT_CTRL_PERF_COLLECTION 0x017e
+#define MFI_CMD_INIT 0x00
+#define MFI_CMD_LD_READ 0x01
+#define MFI_CMD_LD_WRITE 0x02
+#define MFI_CMD_LD_SCSI_IO 0x03
+#define MFI_CMD_PD_SCSI_IO 0x04
+#define MFI_CMD_DCMD 0x05
+#define MFI_CMD_ABORT 0x06
+#define MFI_CMD_SMP 0x07
+#define MFI_CMD_STP 0x08
+#define MFI_CMD_INVALID 0xff
+
+#define MR_DCMD_CTRL_GET_INFO 0x01010000
+#define MR_DCMD_LD_GET_LIST 0x03010000
+#define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000
+#define MR_FLUSH_CTRL_CACHE 0x01
+#define MR_FLUSH_DISK_CACHE 0x02
+
+#define MR_DCMD_CTRL_SHUTDOWN 0x01050000
+#define MR_DCMD_HIBERNATE_SHUTDOWN 0x01060000
+#define MR_ENABLE_DRIVE_SPINDOWN 0x01
+
+#define MR_DCMD_CTRL_EVENT_GET_INFO 0x01040100
+#define MR_DCMD_CTRL_EVENT_GET 0x01040300
+#define MR_DCMD_CTRL_EVENT_WAIT 0x01040500
+#define MR_DCMD_LD_GET_PROPERTIES 0x03030000
+
+#define MR_DCMD_CLUSTER 0x08000000
+#define MR_DCMD_CLUSTER_RESET_ALL 0x08010100
+#define MR_DCMD_CLUSTER_RESET_LD 0x08010200
+#define MR_DCMD_PD_LIST_QUERY 0x02010100
+
+#define MR_DCMD_CTRL_MISC_CPX 0x0100e200
+#define MR_DCMD_CTRL_MISC_CPX_INIT_DATA_GET 0x0100e201
+#define MR_DCMD_CTRL_MISC_CPX_QUEUE_DATA 0x0100e202
+#define MR_DCMD_CTRL_MISC_CPX_UNREGISTER 0x0100e203
+#define MAX_MR_ROW_SIZE 32
+#define MR_CPX_DIR_WRITE 1
+#define MR_CPX_DIR_READ 0
+#define MR_CPX_VERSION 1
+
+#define MR_DCMD_CTRL_IO_METRICS_GET 0x01170200
+
+#define MR_EVT_CFG_CLEARED 0x0004
+
+#define MR_EVT_LD_STATE_CHANGE 0x0051
+#define MR_EVT_PD_INSERTED 0x005b
+#define MR_EVT_PD_REMOVED 0x0070
+#define MR_EVT_LD_CREATED 0x008a
+#define MR_EVT_LD_DELETED 0x008b
+#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
+#define MR_EVT_LD_OFFLINE 0x00fc
+#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
+#define MR_EVT_CTRL_PERF_COLLECTION 0x017e
/*
* MFI command completion codes
*/
enum MFI_STAT {
- MFI_STAT_OK = 0x00,
- MFI_STAT_INVALID_CMD = 0x01,
- MFI_STAT_INVALID_DCMD = 0x02,
- MFI_STAT_INVALID_PARAMETER = 0x03,
- MFI_STAT_INVALID_SEQUENCE_NUMBER = 0x04,
- MFI_STAT_ABORT_NOT_POSSIBLE = 0x05,
- MFI_STAT_APP_HOST_CODE_NOT_FOUND = 0x06,
- MFI_STAT_APP_IN_USE = 0x07,
- MFI_STAT_APP_NOT_INITIALIZED = 0x08,
- MFI_STAT_ARRAY_INDEX_INVALID = 0x09,
- MFI_STAT_ARRAY_ROW_NOT_EMPTY = 0x0a,
- MFI_STAT_CONFIG_RESOURCE_CONFLICT = 0x0b,
- MFI_STAT_DEVICE_NOT_FOUND = 0x0c,
- MFI_STAT_DRIVE_TOO_SMALL = 0x0d,
- MFI_STAT_FLASH_ALLOC_FAIL = 0x0e,
- MFI_STAT_FLASH_BUSY = 0x0f,
- MFI_STAT_FLASH_ERROR = 0x10,
- MFI_STAT_FLASH_IMAGE_BAD = 0x11,
- MFI_STAT_FLASH_IMAGE_INCOMPLETE = 0x12,
- MFI_STAT_FLASH_NOT_OPEN = 0x13,
- MFI_STAT_FLASH_NOT_STARTED = 0x14,
- MFI_STAT_FLUSH_FAILED = 0x15,
- MFI_STAT_HOST_CODE_NOT_FOUNT = 0x16,
- MFI_STAT_LD_CC_IN_PROGRESS = 0x17,
- MFI_STAT_LD_INIT_IN_PROGRESS = 0x18,
- MFI_STAT_LD_LBA_OUT_OF_RANGE = 0x19,
- MFI_STAT_LD_MAX_CONFIGURED = 0x1a,
- MFI_STAT_LD_NOT_OPTIMAL = 0x1b,
- MFI_STAT_LD_RBLD_IN_PROGRESS = 0x1c,
- MFI_STAT_LD_RECON_IN_PROGRESS = 0x1d,
- MFI_STAT_LD_WRONG_RAID_LEVEL = 0x1e,
- MFI_STAT_MAX_SPARES_EXCEEDED = 0x1f,
- MFI_STAT_MEMORY_NOT_AVAILABLE = 0x20,
- MFI_STAT_MFC_HW_ERROR = 0x21,
- MFI_STAT_NO_HW_PRESENT = 0x22,
- MFI_STAT_NOT_FOUND = 0x23,
- MFI_STAT_NOT_IN_ENCL = 0x24,
- MFI_STAT_PD_CLEAR_IN_PROGRESS = 0x25,
- MFI_STAT_PD_TYPE_WRONG = 0x26,
- MFI_STAT_PR_DISABLED = 0x27,
- MFI_STAT_ROW_INDEX_INVALID = 0x28,
- MFI_STAT_SAS_CONFIG_INVALID_ACTION = 0x29,
- MFI_STAT_SAS_CONFIG_INVALID_DATA = 0x2a,
- MFI_STAT_SAS_CONFIG_INVALID_PAGE = 0x2b,
- MFI_STAT_SAS_CONFIG_INVALID_TYPE = 0x2c,
- MFI_STAT_SCSI_DONE_WITH_ERROR = 0x2d,
- MFI_STAT_SCSI_IO_FAILED = 0x2e,
- MFI_STAT_SCSI_RESERVATION_CONFLICT = 0x2f,
- MFI_STAT_SHUTDOWN_FAILED = 0x30,
- MFI_STAT_TIME_NOT_SET = 0x31,
- MFI_STAT_WRONG_STATE = 0x32,
- MFI_STAT_LD_OFFLINE = 0x33,
- MFI_STAT_PEER_NOTIFICATION_REJECTED = 0x34,
- MFI_STAT_PEER_NOTIFICATION_FAILED = 0x35,
- MFI_STAT_RESERVATION_IN_PROGRESS = 0x36,
- MFI_STAT_I2C_ERRORS_DETECTED = 0x37,
- MFI_STAT_PCI_ERRORS_DETECTED = 0x38,
- MFI_STAT_CONFIG_SEQ_MISMATCH = 0x67,
-
- MFI_STAT_INVALID_STATUS = 0xFF
+ MFI_STAT_OK = 0x00,
+ MFI_STAT_INVALID_CMD = 0x01,
+ MFI_STAT_INVALID_DCMD = 0x02,
+ MFI_STAT_INVALID_PARAMETER = 0x03,
+ MFI_STAT_INVALID_SEQUENCE_NUMBER = 0x04,
+ MFI_STAT_ABORT_NOT_POSSIBLE = 0x05,
+ MFI_STAT_APP_HOST_CODE_NOT_FOUND = 0x06,
+ MFI_STAT_APP_IN_USE = 0x07,
+ MFI_STAT_APP_NOT_INITIALIZED = 0x08,
+ MFI_STAT_ARRAY_INDEX_INVALID = 0x09,
+ MFI_STAT_ARRAY_ROW_NOT_EMPTY = 0x0a,
+ MFI_STAT_CONFIG_RESOURCE_CONFLICT = 0x0b,
+ MFI_STAT_DEVICE_NOT_FOUND = 0x0c,
+ MFI_STAT_DRIVE_TOO_SMALL = 0x0d,
+ MFI_STAT_FLASH_ALLOC_FAIL = 0x0e,
+ MFI_STAT_FLASH_BUSY = 0x0f,
+ MFI_STAT_FLASH_ERROR = 0x10,
+ MFI_STAT_FLASH_IMAGE_BAD = 0x11,
+ MFI_STAT_FLASH_IMAGE_INCOMPLETE = 0x12,
+ MFI_STAT_FLASH_NOT_OPEN = 0x13,
+ MFI_STAT_FLASH_NOT_STARTED = 0x14,
+ MFI_STAT_FLUSH_FAILED = 0x15,
+ MFI_STAT_HOST_CODE_NOT_FOUNT = 0x16,
+ MFI_STAT_LD_CC_IN_PROGRESS = 0x17,
+ MFI_STAT_LD_INIT_IN_PROGRESS = 0x18,
+ MFI_STAT_LD_LBA_OUT_OF_RANGE = 0x19,
+ MFI_STAT_LD_MAX_CONFIGURED = 0x1a,
+ MFI_STAT_LD_NOT_OPTIMAL = 0x1b,
+ MFI_STAT_LD_RBLD_IN_PROGRESS = 0x1c,
+ MFI_STAT_LD_RECON_IN_PROGRESS = 0x1d,
+ MFI_STAT_LD_WRONG_RAID_LEVEL = 0x1e,
+ MFI_STAT_MAX_SPARES_EXCEEDED = 0x1f,
+ MFI_STAT_MEMORY_NOT_AVAILABLE = 0x20,
+ MFI_STAT_MFC_HW_ERROR = 0x21,
+ MFI_STAT_NO_HW_PRESENT = 0x22,
+ MFI_STAT_NOT_FOUND = 0x23,
+ MFI_STAT_NOT_IN_ENCL = 0x24,
+ MFI_STAT_PD_CLEAR_IN_PROGRESS = 0x25,
+ MFI_STAT_PD_TYPE_WRONG = 0x26,
+ MFI_STAT_PR_DISABLED = 0x27,
+ MFI_STAT_ROW_INDEX_INVALID = 0x28,
+ MFI_STAT_SAS_CONFIG_INVALID_ACTION = 0x29,
+ MFI_STAT_SAS_CONFIG_INVALID_DATA = 0x2a,
+ MFI_STAT_SAS_CONFIG_INVALID_PAGE = 0x2b,
+ MFI_STAT_SAS_CONFIG_INVALID_TYPE = 0x2c,
+ MFI_STAT_SCSI_DONE_WITH_ERROR = 0x2d,
+ MFI_STAT_SCSI_IO_FAILED = 0x2e,
+ MFI_STAT_SCSI_RESERVATION_CONFLICT = 0x2f,
+ MFI_STAT_SHUTDOWN_FAILED = 0x30,
+ MFI_STAT_TIME_NOT_SET = 0x31,
+ MFI_STAT_WRONG_STATE = 0x32,
+ MFI_STAT_LD_OFFLINE = 0x33,
+ MFI_STAT_PEER_NOTIFICATION_REJECTED = 0x34,
+ MFI_STAT_PEER_NOTIFICATION_FAILED = 0x35,
+ MFI_STAT_RESERVATION_IN_PROGRESS = 0x36,
+ MFI_STAT_I2C_ERRORS_DETECTED = 0x37,
+ MFI_STAT_PCI_ERRORS_DETECTED = 0x38,
+ MFI_STAT_CONFIG_SEQ_MISMATCH = 0x67,
+
+ MFI_STAT_INVALID_STATUS = 0xFF
};
/*
* Number of mailbox bytes in DCMD message frame
*/
-#define MFI_MBOX_SIZE 12
+#define MFI_MBOX_SIZE 12
enum MR_EVT_CLASS {
- MR_EVT_CLASS_DEBUG = -2,
- MR_EVT_CLASS_PROGRESS = -1,
- MR_EVT_CLASS_INFO = 0,
- MR_EVT_CLASS_WARNING = 1,
- MR_EVT_CLASS_CRITICAL = 2,
- MR_EVT_CLASS_FATAL = 3,
- MR_EVT_CLASS_DEAD = 4,
+ MR_EVT_CLASS_DEBUG = -2,
+ MR_EVT_CLASS_PROGRESS = -1,
+ MR_EVT_CLASS_INFO = 0,
+ MR_EVT_CLASS_WARNING = 1,
+ MR_EVT_CLASS_CRITICAL = 2,
+ MR_EVT_CLASS_FATAL = 3,
+ MR_EVT_CLASS_DEAD = 4,
};
enum MR_EVT_LOCALE {
- MR_EVT_LOCALE_LD = 0x0001,
- MR_EVT_LOCALE_PD = 0x0002,
- MR_EVT_LOCALE_ENCL = 0x0004,
- MR_EVT_LOCALE_BBU = 0x0008,
- MR_EVT_LOCALE_SAS = 0x0010,
- MR_EVT_LOCALE_CTRL = 0x0020,
- MR_EVT_LOCALE_CONFIG = 0x0040,
- MR_EVT_LOCALE_CLUSTER = 0x0080,
- MR_EVT_LOCALE_ALL = 0xffff,
+ MR_EVT_LOCALE_LD = 0x0001,
+ MR_EVT_LOCALE_PD = 0x0002,
+ MR_EVT_LOCALE_ENCL = 0x0004,
+ MR_EVT_LOCALE_BBU = 0x0008,
+ MR_EVT_LOCALE_SAS = 0x0010,
+ MR_EVT_LOCALE_CTRL = 0x0020,
+ MR_EVT_LOCALE_CONFIG = 0x0040,
+ MR_EVT_LOCALE_CLUSTER = 0x0080,
+ MR_EVT_LOCALE_ALL = 0xffff,
};
enum MR_EVT_ARGS {
- MR_EVT_ARGS_NONE,
- MR_EVT_ARGS_CDB_SENSE,
- MR_EVT_ARGS_LD,
- MR_EVT_ARGS_LD_COUNT,
- MR_EVT_ARGS_LD_LBA,
- MR_EVT_ARGS_LD_OWNER,
- MR_EVT_ARGS_LD_LBA_PD_LBA,
- MR_EVT_ARGS_LD_PROG,
- MR_EVT_ARGS_LD_STATE,
- MR_EVT_ARGS_LD_STRIP,
- MR_EVT_ARGS_PD,
- MR_EVT_ARGS_PD_ERR,
- MR_EVT_ARGS_PD_LBA,
- MR_EVT_ARGS_PD_LBA_LD,
- MR_EVT_ARGS_PD_PROG,
- MR_EVT_ARGS_PD_STATE,
- MR_EVT_ARGS_PCI,
- MR_EVT_ARGS_RATE,
- MR_EVT_ARGS_STR,
- MR_EVT_ARGS_TIME,
- MR_EVT_ARGS_ECC,
- MR_EVT_ARGS_LD_PROP,
- MR_EVT_ARGS_PD_SPARE,
- MR_EVT_ARGS_PD_INDEX,
- MR_EVT_ARGS_DIAG_PASS,
- MR_EVT_ARGS_DIAG_FAIL,
- MR_EVT_ARGS_PD_LBA_LBA,
- MR_EVT_ARGS_PORT_PHY,
- MR_EVT_ARGS_PD_MISSING,
- MR_EVT_ARGS_PD_ADDRESS,
- MR_EVT_ARGS_BITMAP,
- MR_EVT_ARGS_CONNECTOR,
- MR_EVT_ARGS_PD_PD,
- MR_EVT_ARGS_PD_FRU,
- MR_EVT_ARGS_PD_PATHINFO,
- MR_EVT_ARGS_PD_POWER_STATE,
- MR_EVT_ARGS_GENERIC,
+ MR_EVT_ARGS_NONE,
+ MR_EVT_ARGS_CDB_SENSE,
+ MR_EVT_ARGS_LD,
+ MR_EVT_ARGS_LD_COUNT,
+ MR_EVT_ARGS_LD_LBA,
+ MR_EVT_ARGS_LD_OWNER,
+ MR_EVT_ARGS_LD_LBA_PD_LBA,
+ MR_EVT_ARGS_LD_PROG,
+ MR_EVT_ARGS_LD_STATE,
+ MR_EVT_ARGS_LD_STRIP,
+ MR_EVT_ARGS_PD,
+ MR_EVT_ARGS_PD_ERR,
+ MR_EVT_ARGS_PD_LBA,
+ MR_EVT_ARGS_PD_LBA_LD,
+ MR_EVT_ARGS_PD_PROG,
+ MR_EVT_ARGS_PD_STATE,
+ MR_EVT_ARGS_PCI,
+ MR_EVT_ARGS_RATE,
+ MR_EVT_ARGS_STR,
+ MR_EVT_ARGS_TIME,
+ MR_EVT_ARGS_ECC,
+ MR_EVT_ARGS_LD_PROP,
+ MR_EVT_ARGS_PD_SPARE,
+ MR_EVT_ARGS_PD_INDEX,
+ MR_EVT_ARGS_DIAG_PASS,
+ MR_EVT_ARGS_DIAG_FAIL,
+ MR_EVT_ARGS_PD_LBA_LBA,
+ MR_EVT_ARGS_PORT_PHY,
+ MR_EVT_ARGS_PD_MISSING,
+ MR_EVT_ARGS_PD_ADDRESS,
+ MR_EVT_ARGS_BITMAP,
+ MR_EVT_ARGS_CONNECTOR,
+ MR_EVT_ARGS_PD_PD,
+ MR_EVT_ARGS_PD_FRU,
+ MR_EVT_ARGS_PD_PATHINFO,
+ MR_EVT_ARGS_PD_POWER_STATE,
+ MR_EVT_ARGS_GENERIC,
};
/*
- * Thunderbolt (and later) Defines
+ * Thunderbolt (and later) Defines
*/
-#define MRSAS_MAX_SZ_CHAIN_FRAME 1024
-#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009)
-#define MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256
-#define MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0
-#define MRSAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1
-#define MRSAS_LOAD_BALANCE_FLAG 0x1
-#define MRSAS_DCMD_MBOX_PEND_FLAG 0x1
-#define HOST_DIAG_WRITE_ENABLE 0x80
-#define HOST_DIAG_RESET_ADAPTER 0x4
-#define MRSAS_TBOLT_MAX_RESET_TRIES 3
-#define MRSAS_MAX_MFI_CMDS 32
+#define MRSAS_MAX_SZ_CHAIN_FRAME 1024
+#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009)
+#define MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256
+#define MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0
+#define MRSAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1
+#define MRSAS_LOAD_BALANCE_FLAG 0x1
+#define MRSAS_DCMD_MBOX_PEND_FLAG 0x1
+#define HOST_DIAG_WRITE_ENABLE 0x80
+#define HOST_DIAG_RESET_ADAPTER 0x4
+#define MRSAS_TBOLT_MAX_RESET_TRIES 3
+#define MRSAS_MAX_MFI_CMDS 32
/*
- * Invader Defines
+ * Invader Defines
*/
-#define MPI2_TYPE_CUDA 0x2
-#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH 0x4000
-#define MR_RL_FLAGS_GRANT_DESTINATION_CPU0 0x00
-#define MR_RL_FLAGS_GRANT_DESTINATION_CPU1 0x10
-#define MR_RL_FLAGS_GRANT_DESTINATION_CUDA 0x80
-#define MR_RL_FLAGS_SEQ_NUM_ENABLE 0x8
-
-/*
- * T10 PI defines
+#define MPI2_TYPE_CUDA 0x2
+#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH 0x4000
+#define MR_RL_FLAGS_GRANT_DESTINATION_CPU0 0x00
+#define MR_RL_FLAGS_GRANT_DESTINATION_CPU1 0x10
+#define MR_RL_FLAGS_GRANT_DESTINATION_CUDA 0x80
+#define MR_RL_FLAGS_SEQ_NUM_ENABLE 0x8
+
+/*
+ * T10 PI defines
*/
-#define MR_PROT_INFO_TYPE_CONTROLLER 0x8
-#define MRSAS_SCSI_VARIABLE_LENGTH_CMD 0x7f
-#define MRSAS_SCSI_SERVICE_ACTION_READ32 0x9
-#define MRSAS_SCSI_SERVICE_ACTION_WRITE32 0xB
-#define MRSAS_SCSI_ADDL_CDB_LEN 0x18
-#define MRSAS_RD_WR_PROTECT_CHECK_ALL 0x20
-#define MRSAS_RD_WR_PROTECT_CHECK_NONE 0x60
-#define MRSAS_SCSIBLOCKSIZE 512
+#define MR_PROT_INFO_TYPE_CONTROLLER 0x8
+#define MRSAS_SCSI_VARIABLE_LENGTH_CMD 0x7f
+#define MRSAS_SCSI_SERVICE_ACTION_READ32 0x9
+#define MRSAS_SCSI_SERVICE_ACTION_WRITE32 0xB
+#define MRSAS_SCSI_ADDL_CDB_LEN 0x18
+#define MRSAS_RD_WR_PROTECT_CHECK_ALL 0x20
+#define MRSAS_RD_WR_PROTECT_CHECK_NONE 0x60
+#define MRSAS_SCSIBLOCKSIZE 512
/*
* Raid context flags
*/
-#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT 0x4
-#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK 0x30
+#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT 0x4
+#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK 0x30
typedef enum MR_RAID_FLAGS_IO_SUB_TYPE {
- MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0,
- MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1,
-} MR_RAID_FLAGS_IO_SUB_TYPE;
+ MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0,
+ MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1,
+} MR_RAID_FLAGS_IO_SUB_TYPE;
/*
* Request descriptor types
*/
-#define MRSAS_REQ_DESCRIPT_FLAGS_LD_IO 0x7
-#define MRSAS_REQ_DESCRIPT_FLAGS_MFA 0x1
-#define MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK 0x2
-#define MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT 1
-#define MRSAS_FP_CMD_LEN 16
-#define MRSAS_FUSION_IN_RESET 0
-
-#define RAID_CTX_SPANARM_ARM_SHIFT (0)
-#define RAID_CTX_SPANARM_ARM_MASK (0x1f)
-#define RAID_CTX_SPANARM_SPAN_SHIFT (5)
-#define RAID_CTX_SPANARM_SPAN_MASK (0xE0)
-
-/*
+#define MRSAS_REQ_DESCRIPT_FLAGS_LD_IO 0x7
+#define MRSAS_REQ_DESCRIPT_FLAGS_MFA 0x1
+#define MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK 0x2
+#define MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT 1
+#define MRSAS_FP_CMD_LEN 16
+#define MRSAS_FUSION_IN_RESET 0
+
+#define RAID_CTX_SPANARM_ARM_SHIFT (0)
+#define RAID_CTX_SPANARM_ARM_MASK (0x1f)
+#define RAID_CTX_SPANARM_SPAN_SHIFT (5)
+#define RAID_CTX_SPANARM_SPAN_MASK (0xE0)
+
+/*
* Define region lock types
*/
-typedef enum _REGION_TYPE {
- REGION_TYPE_UNUSED = 0, // lock is currently not active
- REGION_TYPE_SHARED_READ = 1, // shared lock (for reads)
- REGION_TYPE_SHARED_WRITE = 2,
- REGION_TYPE_EXCLUSIVE = 3, // exclusive lock (for writes)
-} REGION_TYPE;
-
-/*
- * MR private defines
- */
-#define MR_PD_INVALID 0xFFFF
-#define MAX_SPAN_DEPTH 8
-#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
-#define MAX_ROW_SIZE 32
-#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
-#define MAX_LOGICAL_DRIVES 64
-#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
-#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
-#define MAX_ARRAYS 128
-#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
-#define MAX_PHYSICAL_DEVICES 256
-#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
-#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101
+typedef enum _REGION_TYPE {
+ REGION_TYPE_UNUSED = 0,
+ REGION_TYPE_SHARED_READ = 1,
+ REGION_TYPE_SHARED_WRITE = 2,
+ REGION_TYPE_EXCLUSIVE = 3,
+} REGION_TYPE;
+
/*
- * SCSI-CAM Related Defines
+ * SCSI-CAM Related Defines
*/
-#define MRSAS_SCSI_MAX_LUNS 0 //zero for now
-#define MRSAS_SCSI_INITIATOR_ID 255
-#define MRSAS_SCSI_MAX_CMDS 8
-#define MRSAS_SCSI_MAX_CDB_LEN 16
-#define MRSAS_SCSI_SENSE_BUFFERSIZE 96
-#define MRSAS_MAX_SGL 70
-#define MRSAS_MAX_IO_SIZE (256 * 1024)
-#define MRSAS_INTERNAL_CMDS 32
+#define MRSAS_SCSI_MAX_LUNS 0
+#define MRSAS_SCSI_INITIATOR_ID 255
+#define MRSAS_SCSI_MAX_CMDS 8
+#define MRSAS_SCSI_MAX_CDB_LEN 16
+#define MRSAS_SCSI_SENSE_BUFFERSIZE 96
+#define MRSAS_MAX_SGL 70
+#define MRSAS_MAX_IO_SIZE (256 * 1024)
+#define MRSAS_INTERNAL_CMDS 32
/* Request types */
-#define MRSAS_REQ_TYPE_INTERNAL_CMD 0x0
-#define MRSAS_REQ_TYPE_AEN_FETCH 0x1
-#define MRSAS_REQ_TYPE_PASSTHRU 0x2
-#define MRSAS_REQ_TYPE_GETSET_PARAM 0x3
-#define MRSAS_REQ_TYPE_SCSI_IO 0x4
+#define MRSAS_REQ_TYPE_INTERNAL_CMD 0x0
+#define MRSAS_REQ_TYPE_AEN_FETCH 0x1
+#define MRSAS_REQ_TYPE_PASSTHRU 0x2
+#define MRSAS_REQ_TYPE_GETSET_PARAM 0x3
+#define MRSAS_REQ_TYPE_SCSI_IO 0x4
/* Request states */
-#define MRSAS_REQ_STATE_FREE 0
-#define MRSAS_REQ_STATE_BUSY 1
-#define MRSAS_REQ_STATE_TRAN 2
-#define MRSAS_REQ_STATE_COMPLETE 3
+#define MRSAS_REQ_STATE_FREE 0
+#define MRSAS_REQ_STATE_BUSY 1
+#define MRSAS_REQ_STATE_TRAN 2
+#define MRSAS_REQ_STATE_COMPLETE 3
enum mrsas_req_flags {
- MRSAS_DIR_UNKNOWN = 0x1,
- MRSAS_DIR_IN = 0x2,
- MRSAS_DIR_OUT = 0x4,
- MRSAS_DIR_NONE = 0x8,
+ MRSAS_DIR_UNKNOWN = 0x1,
+ MRSAS_DIR_IN = 0x2,
+ MRSAS_DIR_OUT = 0x4,
+ MRSAS_DIR_NONE = 0x8,
};
-/*
- * Adapter Reset States
+/*
+ * Adapter Reset States
*/
enum {
- MRSAS_HBA_OPERATIONAL = 0,
- MRSAS_ADPRESET_SM_INFAULT = 1,
- MRSAS_ADPRESET_SM_FW_RESET_SUCCESS = 2,
- MRSAS_ADPRESET_SM_OPERATIONAL = 3,
- MRSAS_HW_CRITICAL_ERROR = 4,
- MRSAS_ADPRESET_INPROG_SIGN = 0xDEADDEAD,
+ MRSAS_HBA_OPERATIONAL = 0,
+ MRSAS_ADPRESET_SM_INFAULT = 1,
+ MRSAS_ADPRESET_SM_FW_RESET_SUCCESS = 2,
+ MRSAS_ADPRESET_SM_OPERATIONAL = 3,
+ MRSAS_HW_CRITICAL_ERROR = 4,
+ MRSAS_ADPRESET_INPROG_SIGN = 0xDEADDEAD,
};
-/*
- * MPT Command Structure
+/*
+ * MPT Command Structure
*/
struct mrsas_mpt_cmd {
- MRSAS_RAID_SCSI_IO_REQUEST *io_request;
- bus_addr_t io_request_phys_addr;
- MPI2_SGE_IO_UNION *chain_frame;
- bus_addr_t chain_frame_phys_addr;
- u_int32_t sge_count;
- u_int8_t *sense;
- bus_addr_t sense_phys_addr;
- u_int8_t retry_for_fw_reset;
- MRSAS_REQUEST_DESCRIPTOR_UNION *request_desc;
- u_int32_t sync_cmd_idx; //For getting MFI cmd from list when complete
- u_int32_t index;
- u_int8_t flags;
- u_int8_t load_balance;
- bus_size_t length; // request length
- u_int32_t error_code; // error during request dmamap load
- bus_dmamap_t data_dmamap;
- void *data;
- union ccb *ccb_ptr; // pointer to ccb
- struct callout cm_callout;
- struct mrsas_softc *sc;
- TAILQ_ENTRY(mrsas_mpt_cmd) next;
+ MRSAS_RAID_SCSI_IO_REQUEST *io_request;
+ bus_addr_t io_request_phys_addr;
+ MPI2_SGE_IO_UNION *chain_frame;
+ bus_addr_t chain_frame_phys_addr;
+ u_int32_t sge_count;
+ u_int8_t *sense;
+ bus_addr_t sense_phys_addr;
+ u_int8_t retry_for_fw_reset;
+ MRSAS_REQUEST_DESCRIPTOR_UNION *request_desc;
+ u_int32_t sync_cmd_idx;
+ u_int32_t index;
+ u_int8_t flags;
+ u_int8_t load_balance;
+ bus_size_t length;
+ u_int32_t error_code;
+ bus_dmamap_t data_dmamap;
+ void *data;
+ union ccb *ccb_ptr;
+ struct callout cm_callout;
+ struct mrsas_softc *sc;
+ TAILQ_ENTRY(mrsas_mpt_cmd) next;
};
-/*
- * MFI Command Structure
+/*
+ * MFI Command Structure
*/
struct mrsas_mfi_cmd {
- union mrsas_frame *frame;
- bus_dmamap_t frame_dmamap; // mfi frame dmamap
- void *frame_mem; // mfi frame virtual addr
- bus_addr_t frame_phys_addr; // mfi frame physical addr
- u_int8_t *sense;
- bus_dmamap_t sense_dmamap; // mfi sense dmamap
- void *sense_mem; // mfi sense virtual addr
- bus_addr_t sense_phys_addr;
- u_int32_t index;
- u_int8_t sync_cmd;
- u_int8_t cmd_status;
- u_int8_t abort_aen;
- u_int8_t retry_for_fw_reset;
- struct mrsas_softc *sc;
- union ccb *ccb_ptr;
- union {
- struct {
- u_int16_t smid;
- u_int16_t resvd;
- } context;
- u_int32_t frame_count;
- } cmd_id;
- TAILQ_ENTRY(mrsas_mfi_cmd) next;
+ union mrsas_frame *frame;
+ bus_dmamap_t frame_dmamap;
+ void *frame_mem;
+ bus_addr_t frame_phys_addr;
+ u_int8_t *sense;
+ bus_dmamap_t sense_dmamap;
+ void *sense_mem;
+ bus_addr_t sense_phys_addr;
+ u_int32_t index;
+ u_int8_t sync_cmd;
+ u_int8_t cmd_status;
+ u_int8_t abort_aen;
+ u_int8_t retry_for_fw_reset;
+ struct mrsas_softc *sc;
+ union ccb *ccb_ptr;
+ union {
+ struct {
+ u_int16_t smid;
+ u_int16_t resvd;
+ } context;
+ u_int32_t frame_count;
+ } cmd_id;
+ TAILQ_ENTRY(mrsas_mfi_cmd) next;
};
@@ -1322,61 +1394,62 @@ struct mrsas_mfi_cmd {
* define constants for device list query options
*/
enum MR_PD_QUERY_TYPE {
- MR_PD_QUERY_TYPE_ALL = 0,
- MR_PD_QUERY_TYPE_STATE = 1,
- MR_PD_QUERY_TYPE_POWER_STATE = 2,
- MR_PD_QUERY_TYPE_MEDIA_TYPE = 3,
- MR_PD_QUERY_TYPE_SPEED = 4,
- MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5,
+ MR_PD_QUERY_TYPE_ALL = 0,
+ MR_PD_QUERY_TYPE_STATE = 1,
+ MR_PD_QUERY_TYPE_POWER_STATE = 2,
+ MR_PD_QUERY_TYPE_MEDIA_TYPE = 3,
+ MR_PD_QUERY_TYPE_SPEED = 4,
+ MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5,
};
-#define MR_EVT_CFG_CLEARED 0x0004
-#define MR_EVT_LD_STATE_CHANGE 0x0051
-#define MR_EVT_PD_INSERTED 0x005b
-#define MR_EVT_PD_REMOVED 0x0070
-#define MR_EVT_LD_CREATED 0x008a
-#define MR_EVT_LD_DELETED 0x008b
-#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
-#define MR_EVT_LD_OFFLINE 0x00fc
-#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
+#define MR_EVT_CFG_CLEARED 0x0004
+#define MR_EVT_LD_STATE_CHANGE 0x0051
+#define MR_EVT_PD_INSERTED 0x005b
+#define MR_EVT_PD_REMOVED 0x0070
+#define MR_EVT_LD_CREATED 0x008a
+#define MR_EVT_LD_DELETED 0x008b
+#define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db
+#define MR_EVT_LD_OFFLINE 0x00fc
+#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
enum MR_PD_STATE {
- MR_PD_STATE_UNCONFIGURED_GOOD = 0x00,
- MR_PD_STATE_UNCONFIGURED_BAD = 0x01,
- MR_PD_STATE_HOT_SPARE = 0x02,
- MR_PD_STATE_OFFLINE = 0x10,
- MR_PD_STATE_FAILED = 0x11,
- MR_PD_STATE_REBUILD = 0x14,
- MR_PD_STATE_ONLINE = 0x18,
- MR_PD_STATE_COPYBACK = 0x20,
- MR_PD_STATE_SYSTEM = 0x40,
- };
-
- /*
+ MR_PD_STATE_UNCONFIGURED_GOOD = 0x00,
+ MR_PD_STATE_UNCONFIGURED_BAD = 0x01,
+ MR_PD_STATE_HOT_SPARE = 0x02,
+ MR_PD_STATE_OFFLINE = 0x10,
+ MR_PD_STATE_FAILED = 0x11,
+ MR_PD_STATE_REBUILD = 0x14,
+ MR_PD_STATE_ONLINE = 0x18,
+ MR_PD_STATE_COPYBACK = 0x20,
+ MR_PD_STATE_SYSTEM = 0x40,
+};
+
+/*
* defines the physical drive address structure
*/
#pragma pack(1)
struct MR_PD_ADDRESS {
- u_int16_t deviceId;
- u_int16_t enclDeviceId;
-
- union {
- struct {
- u_int8_t enclIndex;
- u_int8_t slotNumber;
- } mrPdAddress;
- struct {
- u_int8_t enclPosition;
- u_int8_t enclConnectorIndex;
- } mrEnclAddress;
- } u1;
- u_int8_t scsiDevType;
- union {
- u_int8_t connectedPortBitmap;
- u_int8_t connectedPortNumbers;
- } u2;
- u_int64_t sasAddr[2];
+ u_int16_t deviceId;
+ u_int16_t enclDeviceId;
+
+ union {
+ struct {
+ u_int8_t enclIndex;
+ u_int8_t slotNumber;
+ } mrPdAddress;
+ struct {
+ u_int8_t enclPosition;
+ u_int8_t enclConnectorIndex;
+ } mrEnclAddress;
+ } u1;
+ u_int8_t scsiDevType;
+ union {
+ u_int8_t connectedPortBitmap;
+ u_int8_t connectedPortNumbers;
+ } u2;
+ u_int64_t sasAddr[2];
};
+
#pragma pack()
/*
@@ -1384,31 +1457,33 @@ struct MR_PD_ADDRESS {
*/
#pragma pack(1)
struct MR_PD_LIST {
- u_int32_t size;
- u_int32_t count;
- struct MR_PD_ADDRESS addr[1];
+ u_int32_t size;
+ u_int32_t count;
+ struct MR_PD_ADDRESS addr[1];
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_pd_list {
- u_int16_t tid;
- u_int8_t driveType;
- u_int8_t driveState;
+ u_int16_t tid;
+ u_int8_t driveType;
+ u_int8_t driveState;
};
+
#pragma pack()
- /*
+/*
* defines the logical drive reference structure
*/
-typedef union _MR_LD_REF { // LD reference structure
- struct {
- u_int8_t targetId; // LD target id (0 to MAX_TARGET_ID)
- u_int8_t reserved; // reserved to make in line with MR_PD_REF
- u_int16_t seqNum; // Sequence Number
- } ld_context;
- u_int32_t ref; // shorthand reference to full 32-bits
-} MR_LD_REF; // 4 bytes
+typedef union _MR_LD_REF {
+ struct {
+ u_int8_t targetId;
+ u_int8_t reserved;
+ u_int16_t seqNum;
+ } ld_context;
+ u_int32_t ref;
+} MR_LD_REF;
/*
@@ -1416,15 +1491,16 @@ typedef union _MR_LD_REF { // LD reference structure
*/
#pragma pack(1)
struct MR_LD_LIST {
- u_int32_t ldCount; // number of LDs
- u_int32_t reserved; // pad to 8-byte boundary
- struct {
- MR_LD_REF ref; // LD reference
- u_int8_t state; // current LD state (MR_LD_STATE)
- u_int8_t reserved[3]; // pad to 8-byte boundary
- u_int64_t size; // LD size
- } ldList[MAX_LOGICAL_DRIVES];
-};
+ u_int32_t ldCount;
+ u_int32_t reserved;
+ struct {
+ MR_LD_REF ref;
+ u_int8_t state;
+ u_int8_t reserved[3];
+ u_int64_t size;
+ } ldList[MAX_LOGICAL_DRIVES_EXT];
+};
+
#pragma pack()
/*
@@ -1432,412 +1508,401 @@ struct MR_LD_LIST {
*/
#pragma pack(1)
struct mrsas_ctrl_prop {
- u_int16_t seq_num;
- u_int16_t pred_fail_poll_interval;
- u_int16_t intr_throttle_count;
- u_int16_t intr_throttle_timeouts;
- u_int8_t rebuild_rate;
- u_int8_t patrol_read_rate;
- u_int8_t bgi_rate;
- u_int8_t cc_rate;
- u_int8_t recon_rate;
- u_int8_t cache_flush_interval;
- u_int8_t spinup_drv_count;
- u_int8_t spinup_delay;
- u_int8_t cluster_enable;
- u_int8_t coercion_mode;
- u_int8_t alarm_enable;
- u_int8_t disable_auto_rebuild;
- u_int8_t disable_battery_warn;
- u_int8_t ecc_bucket_size;
- u_int16_t ecc_bucket_leak_rate;
- u_int8_t restore_hotspare_on_insertion;
- u_int8_t expose_encl_devices;
- u_int8_t maintainPdFailHistory;
- u_int8_t disallowHostRequestReordering;
- u_int8_t abortCCOnError; // set TRUE to abort CC on detecting an inconsistency
- u_int8_t loadBalanceMode; // load balance mode (MR_LOAD_BALANCE_MODE)
- u_int8_t disableAutoDetectBackplane; // 0 - use auto detect logic of backplanes
- // like SGPIO, i2c SEP using h/w mechansim
- // like GPIO pins.
- // 1 - disable auto detect SGPIO,
- // 2 - disable i2c SEP auto detect
- // 3 - disable both auto detect
- u_int8_t snapVDSpace; // % of source LD to be reserved for a VDs snapshot in
- // snapshot repository, for metadata and user data.
- // 1=5%, 2=10%, 3=15% and so on.
- /*
- * Add properties that can be controlled by a bit in the following structure.
- */
- struct {
- u_int32_t copyBackDisabled : 1; // set TRUE to disable copyBack
- // (0=copback enabled)
- u_int32_t SMARTerEnabled : 1;
- u_int32_t prCorrectUnconfiguredAreas : 1;
- u_int32_t useFdeOnly : 1;
- u_int32_t disableNCQ : 1;
- u_int32_t SSDSMARTerEnabled : 1;
- u_int32_t SSDPatrolReadEnabled : 1;
- u_int32_t enableSpinDownUnconfigured : 1;
- u_int32_t autoEnhancedImport : 1;
- u_int32_t enableSecretKeyControl : 1;
- u_int32_t disableOnlineCtrlReset : 1;
- u_int32_t allowBootWithPinnedCache : 1;
- u_int32_t disableSpinDownHS : 1;
- u_int32_t enableJBOD : 1;
- u_int32_t reserved :18;
- } OnOffProperties;
- u_int8_t autoSnapVDSpace; // % of source LD to be reserved for auto
- // snapshot in snapshot repository, for
- // metadata and user data.
- // 1=5%, 2=10%, 3=15% and so on.
- u_int8_t viewSpace; // snapshot writeable VIEWs capacity as a %
- // of source LD capacity. 0=READ only.
- // 1=5%, 2=10%, 3=15% and so on
- u_int16_t spinDownTime; // # of idle minutes before device is spun
- // down (0=use FW defaults).
- u_int8_t reserved[24];
-
-};
+ u_int16_t seq_num;
+ u_int16_t pred_fail_poll_interval;
+ u_int16_t intr_throttle_count;
+ u_int16_t intr_throttle_timeouts;
+ u_int8_t rebuild_rate;
+ u_int8_t patrol_read_rate;
+ u_int8_t bgi_rate;
+ u_int8_t cc_rate;
+ u_int8_t recon_rate;
+ u_int8_t cache_flush_interval;
+ u_int8_t spinup_drv_count;
+ u_int8_t spinup_delay;
+ u_int8_t cluster_enable;
+ u_int8_t coercion_mode;
+ u_int8_t alarm_enable;
+ u_int8_t disable_auto_rebuild;
+ u_int8_t disable_battery_warn;
+ u_int8_t ecc_bucket_size;
+ u_int16_t ecc_bucket_leak_rate;
+ u_int8_t restore_hotspare_on_insertion;
+ u_int8_t expose_encl_devices;
+ u_int8_t maintainPdFailHistory;
+ u_int8_t disallowHostRequestReordering;
+ u_int8_t abortCCOnError;
+ u_int8_t loadBalanceMode;
+ u_int8_t disableAutoDetectBackplane;
+ u_int8_t snapVDSpace;
+ /*
+ * Add properties that can be controlled by a bit in the following
+ * structure.
+ */
+ struct {
+ u_int32_t copyBackDisabled:1;
+ u_int32_t SMARTerEnabled:1;
+ u_int32_t prCorrectUnconfiguredAreas:1;
+ u_int32_t useFdeOnly:1;
+ u_int32_t disableNCQ:1;
+ u_int32_t SSDSMARTerEnabled:1;
+ u_int32_t SSDPatrolReadEnabled:1;
+ u_int32_t enableSpinDownUnconfigured:1;
+ u_int32_t autoEnhancedImport:1;
+ u_int32_t enableSecretKeyControl:1;
+ u_int32_t disableOnlineCtrlReset:1;
+ u_int32_t allowBootWithPinnedCache:1;
+ u_int32_t disableSpinDownHS:1;
+ u_int32_t enableJBOD:1;
+ u_int32_t disableCacheBypass:1;
+ u_int32_t useDiskActivityForLocate:1;
+ u_int32_t enablePI:1;
+ u_int32_t preventPIImport:1;
+ u_int32_t useGlobalSparesForEmergency:1;
+ u_int32_t useUnconfGoodForEmergency:1;
+ u_int32_t useEmergencySparesforSMARTer:1;
+ u_int32_t forceSGPIOForQuadOnly:1;
+ u_int32_t enableConfigAutoBalance:1;
+ u_int32_t enableVirtualCache:1;
+ u_int32_t enableAutoLockRecovery:1;
+ u_int32_t disableImmediateIO:1;
+ u_int32_t disableT10RebuildAssist:1;
+ u_int32_t ignore64ldRestriction:1;
+ u_int32_t enableSwZone:1;
+ u_int32_t limitMaxRateSATA3G:1;
+ u_int32_t reserved:2;
+ } OnOffProperties;
+ u_int8_t autoSnapVDSpace;
+ u_int8_t viewSpace;
+ u_int16_t spinDownTime;
+ u_int8_t reserved[24];
+
+};
+
#pragma pack()
/*
* SAS controller information
*/
-//#pragma pack(1)
struct mrsas_ctrl_info {
- /*
- * PCI device information
- */
- struct {
- u_int16_t vendor_id;
- u_int16_t device_id;
- u_int16_t sub_vendor_id;
- u_int16_t sub_device_id;
- u_int8_t reserved[24];
- } __packed pci;
- /*
- * Host interface information
- */
- struct {
- u_int8_t PCIX:1;
- u_int8_t PCIE:1;
- u_int8_t iSCSI:1;
- u_int8_t SAS_3G:1;
- u_int8_t reserved_0:4;
- u_int8_t reserved_1[6];
- u_int8_t port_count;
- u_int64_t port_addr[8];
- } __packed host_interface;
- /*
- * Device (backend) interface information
- */
- struct {
- u_int8_t SPI:1;
- u_int8_t SAS_3G:1;
- u_int8_t SATA_1_5G:1;
- u_int8_t SATA_3G:1;
- u_int8_t reserved_0:4;
- u_int8_t reserved_1[6];
- u_int8_t port_count;
- u_int64_t port_addr[8];
- } __packed device_interface;
-
- /*
- * List of components residing in flash. All str are null terminated
- */
- u_int32_t image_check_word;
- u_int32_t image_component_count;
-
- struct {
- char name[8];
- char version[32];
- char build_date[16];
- char built_time[16];
- } __packed image_component[8];
- /*
- * List of flash components that have been flashed on the card, but
- * are not in use, pending reset of the adapter. This list will be
- * empty if a flash operation has not occurred. All stings are null
- * terminated
- */
- u_int32_t pending_image_component_count;
-
- struct {
- char name[8];
- char version[32];
- char build_date[16];
- char build_time[16];
- } __packed pending_image_component[8];
-
- u_int8_t max_arms;
- u_int8_t max_spans;
- u_int8_t max_arrays;
- u_int8_t max_lds;
- char product_name[80];
- char serial_no[32];
-
- /*
- * Other physical/controller/operation information. Indicates the
- * presence of the hardware
- */
- struct {
- u_int32_t bbu:1;
- u_int32_t alarm:1;
- u_int32_t nvram:1;
- u_int32_t uart:1;
- u_int32_t reserved:28;
- } __packed hw_present;
-
- u_int32_t current_fw_time;
-
- /*
- * Maximum data transfer sizes
- */
- u_int16_t max_concurrent_cmds;
- u_int16_t max_sge_count;
- u_int32_t max_request_size;
-
- /*
- * Logical and physical device counts
- */
- u_int16_t ld_present_count;
- u_int16_t ld_degraded_count;
- u_int16_t ld_offline_count;
-
- u_int16_t pd_present_count;
- u_int16_t pd_disk_present_count;
- u_int16_t pd_disk_pred_failure_count;
- u_int16_t pd_disk_failed_count;
-
- /*
- * Memory size information
- */
- u_int16_t nvram_size;
- u_int16_t memory_size;
- u_int16_t flash_size;
-
- /*
- * Error counters
- */
- u_int16_t mem_correctable_error_count;
- u_int16_t mem_uncorrectable_error_count;
-
- /*
- * Cluster information
- */
- u_int8_t cluster_permitted;
- u_int8_t cluster_active;
-
- /*
- * Additional max data transfer sizes
- */
- u_int16_t max_strips_per_io;
-
- /*
- * Controller capabilities structures
- */
- struct {
- u_int32_t raid_level_0:1;
- u_int32_t raid_level_1:1;
- u_int32_t raid_level_5:1;
- u_int32_t raid_level_1E:1;
- u_int32_t raid_level_6:1;
- u_int32_t reserved:27;
- } __packed raid_levels;
-
- struct {
- u_int32_t rbld_rate:1;
- u_int32_t cc_rate:1;
- u_int32_t bgi_rate:1;
- u_int32_t recon_rate:1;
- u_int32_t patrol_rate:1;
- u_int32_t alarm_control:1;
- u_int32_t cluster_supported:1;
- u_int32_t bbu:1;
- u_int32_t spanning_allowed:1;
- u_int32_t dedicated_hotspares:1;
- u_int32_t revertible_hotspares:1;
- u_int32_t foreign_config_import:1;
- u_int32_t self_diagnostic:1;
- u_int32_t mixed_redundancy_arr:1;
- u_int32_t global_hot_spares:1;
- u_int32_t reserved:17;
- } __packed adapter_operations;
-
- struct {
- u_int32_t read_policy:1;
- u_int32_t write_policy:1;
- u_int32_t io_policy:1;
- u_int32_t access_policy:1;
- u_int32_t disk_cache_policy:1;
- u_int32_t reserved:27;
- } __packed ld_operations;
-
- struct {
- u_int8_t min;
- u_int8_t max;
- u_int8_t reserved[2];
- } __packed stripe_sz_ops;
-
- struct {
- u_int32_t force_online:1;
- u_int32_t force_offline:1;
- u_int32_t force_rebuild:1;
- u_int32_t reserved:29;
- } __packed pd_operations;
-
- struct {
- u_int32_t ctrl_supports_sas:1;
- u_int32_t ctrl_supports_sata:1;
- u_int32_t allow_mix_in_encl:1;
- u_int32_t allow_mix_in_ld:1;
- u_int32_t allow_sata_in_cluster:1;
- u_int32_t reserved:27;
- } __packed pd_mix_support;
-
- /*
- * Define ECC single-bit-error bucket information
- */
- u_int8_t ecc_bucket_count;
- u_int8_t reserved_2[11];
-
- /*
- * Include the controller properties (changeable items)
- */
- struct mrsas_ctrl_prop properties;
-
- /*
- * Define FW pkg version (set in envt v'bles on OEM basis)
- */
- char package_version[0x60];
+ /*
+ * PCI device information
+ */
+ struct {
+ u_int16_t vendor_id;
+ u_int16_t device_id;
+ u_int16_t sub_vendor_id;
+ u_int16_t sub_device_id;
+ u_int8_t reserved[24];
+ } __packed pci;
+ /*
+ * Host interface information
+ */
+ struct {
+ u_int8_t PCIX:1;
+ u_int8_t PCIE:1;
+ u_int8_t iSCSI:1;
+ u_int8_t SAS_3G:1;
+ u_int8_t reserved_0:4;
+ u_int8_t reserved_1[6];
+ u_int8_t port_count;
+ u_int64_t port_addr[8];
+ } __packed host_interface;
+ /*
+ * Device (backend) interface information
+ */
+ struct {
+ u_int8_t SPI:1;
+ u_int8_t SAS_3G:1;
+ u_int8_t SATA_1_5G:1;
+ u_int8_t SATA_3G:1;
+ u_int8_t reserved_0:4;
+ u_int8_t reserved_1[6];
+ u_int8_t port_count;
+ u_int64_t port_addr[8];
+ } __packed device_interface;
+
+ u_int32_t image_check_word;
+ u_int32_t image_component_count;
+
+ struct {
+ char name[8];
+ char version[32];
+ char build_date[16];
+ char built_time[16];
+ } __packed image_component[8];
+
+ u_int32_t pending_image_component_count;
+
+ struct {
+ char name[8];
+ char version[32];
+ char build_date[16];
+ char build_time[16];
+ } __packed pending_image_component[8];
+
+ u_int8_t max_arms;
+ u_int8_t max_spans;
+ u_int8_t max_arrays;
+ u_int8_t max_lds;
+ char product_name[80];
+ char serial_no[32];
/*
- * If adapterOperations.supportMoreThan8Phys is set, and deviceInterface.portCount is greater than 8,
- * SAS Addrs for first 8 ports shall be populated in deviceInterface.portAddr, and the rest shall be
- * populated in deviceInterfacePortAddr2.
- */
- u_int64_t deviceInterfacePortAddr2[8]; //0x6a0
- u_int8_t reserved3[128]; //0x6e0
-
- struct { //0x760
- u_int16_t minPdRaidLevel_0 : 4;
- u_int16_t maxPdRaidLevel_0 : 12;
-
- u_int16_t minPdRaidLevel_1 : 4;
- u_int16_t maxPdRaidLevel_1 : 12;
-
- u_int16_t minPdRaidLevel_5 : 4;
- u_int16_t maxPdRaidLevel_5 : 12;
-
- u_int16_t minPdRaidLevel_1E : 4;
- u_int16_t maxPdRaidLevel_1E : 12;
-
- u_int16_t minPdRaidLevel_6 : 4;
- u_int16_t maxPdRaidLevel_6 : 12;
-
- u_int16_t minPdRaidLevel_10 : 4;
- u_int16_t maxPdRaidLevel_10 : 12;
-
- u_int16_t minPdRaidLevel_50 : 4;
- u_int16_t maxPdRaidLevel_50 : 12;
-
- u_int16_t minPdRaidLevel_60 : 4;
- u_int16_t maxPdRaidLevel_60 : 12;
-
- u_int16_t minPdRaidLevel_1E_RLQ0 : 4;
- u_int16_t maxPdRaidLevel_1E_RLQ0 : 12;
-
- u_int16_t minPdRaidLevel_1E0_RLQ0 : 4;
- u_int16_t maxPdRaidLevel_1E0_RLQ0 : 12;
-
- u_int16_t reserved[6];
- } pdsForRaidLevels;
-
- u_int16_t maxPds; //0x780
- u_int16_t maxDedHSPs; //0x782
- u_int16_t maxGlobalHSPs; //0x784
- u_int16_t ddfSize; //0x786
- u_int8_t maxLdsPerArray; //0x788
- u_int8_t partitionsInDDF; //0x789
- u_int8_t lockKeyBinding; //0x78a
- u_int8_t maxPITsPerLd; //0x78b
- u_int8_t maxViewsPerLd; //0x78c
- u_int8_t maxTargetId; //0x78d
- u_int16_t maxBvlVdSize; //0x78e
-
- u_int16_t maxConfigurableSSCSize; //0x790
- u_int16_t currentSSCsize; //0x792
-
- char expanderFwVersion[12]; //0x794
-
- u_int16_t PFKTrialTimeRemaining; //0x7A0
-
- u_int16_t cacheMemorySize; //0x7A2
-
- struct { //0x7A4
- u_int32_t supportPIcontroller :1;
- u_int32_t supportLdPIType1 :1;
- u_int32_t supportLdPIType2 :1;
- u_int32_t supportLdPIType3 :1;
- u_int32_t supportLdBBMInfo :1;
- u_int32_t supportShieldState :1;
- u_int32_t blockSSDWriteCacheChange :1;
- u_int32_t supportSuspendResumeBGops :1;
- u_int32_t supportEmergencySpares :1;
- u_int32_t supportSetLinkSpeed :1;
- u_int32_t supportBootTimePFKChange :1;
- u_int32_t supportJBOD :1;
- u_int32_t disableOnlinePFKChange :1;
- u_int32_t supportPerfTuning :1;
- u_int32_t supportSSDPatrolRead :1;
- u_int32_t realTimeScheduler :1;
-
- u_int32_t supportResetNow :1;
- u_int32_t supportEmulatedDrives :1;
- u_int32_t headlessMode :1;
- u_int32_t dedicatedHotSparesLimited :1;
-
-
- u_int32_t supportUnevenSpans :1;
- u_int32_t reserved :11;
- } adapterOperations2;
-
- u_int8_t driverVersion[32]; //0x7A8
- u_int8_t maxDAPdCountSpinup60; //0x7C8
- u_int8_t temperatureROC; //0x7C9
- u_int8_t temperatureCtrl; //0x7CA
- u_int8_t reserved4; //0x7CB
- u_int16_t maxConfigurablePds; //0x7CC
-
-
- u_int8_t reserved5[2]; //0x7CD reserved for future use
+ * Other physical/controller/operation information. Indicates the
+ * presence of the hardware
+ */
+ struct {
+ u_int32_t bbu:1;
+ u_int32_t alarm:1;
+ u_int32_t nvram:1;
+ u_int32_t uart:1;
+ u_int32_t reserved:28;
+ } __packed hw_present;
+
+ u_int32_t current_fw_time;
/*
- * HA cluster information
- */
+ * Maximum data transfer sizes
+ */
+ u_int16_t max_concurrent_cmds;
+ u_int16_t max_sge_count;
+ u_int32_t max_request_size;
+
+ /*
+ * Logical and physical device counts
+ */
+ u_int16_t ld_present_count;
+ u_int16_t ld_degraded_count;
+ u_int16_t ld_offline_count;
+
+ u_int16_t pd_present_count;
+ u_int16_t pd_disk_present_count;
+ u_int16_t pd_disk_pred_failure_count;
+ u_int16_t pd_disk_failed_count;
+
+ /*
+ * Memory size information
+ */
+ u_int16_t nvram_size;
+ u_int16_t memory_size;
+ u_int16_t flash_size;
+
+ /*
+ * Error counters
+ */
+ u_int16_t mem_correctable_error_count;
+ u_int16_t mem_uncorrectable_error_count;
+
+ /*
+ * Cluster information
+ */
+ u_int8_t cluster_permitted;
+ u_int8_t cluster_active;
+
+ /*
+ * Additional max data transfer sizes
+ */
+ u_int16_t max_strips_per_io;
+
+ /*
+ * Controller capabilities structures
+ */
struct {
- u_int32_t peerIsPresent :1;
- u_int32_t peerIsIncompatible :1;
-
- u_int32_t hwIncompatible :1;
- u_int32_t fwVersionMismatch :1;
- u_int32_t ctrlPropIncompatible :1;
- u_int32_t premiumFeatureMismatch :1;
- u_int32_t reserved :26;
- } cluster;
-
- char clusterId[16]; //0x7D4
-
- u_int8_t pad[0x800-0x7E4]; //0x7E4
-} __packed;
-
-/*
- * Ld and PD Max Support Defines
- */
-#define MRSAS_MAX_PD 256
-#define MRSAS_MAX_LD 64
+ u_int32_t raid_level_0:1;
+ u_int32_t raid_level_1:1;
+ u_int32_t raid_level_5:1;
+ u_int32_t raid_level_1E:1;
+ u_int32_t raid_level_6:1;
+ u_int32_t reserved:27;
+ } __packed raid_levels;
+
+ struct {
+ u_int32_t rbld_rate:1;
+ u_int32_t cc_rate:1;
+ u_int32_t bgi_rate:1;
+ u_int32_t recon_rate:1;
+ u_int32_t patrol_rate:1;
+ u_int32_t alarm_control:1;
+ u_int32_t cluster_supported:1;
+ u_int32_t bbu:1;
+ u_int32_t spanning_allowed:1;
+ u_int32_t dedicated_hotspares:1;
+ u_int32_t revertible_hotspares:1;
+ u_int32_t foreign_config_import:1;
+ u_int32_t self_diagnostic:1;
+ u_int32_t mixed_redundancy_arr:1;
+ u_int32_t global_hot_spares:1;
+ u_int32_t reserved:17;
+ } __packed adapter_operations;
+
+ struct {
+ u_int32_t read_policy:1;
+ u_int32_t write_policy:1;
+ u_int32_t io_policy:1;
+ u_int32_t access_policy:1;
+ u_int32_t disk_cache_policy:1;
+ u_int32_t reserved:27;
+ } __packed ld_operations;
+
+ struct {
+ u_int8_t min;
+ u_int8_t max;
+ u_int8_t reserved[2];
+ } __packed stripe_sz_ops;
+
+ struct {
+ u_int32_t force_online:1;
+ u_int32_t force_offline:1;
+ u_int32_t force_rebuild:1;
+ u_int32_t reserved:29;
+ } __packed pd_operations;
+
+ struct {
+ u_int32_t ctrl_supports_sas:1;
+ u_int32_t ctrl_supports_sata:1;
+ u_int32_t allow_mix_in_encl:1;
+ u_int32_t allow_mix_in_ld:1;
+ u_int32_t allow_sata_in_cluster:1;
+ u_int32_t reserved:27;
+ } __packed pd_mix_support;
+
+ /*
+ * Define ECC single-bit-error bucket information
+ */
+ u_int8_t ecc_bucket_count;
+ u_int8_t reserved_2[11];
+
+ /*
+ * Include the controller properties (changeable items)
+ */
+ struct mrsas_ctrl_prop properties;
+
+ /*
+ * Define FW pkg version (set in envt v'bles on OEM basis)
+ */
+ char package_version[0x60];
+
+ u_int64_t deviceInterfacePortAddr2[8];
+ u_int8_t reserved3[128];
+
+ struct {
+ u_int16_t minPdRaidLevel_0:4;
+ u_int16_t maxPdRaidLevel_0:12;
+
+ u_int16_t minPdRaidLevel_1:4;
+ u_int16_t maxPdRaidLevel_1:12;
+
+ u_int16_t minPdRaidLevel_5:4;
+ u_int16_t maxPdRaidLevel_5:12;
+
+ u_int16_t minPdRaidLevel_1E:4;
+ u_int16_t maxPdRaidLevel_1E:12;
+
+ u_int16_t minPdRaidLevel_6:4;
+ u_int16_t maxPdRaidLevel_6:12;
+
+ u_int16_t minPdRaidLevel_10:4;
+ u_int16_t maxPdRaidLevel_10:12;
+
+ u_int16_t minPdRaidLevel_50:4;
+ u_int16_t maxPdRaidLevel_50:12;
+
+ u_int16_t minPdRaidLevel_60:4;
+ u_int16_t maxPdRaidLevel_60:12;
+
+ u_int16_t minPdRaidLevel_1E_RLQ0:4;
+ u_int16_t maxPdRaidLevel_1E_RLQ0:12;
+
+ u_int16_t minPdRaidLevel_1E0_RLQ0:4;
+ u_int16_t maxPdRaidLevel_1E0_RLQ0:12;
+
+ u_int16_t reserved[6];
+ } pdsForRaidLevels;
+
+ u_int16_t maxPds; /* 0x780 */
+ u_int16_t maxDedHSPs; /* 0x782 */
+ u_int16_t maxGlobalHSPs; /* 0x784 */
+ u_int16_t ddfSize; /* 0x786 */
+ u_int8_t maxLdsPerArray; /* 0x788 */
+ u_int8_t partitionsInDDF; /* 0x789 */
+ u_int8_t lockKeyBinding; /* 0x78a */
+ u_int8_t maxPITsPerLd; /* 0x78b */
+ u_int8_t maxViewsPerLd; /* 0x78c */
+ u_int8_t maxTargetId; /* 0x78d */
+ u_int16_t maxBvlVdSize; /* 0x78e */
+
+ u_int16_t maxConfigurableSSCSize; /* 0x790 */
+ u_int16_t currentSSCsize; /* 0x792 */
+
+ char expanderFwVersion[12]; /* 0x794 */
+
+ u_int16_t PFKTrialTimeRemaining;/* 0x7A0 */
+
+ u_int16_t cacheMemorySize; /* 0x7A2 */
+
+ struct { /* 0x7A4 */
+ u_int32_t supportPIcontroller:1;
+ u_int32_t supportLdPIType1:1;
+ u_int32_t supportLdPIType2:1;
+ u_int32_t supportLdPIType3:1;
+ u_int32_t supportLdBBMInfo:1;
+ u_int32_t supportShieldState:1;
+ u_int32_t blockSSDWriteCacheChange:1;
+ u_int32_t supportSuspendResumeBGops:1;
+ u_int32_t supportEmergencySpares:1;
+ u_int32_t supportSetLinkSpeed:1;
+ u_int32_t supportBootTimePFKChange:1;
+ u_int32_t supportJBOD:1;
+ u_int32_t disableOnlinePFKChange:1;
+ u_int32_t supportPerfTuning:1;
+ u_int32_t supportSSDPatrolRead:1;
+ u_int32_t realTimeScheduler:1;
+
+ u_int32_t supportResetNow:1;
+ u_int32_t supportEmulatedDrives:1;
+ u_int32_t headlessMode:1;
+ u_int32_t dedicatedHotSparesLimited:1;
+
+
+ u_int32_t supportUnevenSpans:1;
+ u_int32_t reserved:11;
+ } adapterOperations2;
+
+ u_int8_t driverVersion[32]; /* 0x7A8 */
+ u_int8_t maxDAPdCountSpinup60; /* 0x7C8 */
+ u_int8_t temperatureROC; /* 0x7C9 */
+ u_int8_t temperatureCtrl; /* 0x7CA */
+ u_int8_t reserved4; /* 0x7CB */
+ u_int16_t maxConfigurablePds; /* 0x7CC */
+
+
+ u_int8_t reserved5[2]; /* 0x7CD reserved */
+
+ struct {
+ u_int32_t peerIsPresent:1;
+ u_int32_t peerIsIncompatible:1;
+
+ u_int32_t hwIncompatible:1;
+ u_int32_t fwVersionMismatch:1;
+ u_int32_t ctrlPropIncompatible:1;
+ u_int32_t premiumFeatureMismatch:1;
+ u_int32_t reserved:26;
+ } cluster;
+
+ char clusterId[16]; /* 0x7D4 */
+
+ char reserved6[4]; /* 0x7E4 RESERVED FOR IOV */
+
+ struct { /* 0x7E8 */
+ u_int32_t resrved:5;
+ u_int32_t supportMaxExtLDs:1;
+ u_int32_t reserved1:26;
+ } adapterOperations3;
+
+ u_int8_t pad[0x800 - 0x7EC]; /* 0x7EC */
+} __packed;
/*
* When SCSI mid-layer calls driver's reset routine, driver waits for
@@ -1846,304 +1911,334 @@ struct mrsas_ctrl_info {
* it is waiting for the commands to complete, it prints a diagnostic message
* every MRSAS_RESET_NOTICE_INTERVAL seconds
*/
-#define MRSAS_RESET_WAIT_TIME 180
-#define MRSAS_INTERNAL_CMD_WAIT_TIME 180
-#define MRSAS_IOC_INIT_WAIT_TIME 60
-#define MRSAS_RESET_NOTICE_INTERVAL 5
-#define MRSAS_IOCTL_CMD 0
-#define MRSAS_DEFAULT_CMD_TIMEOUT 90
-#define MRSAS_THROTTLE_QUEUE_DEPTH 16
-
-/*
+#define MRSAS_RESET_WAIT_TIME 180
+#define MRSAS_INTERNAL_CMD_WAIT_TIME 180
+#define MRSAS_IOC_INIT_WAIT_TIME 60
+#define MRSAS_RESET_NOTICE_INTERVAL 5
+#define MRSAS_IOCTL_CMD 0
+#define MRSAS_DEFAULT_CMD_TIMEOUT 90
+#define MRSAS_THROTTLE_QUEUE_DEPTH 16
+
+/*
+ * MSI-x regsiters offset defines
+ */
+#define MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C)
+#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
+#define MR_MAX_REPLY_QUEUES_OFFSET (0x0000001F)
+#define MR_MAX_REPLY_QUEUES_EXT_OFFSET (0x003FC000)
+#define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14
+#define MR_MAX_MSIX_REG_ARRAY 16
+
+/*
* FW reports the maximum of number of commands that it can accept (maximum
* commands that can be outstanding) at any time. The driver must report a
* lower number to the mid layer because it can issue a few internal commands
* itself (E.g, AEN, abort cmd, IOCTLs etc). The number of commands it needs
* is shown below
*/
-#define MRSAS_INT_CMDS 32
-#define MRSAS_SKINNY_INT_CMDS 5
-#define MRSAS_MAX_MSIX_QUEUES 16
+#define MRSAS_INT_CMDS 32
+#define MRSAS_SKINNY_INT_CMDS 5
+#define MRSAS_MAX_MSIX_QUEUES 128
/*
- * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
- * SGLs based on the size of bus_addr_t
+ * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit SGLs
+ * based on the size of bus_addr_t
*/
-#define IS_DMA64 (sizeof(bus_addr_t) == 8)
-
-#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT 0x00000001 // MFI state change interrupt
-#define MFI_INTR_FLAG_REPLY_MESSAGE 0x00000001
-#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE 0x00000002
-#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT 0x00000004 //MFI state change interrupt
-
-#define MFI_OB_INTR_STATUS_MASK 0x00000002
-#define MFI_POLL_TIMEOUT_SECS 60
-
-#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
-#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
-#define MFI_GEN2_ENABLE_INTERRUPT_MASK 0x00000001
-#define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT 0x40000000
-#define MFI_SKINNY_ENABLE_INTERRUPT_MASK (0x00000001)
-#define MFI_1068_PCSR_OFFSET 0x84
-#define MFI_1068_FW_HANDSHAKE_OFFSET 0x64
-#define MFI_1068_FW_READY 0xDDDD0000
+#define IS_DMA64 (sizeof(bus_addr_t) == 8)
+
+#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT 0x00000001
+#define MFI_INTR_FLAG_REPLY_MESSAGE 0x00000001
+#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE 0x00000002
+#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT 0x00000004
+
+#define MFI_OB_INTR_STATUS_MASK 0x00000002
+#define MFI_POLL_TIMEOUT_SECS 60
+
+#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
+#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
+#define MFI_GEN2_ENABLE_INTERRUPT_MASK 0x00000001
+#define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT 0x40000000
+#define MFI_SKINNY_ENABLE_INTERRUPT_MASK (0x00000001)
+#define MFI_1068_PCSR_OFFSET 0x84
+#define MFI_1068_FW_HANDSHAKE_OFFSET 0x64
+#define MFI_1068_FW_READY 0xDDDD0000
+
+typedef union _MFI_CAPABILITIES {
+ struct {
+ u_int32_t support_fp_remote_lun:1;
+ u_int32_t support_additional_msix:1;
+ u_int32_t support_fastpath_wb:1;
+ u_int32_t support_max_255lds:1;
+ u_int32_t reserved:28;
+ } mfi_capabilities;
+ u_int32_t reg;
+} MFI_CAPABILITIES;
#pragma pack(1)
struct mrsas_sge32 {
- u_int32_t phys_addr;
- u_int32_t length;
+ u_int32_t phys_addr;
+ u_int32_t length;
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_sge64 {
- u_int64_t phys_addr;
- u_int32_t length;
+ u_int64_t phys_addr;
+ u_int32_t length;
};
+
#pragma pack()
#pragma pack()
union mrsas_sgl {
- struct mrsas_sge32 sge32[1];
- struct mrsas_sge64 sge64[1];
+ struct mrsas_sge32 sge32[1];
+ struct mrsas_sge64 sge64[1];
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_header {
- u_int8_t cmd; /*00e */
- u_int8_t sense_len; /*01h */
- u_int8_t cmd_status; /*02h */
- u_int8_t scsi_status; /*03h */
-
- u_int8_t target_id; /*04h */
- u_int8_t lun; /*05h */
- u_int8_t cdb_len; /*06h */
- u_int8_t sge_count; /*07h */
-
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
-
- u_int16_t flags; /*10h */
- u_int16_t timeout; /*12h */
- u_int32_t data_xferlen; /*14h */
+ u_int8_t cmd; /* 00e */
+ u_int8_t sense_len; /* 01h */
+ u_int8_t cmd_status; /* 02h */
+ u_int8_t scsi_status; /* 03h */
+
+ u_int8_t target_id; /* 04h */
+ u_int8_t lun; /* 05h */
+ u_int8_t cdb_len; /* 06h */
+ u_int8_t sge_count; /* 07h */
+
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
+
+ u_int16_t flags; /* 10h */
+ u_int16_t timeout; /* 12h */
+ u_int32_t data_xferlen; /* 14h */
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_init_frame {
- u_int8_t cmd; /*00h */
- u_int8_t reserved_0; /*01h */
- u_int8_t cmd_status; /*02h */
-
- u_int8_t reserved_1; /*03h */
- u_int32_t reserved_2; /*04h */
-
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
-
- u_int16_t flags; /*10h */
- u_int16_t reserved_3; /*12h */
- u_int32_t data_xfer_len; /*14h */
-
- u_int32_t queue_info_new_phys_addr_lo; /*18h */
- u_int32_t queue_info_new_phys_addr_hi; /*1Ch */
- u_int32_t queue_info_old_phys_addr_lo; /*20h */
- u_int32_t queue_info_old_phys_addr_hi; /*24h */
- u_int32_t driver_ver_lo; /*28h */
- u_int32_t driver_ver_hi; /*2Ch */
- u_int32_t reserved_4[4]; /*30h */
+ u_int8_t cmd; /* 00h */
+ u_int8_t reserved_0; /* 01h */
+ u_int8_t cmd_status; /* 02h */
+
+ u_int8_t reserved_1; /* 03h */
+ MFI_CAPABILITIES driver_operations; /* 04h */
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
+
+ u_int16_t flags; /* 10h */
+ u_int16_t reserved_3; /* 12h */
+ u_int32_t data_xfer_len; /* 14h */
+
+ u_int32_t queue_info_new_phys_addr_lo; /* 18h */
+ u_int32_t queue_info_new_phys_addr_hi; /* 1Ch */
+ u_int32_t queue_info_old_phys_addr_lo; /* 20h */
+ u_int32_t queue_info_old_phys_addr_hi; /* 24h */
+ u_int32_t driver_ver_lo; /* 28h */
+ u_int32_t driver_ver_hi; /* 2Ch */
+ u_int32_t reserved_4[4]; /* 30h */
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_io_frame {
- u_int8_t cmd; /*00h */
- u_int8_t sense_len; /*01h */
- u_int8_t cmd_status; /*02h */
- u_int8_t scsi_status; /*03h */
+ u_int8_t cmd; /* 00h */
+ u_int8_t sense_len; /* 01h */
+ u_int8_t cmd_status; /* 02h */
+ u_int8_t scsi_status; /* 03h */
- u_int8_t target_id; /*04h */
- u_int8_t access_byte; /*05h */
- u_int8_t reserved_0; /*06h */
- u_int8_t sge_count; /*07h */
+ u_int8_t target_id; /* 04h */
+ u_int8_t access_byte; /* 05h */
+ u_int8_t reserved_0; /* 06h */
+ u_int8_t sge_count; /* 07h */
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
- u_int16_t flags; /*10h */
- u_int16_t timeout; /*12h */
- u_int32_t lba_count; /*14h */
+ u_int16_t flags; /* 10h */
+ u_int16_t timeout; /* 12h */
+ u_int32_t lba_count; /* 14h */
- u_int32_t sense_buf_phys_addr_lo; /*18h */
- u_int32_t sense_buf_phys_addr_hi; /*1Ch */
+ u_int32_t sense_buf_phys_addr_lo; /* 18h */
+ u_int32_t sense_buf_phys_addr_hi; /* 1Ch */
- u_int32_t start_lba_lo; /*20h */
- u_int32_t start_lba_hi; /*24h */
+ u_int32_t start_lba_lo; /* 20h */
+ u_int32_t start_lba_hi; /* 24h */
- union mrsas_sgl sgl; /*28h */
+ union mrsas_sgl sgl; /* 28h */
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_pthru_frame {
- u_int8_t cmd; /*00h */
- u_int8_t sense_len; /*01h */
- u_int8_t cmd_status; /*02h */
- u_int8_t scsi_status; /*03h */
+ u_int8_t cmd; /* 00h */
+ u_int8_t sense_len; /* 01h */
+ u_int8_t cmd_status; /* 02h */
+ u_int8_t scsi_status; /* 03h */
- u_int8_t target_id; /*04h */
- u_int8_t lun; /*05h */
- u_int8_t cdb_len; /*06h */
- u_int8_t sge_count; /*07h */
+ u_int8_t target_id; /* 04h */
+ u_int8_t lun; /* 05h */
+ u_int8_t cdb_len; /* 06h */
+ u_int8_t sge_count; /* 07h */
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
- u_int16_t flags; /*10h */
- u_int16_t timeout; /*12h */
- u_int32_t data_xfer_len; /*14h */
+ u_int16_t flags; /* 10h */
+ u_int16_t timeout; /* 12h */
+ u_int32_t data_xfer_len; /* 14h */
- u_int32_t sense_buf_phys_addr_lo; /*18h */
- u_int32_t sense_buf_phys_addr_hi; /*1Ch */
+ u_int32_t sense_buf_phys_addr_lo; /* 18h */
+ u_int32_t sense_buf_phys_addr_hi; /* 1Ch */
- u_int8_t cdb[16]; /*20h */
- union mrsas_sgl sgl; /*30h */
+ u_int8_t cdb[16]; /* 20h */
+ union mrsas_sgl sgl; /* 30h */
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_dcmd_frame {
- u_int8_t cmd; /*00h */
- u_int8_t reserved_0; /*01h */
- u_int8_t cmd_status; /*02h */
- u_int8_t reserved_1[4]; /*03h */
- u_int8_t sge_count; /*07h */
+ u_int8_t cmd; /* 00h */
+ u_int8_t reserved_0; /* 01h */
+ u_int8_t cmd_status; /* 02h */
+ u_int8_t reserved_1[4]; /* 03h */
+ u_int8_t sge_count; /* 07h */
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
- u_int16_t flags; /*10h */
- u_int16_t timeout; /*12h */
+ u_int16_t flags; /* 10h */
+ u_int16_t timeout; /* 12h */
- u_int32_t data_xfer_len; /*14h */
- u_int32_t opcode; /*18h */
+ u_int32_t data_xfer_len; /* 14h */
+ u_int32_t opcode; /* 18h */
- union { /*1Ch */
- u_int8_t b[12];
- u_int16_t s[6];
- u_int32_t w[3];
- } mbox;
+ union { /* 1Ch */
+ u_int8_t b[12];
+ u_int16_t s[6];
+ u_int32_t w[3];
+ } mbox;
- union mrsas_sgl sgl; /*28h */
+ union mrsas_sgl sgl; /* 28h */
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_abort_frame {
- u_int8_t cmd; /*00h */
- u_int8_t reserved_0; /*01h */
- u_int8_t cmd_status; /*02h */
-
- u_int8_t reserved_1; /*03h */
- u_int32_t reserved_2; /*04h */
+ u_int8_t cmd; /* 00h */
+ u_int8_t reserved_0; /* 01h */
+ u_int8_t cmd_status; /* 02h */
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
+ u_int8_t reserved_1; /* 03h */
+ MFI_CAPABILITIES driver_operations; /* 04h */
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
- u_int16_t flags; /*10h */
- u_int16_t reserved_3; /*12h */
- u_int32_t reserved_4; /*14h */
+ u_int16_t flags; /* 10h */
+ u_int16_t reserved_3; /* 12h */
+ u_int32_t reserved_4; /* 14h */
- u_int32_t abort_context; /*18h */
- u_int32_t pad_1; /*1Ch */
+ u_int32_t abort_context; /* 18h */
+ u_int32_t pad_1; /* 1Ch */
- u_int32_t abort_mfi_phys_addr_lo; /*20h */
- u_int32_t abort_mfi_phys_addr_hi; /*24h */
+ u_int32_t abort_mfi_phys_addr_lo; /* 20h */
+ u_int32_t abort_mfi_phys_addr_hi; /* 24h */
- u_int32_t reserved_5[6]; /*28h */
+ u_int32_t reserved_5[6]; /* 28h */
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_smp_frame {
- u_int8_t cmd; /*00h */
- u_int8_t reserved_1; /*01h */
- u_int8_t cmd_status; /*02h */
- u_int8_t connection_status; /*03h */
+ u_int8_t cmd; /* 00h */
+ u_int8_t reserved_1; /* 01h */
+ u_int8_t cmd_status; /* 02h */
+ u_int8_t connection_status; /* 03h */
- u_int8_t reserved_2[3]; /*04h */
- u_int8_t sge_count; /*07h */
+ u_int8_t reserved_2[3]; /* 04h */
+ u_int8_t sge_count; /* 07h */
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
- u_int16_t flags; /*10h */
- u_int16_t timeout; /*12h */
+ u_int16_t flags; /* 10h */
+ u_int16_t timeout; /* 12h */
- u_int32_t data_xfer_len; /*14h */
- u_int64_t sas_addr; /*18h */
+ u_int32_t data_xfer_len; /* 14h */
+ u_int64_t sas_addr; /* 18h */
- union {
- struct mrsas_sge32 sge32[2]; /* [0]: resp [1]: req */
- struct mrsas_sge64 sge64[2]; /* [0]: resp [1]: req */
- } sgl;
+ union {
+ struct mrsas_sge32 sge32[2]; /* [0]: resp [1]: req */
+ struct mrsas_sge64 sge64[2]; /* [0]: resp [1]: req */
+ } sgl;
};
+
#pragma pack()
#pragma pack(1)
struct mrsas_stp_frame {
- u_int8_t cmd; /*00h */
- u_int8_t reserved_1; /*01h */
- u_int8_t cmd_status; /*02h */
- u_int8_t reserved_2; /*03h */
+ u_int8_t cmd; /* 00h */
+ u_int8_t reserved_1; /* 01h */
+ u_int8_t cmd_status; /* 02h */
+ u_int8_t reserved_2; /* 03h */
- u_int8_t target_id; /*04h */
- u_int8_t reserved_3[2]; /*05h */
- u_int8_t sge_count; /*07h */
+ u_int8_t target_id; /* 04h */
+ u_int8_t reserved_3[2]; /* 05h */
+ u_int8_t sge_count; /* 07h */
- u_int32_t context; /*08h */
- u_int32_t pad_0; /*0Ch */
+ u_int32_t context; /* 08h */
+ u_int32_t pad_0; /* 0Ch */
- u_int16_t flags; /*10h */
- u_int16_t timeout; /*12h */
+ u_int16_t flags; /* 10h */
+ u_int16_t timeout; /* 12h */
- u_int32_t data_xfer_len; /*14h */
+ u_int32_t data_xfer_len; /* 14h */
- u_int16_t fis[10]; /*18h */
- u_int32_t stp_flags;
+ u_int16_t fis[10]; /* 18h */
+ u_int32_t stp_flags;
- union {
- struct mrsas_sge32 sge32[2]; /* [0]: resp [1]: data */
- struct mrsas_sge64 sge64[2]; /* [0]: resp [1]: data */
- } sgl;
+ union {
+ struct mrsas_sge32 sge32[2]; /* [0]: resp [1]: data */
+ struct mrsas_sge64 sge64[2]; /* [0]: resp [1]: data */
+ } sgl;
};
+
#pragma pack()
union mrsas_frame {
- struct mrsas_header hdr;
- struct mrsas_init_frame init;
- struct mrsas_io_frame io;
- struct mrsas_pthru_frame pthru;
- struct mrsas_dcmd_frame dcmd;
- struct mrsas_abort_frame abort;
- struct mrsas_smp_frame smp;
- struct mrsas_stp_frame stp;
- u_int8_t raw_bytes[64];
+ struct mrsas_header hdr;
+ struct mrsas_init_frame init;
+ struct mrsas_io_frame io;
+ struct mrsas_pthru_frame pthru;
+ struct mrsas_dcmd_frame dcmd;
+ struct mrsas_abort_frame abort;
+ struct mrsas_smp_frame smp;
+ struct mrsas_stp_frame stp;
+ u_int8_t raw_bytes[64];
};
#pragma pack(1)
union mrsas_evt_class_locale {
- struct {
- u_int16_t locale;
- u_int8_t reserved;
- int8_t class;
- } __packed members;
-
- u_int32_t word;
-
+ struct {
+ u_int16_t locale;
+ u_int8_t reserved;
+ int8_t class;
+ } __packed members;
+
+ u_int32_t word;
+
} __packed;
#pragma pack()
@@ -2151,12 +2246,12 @@ union mrsas_evt_class_locale {
#pragma pack(1)
struct mrsas_evt_log_info {
- u_int32_t newest_seq_num;
- u_int32_t oldest_seq_num;
- u_int32_t clear_seq_num;
- u_int32_t shutdown_seq_num;
- u_int32_t boot_seq_num;
-
+ u_int32_t newest_seq_num;
+ u_int32_t oldest_seq_num;
+ u_int32_t clear_seq_num;
+ u_int32_t shutdown_seq_num;
+ u_int32_t boot_seq_num;
+
} __packed;
#pragma pack()
@@ -2280,7 +2375,7 @@ struct mrsas_evt_detail {
} __packed pci;
u_int32_t rate;
- char str[96];
+ char str[96];
struct {
u_int32_t rtc;
@@ -2290,175 +2385,213 @@ struct mrsas_evt_detail {
struct {
u_int32_t ecar;
u_int32_t elog;
- char str[64];
+ char str[64];
} __packed ecc;
u_int8_t b[96];
u_int16_t s[48];
u_int32_t w[24];
u_int64_t d[12];
- } args;
+ } args;
- char description[128];
+ char description[128];
} __packed;
+struct mrsas_irq_context {
+ struct mrsas_softc *sc;
+ uint32_t MSIxIndex;
+};
+
+/* Controller management info added to support Linux Emulator */
+#define MAX_MGMT_ADAPTERS 1024
+
+struct mrsas_mgmt_info {
+ u_int16_t count;
+ struct mrsas_softc *sc_ptr[MAX_MGMT_ADAPTERS];
+ int max_index;
+};
/*******************************************************************
* per-instance data
********************************************************************/
struct mrsas_softc {
- device_t mrsas_dev; // bus device
- struct cdev *mrsas_cdev; // controller device
- uint16_t device_id; // pci device
- struct resource *reg_res; // register interface window
- int reg_res_id; // register resource id
- bus_space_tag_t bus_tag; // bus space tag
- bus_space_handle_t bus_handle; // bus space handle
- bus_dma_tag_t mrsas_parent_tag; // bus dma parent tag
- bus_dma_tag_t verbuf_tag; // verbuf tag
- bus_dmamap_t verbuf_dmamap; // verbuf dmamap
- void *verbuf_mem; // verbuf mem
- bus_addr_t verbuf_phys_addr; // verbuf physical addr
- bus_dma_tag_t sense_tag; // bus dma verbuf tag
- bus_dmamap_t sense_dmamap; // bus dma verbuf dmamap
- void *sense_mem; // pointer to sense buf
- bus_addr_t sense_phys_addr; // bus dma verbuf mem
- bus_dma_tag_t io_request_tag; // bus dma io request tag
- bus_dmamap_t io_request_dmamap; // bus dma io request dmamap
- void *io_request_mem; // bus dma io request mem
- bus_addr_t io_request_phys_addr; // io request physical address
- bus_dma_tag_t chain_frame_tag; // bus dma chain frame tag
- bus_dmamap_t chain_frame_dmamap; // bus dma chain frame dmamap
- void *chain_frame_mem; // bus dma chain frame mem
- bus_addr_t chain_frame_phys_addr; // chain frame phys address
- bus_dma_tag_t reply_desc_tag; // bus dma io request tag
- bus_dmamap_t reply_desc_dmamap; // bus dma io request dmamap
- void *reply_desc_mem; // bus dma io request mem
- bus_addr_t reply_desc_phys_addr; // bus dma io request mem
- bus_dma_tag_t ioc_init_tag; // bus dma io request tag
- bus_dmamap_t ioc_init_dmamap; // bus dma io request dmamap
- void *ioc_init_mem; // bus dma io request mem
- bus_addr_t ioc_init_phys_mem; // io request physical address
- bus_dma_tag_t data_tag; // bus dma data from OS tag
- struct cam_sim *sim_0; // SIM pointer
- struct cam_sim *sim_1; // SIM pointer
- struct cam_path *path_0; // ldio path pointer to CAM
- struct cam_path *path_1; // syspd path pointer to CAM
- struct mtx sim_lock; // sim lock
- struct mtx pci_lock; // serialize pci access
- struct mtx io_lock; // IO lock
- struct mtx ioctl_lock; // IOCTL lock
- struct mtx mpt_cmd_pool_lock; // lock for cmd pool linked list
- struct mtx mfi_cmd_pool_lock; // lock for cmd pool linked list
- struct mtx raidmap_lock; // lock for raid map access/update
- struct mtx aen_lock; // aen lock
- uint32_t max_fw_cmds; // Max commands from FW
- uint32_t max_num_sge; // Max number of SGEs
- struct resource *mrsas_irq; // interrupt interface window
- void *intr_handle; // handle
- int irq_id; // intr resource id
- struct mrsas_mpt_cmd **mpt_cmd_list;
- struct mrsas_mfi_cmd **mfi_cmd_list;
- TAILQ_HEAD(, mrsas_mpt_cmd) mrsas_mpt_cmd_list_head;
- TAILQ_HEAD(, mrsas_mfi_cmd) mrsas_mfi_cmd_list_head;
- bus_addr_t req_frames_desc_phys;
- u_int8_t *req_frames_desc;
- u_int8_t *req_desc;
- bus_addr_t io_request_frames_phys;
- u_int8_t *io_request_frames;
- bus_addr_t reply_frames_desc_phys;
- u_int16_t last_reply_idx;
- u_int32_t reply_q_depth;
- u_int32_t request_alloc_sz;
- u_int32_t reply_alloc_sz;
- u_int32_t io_frames_alloc_sz;
- u_int32_t chain_frames_alloc_sz;
- u_int16_t max_sge_in_main_msg;
- u_int16_t max_sge_in_chain;
- u_int8_t chain_offset_io_request;
- u_int8_t chain_offset_mfi_pthru;
- u_int32_t map_sz;
- u_int64_t map_id;
- struct mrsas_mfi_cmd *map_update_cmd;
- struct mrsas_mfi_cmd *aen_cmd;
- u_int8_t fast_path_io;
- void* chan;
- void* ocr_chan;
- u_int8_t adprecovery;
- u_int8_t remove_in_progress;
- u_int8_t ocr_thread_active;
- u_int8_t do_timedout_reset;
- u_int32_t reset_in_progress;
- u_int32_t reset_count;
- bus_dma_tag_t raidmap_tag[2]; // bus dma tag for RAID map
- bus_dmamap_t raidmap_dmamap[2]; // bus dma dmamap RAID map
- void *raidmap_mem[2]; // bus dma mem RAID map
- bus_addr_t raidmap_phys_addr[2]; // RAID map physical address
- bus_dma_tag_t mficmd_frame_tag; // tag for mfi frame
- bus_dma_tag_t mficmd_sense_tag; // tag for mfi sense
- bus_dma_tag_t evt_detail_tag; // event detail tag
- bus_dmamap_t evt_detail_dmamap; // event detail dmamap
- struct mrsas_evt_detail *evt_detail_mem; // event detail mem
- bus_addr_t evt_detail_phys_addr; // event detail physical addr
- bus_dma_tag_t ctlr_info_tag; // tag for get ctlr info cmd
- bus_dmamap_t ctlr_info_dmamap; // get ctlr info cmd dmamap
- void *ctlr_info_mem; // get ctlr info cmd virtual addr
- bus_addr_t ctlr_info_phys_addr; //get ctlr info cmd physical addr
- u_int32_t max_sectors_per_req;
- u_int8_t disableOnlineCtrlReset;
- atomic_t fw_outstanding;
- u_int32_t mrsas_debug;
- u_int32_t mrsas_io_timeout;
- u_int32_t mrsas_fw_fault_check_delay;
- u_int32_t io_cmds_highwater;
- u_int8_t UnevenSpanSupport;
- struct sysctl_ctx_list sysctl_ctx;
- struct sysctl_oid *sysctl_tree;
- struct proc *ocr_thread;
- u_int32_t last_seq_num;
- bus_dma_tag_t el_info_tag; // tag for get event log info cmd
- bus_dmamap_t el_info_dmamap; // get event log info cmd dmamap
- void *el_info_mem; // get event log info cmd virtual addr
- bus_addr_t el_info_phys_addr; //get event log info cmd physical addr
- struct mrsas_pd_list pd_list[MRSAS_MAX_PD];
- struct mrsas_pd_list local_pd_list[MRSAS_MAX_PD];
- u_int8_t ld_ids[MRSAS_MAX_LD];
- struct taskqueue *ev_tq; //taskqueue for events
- struct task ev_task;
- u_int32_t CurLdCount;
- u_int64_t reset_flags;
- LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
- LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES];
+ device_t mrsas_dev;
+ struct cdev *mrsas_cdev;
+ uint16_t device_id;
+ struct resource *reg_res;
+ int reg_res_id;
+ bus_space_tag_t bus_tag;
+ bus_space_handle_t bus_handle;
+ bus_dma_tag_t mrsas_parent_tag;
+ bus_dma_tag_t verbuf_tag;
+ bus_dmamap_t verbuf_dmamap;
+ void *verbuf_mem;
+ bus_addr_t verbuf_phys_addr;
+ bus_dma_tag_t sense_tag;
+ bus_dmamap_t sense_dmamap;
+ void *sense_mem;
+ bus_addr_t sense_phys_addr;
+ bus_dma_tag_t io_request_tag;
+ bus_dmamap_t io_request_dmamap;
+ void *io_request_mem;
+ bus_addr_t io_request_phys_addr;
+ bus_dma_tag_t chain_frame_tag;
+ bus_dmamap_t chain_frame_dmamap;
+ void *chain_frame_mem;
+ bus_addr_t chain_frame_phys_addr;
+ bus_dma_tag_t reply_desc_tag;
+ bus_dmamap_t reply_desc_dmamap;
+ void *reply_desc_mem;
+ bus_addr_t reply_desc_phys_addr;
+ bus_dma_tag_t ioc_init_tag;
+ bus_dmamap_t ioc_init_dmamap;
+ void *ioc_init_mem;
+ bus_addr_t ioc_init_phys_mem;
+ bus_dma_tag_t data_tag;
+ struct cam_sim *sim_0;
+ struct cam_sim *sim_1;
+ struct cam_path *path_0;
+ struct cam_path *path_1;
+ struct mtx sim_lock;
+ struct mtx pci_lock;
+ struct mtx io_lock;
+ struct mtx ioctl_lock;
+ struct mtx mpt_cmd_pool_lock;
+ struct mtx mfi_cmd_pool_lock;
+ struct mtx raidmap_lock;
+ struct mtx aen_lock;
+ struct selinfo mrsas_select;
+ uint32_t mrsas_aen_triggered;
+ uint32_t mrsas_poll_waiting;
+
+ struct sema ioctl_count_sema;
+ uint32_t max_fw_cmds;
+ uint32_t max_num_sge;
+ struct resource *mrsas_irq[MAX_MSIX_COUNT];
+ void *intr_handle[MAX_MSIX_COUNT];
+ int irq_id[MAX_MSIX_COUNT];
+ struct mrsas_irq_context irq_context[MAX_MSIX_COUNT];
+ int msix_vectors;
+ int msix_enable;
+ uint32_t msix_reg_offset[16];
+ struct mrsas_mpt_cmd **mpt_cmd_list;
+ struct mrsas_mfi_cmd **mfi_cmd_list;
+ TAILQ_HEAD(, mrsas_mpt_cmd) mrsas_mpt_cmd_list_head;
+ TAILQ_HEAD(, mrsas_mfi_cmd) mrsas_mfi_cmd_list_head;
+ bus_addr_t req_frames_desc_phys;
+ u_int8_t *req_frames_desc;
+ u_int8_t *req_desc;
+ bus_addr_t io_request_frames_phys;
+ u_int8_t *io_request_frames;
+ bus_addr_t reply_frames_desc_phys;
+ u_int16_t last_reply_idx[MAX_MSIX_COUNT];
+ u_int32_t reply_q_depth;
+ u_int32_t request_alloc_sz;
+ u_int32_t reply_alloc_sz;
+ u_int32_t io_frames_alloc_sz;
+ u_int32_t chain_frames_alloc_sz;
+ u_int16_t max_sge_in_main_msg;
+ u_int16_t max_sge_in_chain;
+ u_int8_t chain_offset_io_request;
+ u_int8_t chain_offset_mfi_pthru;
+ u_int32_t map_sz;
+ u_int64_t map_id;
+ struct mrsas_mfi_cmd *map_update_cmd;
+ struct mrsas_mfi_cmd *aen_cmd;
+ u_int8_t fast_path_io;
+ void *chan;
+ void *ocr_chan;
+ u_int8_t adprecovery;
+ u_int8_t remove_in_progress;
+ u_int8_t ocr_thread_active;
+ u_int8_t do_timedout_reset;
+ u_int32_t reset_in_progress;
+ u_int32_t reset_count;
+ bus_dma_tag_t raidmap_tag[2];
+ bus_dmamap_t raidmap_dmamap[2];
+ void *raidmap_mem[2];
+ bus_addr_t raidmap_phys_addr[2];
+ bus_dma_tag_t mficmd_frame_tag;
+ bus_dma_tag_t mficmd_sense_tag;
+ bus_dma_tag_t evt_detail_tag;
+ bus_dmamap_t evt_detail_dmamap;
+ struct mrsas_evt_detail *evt_detail_mem;
+ bus_addr_t evt_detail_phys_addr;
+ bus_dma_tag_t ctlr_info_tag;
+ bus_dmamap_t ctlr_info_dmamap;
+ void *ctlr_info_mem;
+ bus_addr_t ctlr_info_phys_addr;
+ u_int32_t max_sectors_per_req;
+ u_int8_t disableOnlineCtrlReset;
+ atomic_t fw_outstanding;
+ u_int32_t mrsas_debug;
+ u_int32_t mrsas_io_timeout;
+ u_int32_t mrsas_fw_fault_check_delay;
+ u_int32_t io_cmds_highwater;
+ u_int8_t UnevenSpanSupport;
+ struct sysctl_ctx_list sysctl_ctx;
+ struct sysctl_oid *sysctl_tree;
+ struct proc *ocr_thread;
+ u_int32_t last_seq_num;
+ bus_dma_tag_t el_info_tag;
+ bus_dmamap_t el_info_dmamap;
+ void *el_info_mem;
+ bus_addr_t el_info_phys_addr;
+ struct mrsas_pd_list pd_list[MRSAS_MAX_PD];
+ struct mrsas_pd_list local_pd_list[MRSAS_MAX_PD];
+ u_int8_t ld_ids[MRSAS_MAX_LD_IDS];
+ struct taskqueue *ev_tq;
+ struct task ev_task;
+ u_int32_t CurLdCount;
+ u_int64_t reset_flags;
+ LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT];
+ LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
+
+ u_int8_t max256vdSupport;
+ u_int16_t fw_supported_vd_count;
+ u_int16_t fw_supported_pd_count;
+
+ u_int16_t drv_supported_vd_count;
+ u_int16_t drv_supported_pd_count;
+
+ u_int32_t max_map_sz;
+ u_int32_t current_map_sz;
+ u_int32_t old_map_sz;
+ u_int32_t new_map_sz;
+ u_int32_t drv_map_sz;
+
+ /* Non dma-able memory. Driver local copy. */
+ MR_DRV_RAID_MAP_ALL *ld_drv_map[2];
};
/* Compatibility shims for different OS versions */
#if __FreeBSD_version >= 800001
-#define mrsas_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
+#define mrsas_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg)
-#define mrsas_kproc_exit(arg) kproc_exit(arg)
+#define mrsas_kproc_exit(arg) kproc_exit(arg)
#else
-#define mrsas_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
+#define mrsas_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg)
-#define mrsas_kproc_exit(arg) kthread_exit(arg)
+#define mrsas_kproc_exit(arg) kthread_exit(arg)
#endif
static __inline void
clear_bit(int b, volatile void *p)
{
- atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
+ atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
}
static __inline void
set_bit(int b, volatile void *p)
{
- atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
+ atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f));
}
static __inline int
test_bit(int b, volatile void *p)
{
- return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f));
+ return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f));
}
-#endif /* MRSAS_H */
+#endif /* MRSAS_H */
diff --git a/sys/dev/mrsas/mrsas_cam.c b/sys/dev/mrsas/mrsas_cam.c
index bde974a..c454f7b 100644
--- a/sys/dev/mrsas/mrsas_cam.c
+++ b/sys/dev/mrsas/mrsas_cam.c
@@ -1,42 +1,38 @@
/*
- * Copyright (c) 2014, LSI Corp.
- * All rights reserved.
- * Author: Marian Choy
+ * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
* Support: freebsdraid@lsi.com
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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 <ORGANIZATION> nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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
+ * <ORGANIZATION> 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 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 HOLDER 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
+ * 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 HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
-*/
+ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "dev/mrsas/mrsas.h"
+#include "dev/mrsas/mrsas.h"
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -49,725 +45,735 @@ __FBSDID("$FreeBSD$");
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
#include <sys/taskqueue.h>
+#include <sys/kernel.h>
+
+
+#include <sys/time.h> /* XXX for pcpu.h */
+#include <sys/pcpu.h> /* XXX for PCPU_GET */
+#define smp_processor_id() PCPU_GET(cpuid)
/*
* Function prototypes
*/
-int mrsas_cam_attach(struct mrsas_softc *sc);
-//int mrsas_ldio_inq(union ccb *ccb);
-int mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb);
-int mrsas_bus_scan(struct mrsas_softc *sc);
-int mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim);
-int mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd);
-int mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
- union ccb *ccb);
-int mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
- union ccb *ccb, struct cam_sim *sim);
-int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
- union ccb *ccb, u_int32_t device_id,
- MRSAS_RAID_SCSI_IO_REQUEST *io_request);
-void mrsas_xpt_freeze(struct mrsas_softc *sc);
-void mrsas_xpt_release(struct mrsas_softc *sc);
-void mrsas_cam_detach(struct mrsas_softc *sc);
-void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd);
-void mrsas_unmap_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd);
-void mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd);
-void mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo,
- u_int32_t req_desc_hi);
-void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST *io_request, u_int8_t cdb_len,
- struct IO_REQUEST_INFO *io_info, union ccb *ccb,
- MR_FW_RAID_MAP_ALL *local_map_ptr, u_int32_t ref_tag,
- u_int32_t ld_block_size);
+int mrsas_cam_attach(struct mrsas_softc *sc);
+int mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb);
+int mrsas_bus_scan(struct mrsas_softc *sc);
+int mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim);
+int mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd);
+int
+mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
+ union ccb *ccb);
+int
+mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
+ union ccb *ccb, struct cam_sim *sim);
+int
+mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
+ union ccb *ccb, u_int32_t device_id,
+ MRSAS_RAID_SCSI_IO_REQUEST * io_request);
+void mrsas_xpt_freeze(struct mrsas_softc *sc);
+void mrsas_xpt_release(struct mrsas_softc *sc);
+void mrsas_cam_detach(struct mrsas_softc *sc);
+void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd);
+void mrsas_unmap_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd);
+void mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd);
+void
+mrsas_fire_cmd(struct mrsas_softc *sc, u_int32_t req_desc_lo,
+ u_int32_t req_desc_hi);
+void
+mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request,
+ u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb,
+ MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag,
+ u_int32_t ld_block_size);
static void mrsas_freeze_simq(struct mrsas_mpt_cmd *cmd, struct cam_sim *sim);
-static void mrsas_poll(struct cam_sim *sim);
+static void mrsas_cam_poll(struct cam_sim *sim);
static void mrsas_action(struct cam_sim *sim, union ccb *ccb);
static void mrsas_scsiio_timeout(void *data);
-static void mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs,
- int nseg, int error);
-static int32_t mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim,
- union ccb *ccb);
-struct mrsas_mpt_cmd * mrsas_get_mpt_cmd(struct mrsas_softc *sc);
-MRSAS_REQUEST_DESCRIPTOR_UNION *mrsas_get_request_desc(struct mrsas_softc *sc,
- u_int16_t index);
-
-extern u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map);
-extern u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map,
+static void
+mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs,
+ int nseg, int error);
+static int32_t
+mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim,
+ union ccb *ccb);
+struct mrsas_mpt_cmd *mrsas_get_mpt_cmd(struct mrsas_softc *sc);
+MRSAS_REQUEST_DESCRIPTOR_UNION *
+ mrsas_get_request_desc(struct mrsas_softc *sc, u_int16_t index);
+
+extern u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map);
+extern u_int32_t
+MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map,
struct mrsas_softc *sc);
extern void mrsas_isr(void *arg);
extern void mrsas_aen_handler(struct mrsas_softc *sc);
-extern u_int8_t MR_BuildRaidContext(struct mrsas_softc *sc,
- struct IO_REQUEST_INFO *io_info,RAID_CONTEXT *pRAID_Context,
- MR_FW_RAID_MAP_ALL *map);
-extern u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span,
- MR_FW_RAID_MAP_ALL *map);
-extern u_int16_t mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo,
- struct IO_REQUEST_INFO *io_info);
-extern u_int8_t megasas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm,
- u_int64_t block, u_int32_t count);
-
-
-/**
- * mrsas_cam_attach: Main entry to CAM subsystem
- * input: Adapter instance soft state
+extern u_int8_t
+MR_BuildRaidContext(struct mrsas_softc *sc,
+ struct IO_REQUEST_INFO *io_info, RAID_CONTEXT * pRAID_Context,
+ MR_DRV_RAID_MAP_ALL * map);
+extern u_int16_t
+MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span,
+ MR_DRV_RAID_MAP_ALL * map);
+extern u_int16_t
+mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo,
+ struct IO_REQUEST_INFO *io_info);
+extern u_int8_t
+megasas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm,
+ u_int64_t block, u_int32_t count);
+
+
+/*
+ * mrsas_cam_attach: Main entry to CAM subsystem
+ * input: Adapter instance soft state
*
- * This function is called from mrsas_attach() during initialization
- * to perform SIM allocations and XPT bus registration. If the kernel
- * version is 7.4 or earlier, it would also initiate a bus scan.
+ * This function is called from mrsas_attach() during initialization to perform
+ * SIM allocations and XPT bus registration. If the kernel version is 7.4 or
+ * earlier, it would also initiate a bus scan.
*/
-int mrsas_cam_attach(struct mrsas_softc *sc)
+int
+mrsas_cam_attach(struct mrsas_softc *sc)
{
- struct cam_devq *devq;
- int mrsas_cam_depth;
-
- mrsas_cam_depth = sc->max_fw_cmds - MRSAS_INTERNAL_CMDS;
-
- if ((devq = cam_simq_alloc(mrsas_cam_depth)) == NULL) {
- device_printf(sc->mrsas_dev, "Cannot allocate SIM queue\n");
- return(ENOMEM);
- }
-
-
- /*
- * Create SIM for bus 0 and register, also create path
- */
- sc->sim_0 = cam_sim_alloc(mrsas_action, mrsas_poll, "mrsas", sc,
- device_get_unit(sc->mrsas_dev), &sc->sim_lock, mrsas_cam_depth,
- mrsas_cam_depth, devq);
- if (sc->sim_0 == NULL){
- cam_simq_free(devq);
- device_printf(sc->mrsas_dev, "Cannot register SIM\n");
- return(ENXIO);
- }
- /* Initialize taskqueue for Event Handling */
- TASK_INIT(&sc->ev_task, 0, (void *)mrsas_aen_handler, sc);
- sc->ev_tq = taskqueue_create("mrsas_taskq", M_NOWAIT | M_ZERO,
- taskqueue_thread_enqueue, &sc->ev_tq);
-
- /* Run the task queue with lowest priority */
- taskqueue_start_threads(&sc->ev_tq, 1, 255, "%s taskq",
- device_get_nameunit(sc->mrsas_dev));
- mtx_lock(&sc->sim_lock);
- if (xpt_bus_register(sc->sim_0, sc->mrsas_dev,0) != CAM_SUCCESS)
- {
- cam_sim_free(sc->sim_0, TRUE); // passing true frees the devq
- mtx_unlock(&sc->sim_lock);
- return(ENXIO);
- }
- if (xpt_create_path(&sc->path_0, NULL, cam_sim_path(sc->sim_0),
- CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- xpt_bus_deregister(cam_sim_path(sc->sim_0));
- cam_sim_free(sc->sim_0, TRUE); // passing true will free the devq
- mtx_unlock(&sc->sim_lock);
- return(ENXIO);
- }
- mtx_unlock(&sc->sim_lock);
-
- /*
- * Create SIM for bus 1 and register, also create path
- */
- sc->sim_1 = cam_sim_alloc(mrsas_action, mrsas_poll, "mrsas", sc,
- device_get_unit(sc->mrsas_dev), &sc->sim_lock, mrsas_cam_depth,
- mrsas_cam_depth, devq);
- if (sc->sim_1 == NULL){
- cam_simq_free(devq);
- device_printf(sc->mrsas_dev, "Cannot register SIM\n");
- return(ENXIO);
- }
-
- mtx_lock(&sc->sim_lock);
- if (xpt_bus_register(sc->sim_1, sc->mrsas_dev, 1) != CAM_SUCCESS){
- cam_sim_free(sc->sim_1, TRUE); // passing true frees the devq
- mtx_unlock(&sc->sim_lock);
- return(ENXIO);
- }
- if (xpt_create_path(&sc->path_1, NULL, cam_sim_path(sc->sim_1),
- CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- xpt_bus_deregister(cam_sim_path(sc->sim_1));
- cam_sim_free(sc->sim_1, TRUE);
- mtx_unlock(&sc->sim_lock);
- return(ENXIO);
- }
- mtx_unlock(&sc->sim_lock);
+ struct cam_devq *devq;
+ int mrsas_cam_depth;
+
+ mrsas_cam_depth = sc->max_fw_cmds - MRSAS_INTERNAL_CMDS;
+
+ if ((devq = cam_simq_alloc(mrsas_cam_depth)) == NULL) {
+ device_printf(sc->mrsas_dev, "Cannot allocate SIM queue\n");
+ return (ENOMEM);
+ }
+ /*
+ * Create SIM for bus 0 and register, also create path
+ */
+ sc->sim_0 = cam_sim_alloc(mrsas_action, mrsas_cam_poll, "mrsas", sc,
+ device_get_unit(sc->mrsas_dev), &sc->sim_lock, mrsas_cam_depth,
+ mrsas_cam_depth, devq);
+ if (sc->sim_0 == NULL) {
+ cam_simq_free(devq);
+ device_printf(sc->mrsas_dev, "Cannot register SIM\n");
+ return (ENXIO);
+ }
+ /* Initialize taskqueue for Event Handling */
+ TASK_INIT(&sc->ev_task, 0, (void *)mrsas_aen_handler, sc);
+ sc->ev_tq = taskqueue_create("mrsas_taskq", M_NOWAIT | M_ZERO,
+ taskqueue_thread_enqueue, &sc->ev_tq);
+
+ /* Run the task queue with lowest priority */
+ taskqueue_start_threads(&sc->ev_tq, 1, 255, "%s taskq",
+ device_get_nameunit(sc->mrsas_dev));
+ mtx_lock(&sc->sim_lock);
+ if (xpt_bus_register(sc->sim_0, sc->mrsas_dev, 0) != CAM_SUCCESS) {
+ cam_sim_free(sc->sim_0, TRUE); /* passing true frees the devq */
+ mtx_unlock(&sc->sim_lock);
+ return (ENXIO);
+ }
+ if (xpt_create_path(&sc->path_0, NULL, cam_sim_path(sc->sim_0),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_bus_deregister(cam_sim_path(sc->sim_0));
+ cam_sim_free(sc->sim_0, TRUE); /* passing true will free the
+ * devq */
+ mtx_unlock(&sc->sim_lock);
+ return (ENXIO);
+ }
+ mtx_unlock(&sc->sim_lock);
+
+ /*
+ * Create SIM for bus 1 and register, also create path
+ */
+ sc->sim_1 = cam_sim_alloc(mrsas_action, mrsas_cam_poll, "mrsas", sc,
+ device_get_unit(sc->mrsas_dev), &sc->sim_lock, mrsas_cam_depth,
+ mrsas_cam_depth, devq);
+ if (sc->sim_1 == NULL) {
+ cam_simq_free(devq);
+ device_printf(sc->mrsas_dev, "Cannot register SIM\n");
+ return (ENXIO);
+ }
+ mtx_lock(&sc->sim_lock);
+ if (xpt_bus_register(sc->sim_1, sc->mrsas_dev, 1) != CAM_SUCCESS) {
+ cam_sim_free(sc->sim_1, TRUE); /* passing true frees the devq */
+ mtx_unlock(&sc->sim_lock);
+ return (ENXIO);
+ }
+ if (xpt_create_path(&sc->path_1, NULL, cam_sim_path(sc->sim_1),
+ CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_bus_deregister(cam_sim_path(sc->sim_1));
+ cam_sim_free(sc->sim_1, TRUE);
+ mtx_unlock(&sc->sim_lock);
+ return (ENXIO);
+ }
+ mtx_unlock(&sc->sim_lock);
#if (__FreeBSD_version <= 704000)
- if (mrsas_bus_scan(sc)){
- device_printf(sc->mrsas_dev, "Error in bus scan.\n");
- return(1);
- }
+ if (mrsas_bus_scan(sc)) {
+ device_printf(sc->mrsas_dev, "Error in bus scan.\n");
+ return (1);
+ }
#endif
- return(0);
+ return (0);
}
-/**
- * mrsas_cam_detach: De-allocates and teardown CAM
- * input: Adapter instance soft state
+/*
+ * mrsas_cam_detach: De-allocates and teardown CAM
+ * input: Adapter instance soft state
*
- * De-registers and frees the paths and SIMs.
+ * De-registers and frees the paths and SIMs.
*/
-void mrsas_cam_detach(struct mrsas_softc *sc)
+void
+mrsas_cam_detach(struct mrsas_softc *sc)
{
if (sc->ev_tq != NULL)
- taskqueue_free(sc->ev_tq);
- mtx_lock(&sc->sim_lock);
- if (sc->path_0)
- xpt_free_path(sc->path_0);
- if (sc->sim_0) {
- xpt_bus_deregister(cam_sim_path(sc->sim_0));
- cam_sim_free(sc->sim_0, FALSE);
- }
- if (sc->path_1)
- xpt_free_path(sc->path_1);
- if (sc->sim_1) {
- xpt_bus_deregister(cam_sim_path(sc->sim_1));
- cam_sim_free(sc->sim_1, TRUE);
- }
- mtx_unlock(&sc->sim_lock);
+ taskqueue_free(sc->ev_tq);
+ mtx_lock(&sc->sim_lock);
+ if (sc->path_0)
+ xpt_free_path(sc->path_0);
+ if (sc->sim_0) {
+ xpt_bus_deregister(cam_sim_path(sc->sim_0));
+ cam_sim_free(sc->sim_0, FALSE);
+ }
+ if (sc->path_1)
+ xpt_free_path(sc->path_1);
+ if (sc->sim_1) {
+ xpt_bus_deregister(cam_sim_path(sc->sim_1));
+ cam_sim_free(sc->sim_1, TRUE);
+ }
+ mtx_unlock(&sc->sim_lock);
}
-/**
- * mrsas_action: SIM callback entry point
- * input: pointer to SIM
- * pointer to CAM Control Block
+/*
+ * mrsas_action: SIM callback entry point
+ * input: pointer to SIM pointer to CAM Control Block
*
- * This function processes CAM subsystem requests. The type of request is
- * stored in ccb->ccb_h.func_code. The preprocessor #ifdef is necessary
- * because ccb->cpi.maxio is not supported for FreeBSD version 7.4 or
- * earlier.
+ * This function processes CAM subsystem requests. The type of request is stored
+ * in ccb->ccb_h.func_code. The preprocessor #ifdef is necessary because
+ * ccb->cpi.maxio is not supported for FreeBSD version 7.4 or earlier.
*/
-static void mrsas_action(struct cam_sim *sim, union ccb *ccb)
+static void
+mrsas_action(struct cam_sim *sim, union ccb *ccb)
{
- struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim);
- struct ccb_hdr *ccb_h = &(ccb->ccb_h);
- u_int32_t device_id;
-
- switch (ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- {
- device_id = ccb_h->target_id;
-
- /*
- * bus 0 is LD, bus 1 is for system-PD
- */
- if (cam_sim_bus(sim) == 1 &&
- sc->pd_list[device_id].driveState != MR_PD_STATE_SYSTEM) {
- ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
- xpt_done(ccb);
- }
- else {
- if (mrsas_startio(sc, sim, ccb)){
- ccb->ccb_h.status |= CAM_REQ_INVALID;
- xpt_done(ccb);
- }
- }
- break;
- }
- case XPT_ABORT:
- {
- ccb->ccb_h.status = CAM_UA_ABORT;
- xpt_done(ccb);
- break;
- }
- case XPT_RESET_BUS:
- {
- xpt_done(ccb);
- break;
- }
- case XPT_GET_TRAN_SETTINGS:
- {
- ccb->cts.protocol = PROTO_SCSI;
- ccb->cts.protocol_version = SCSI_REV_2;
- ccb->cts.transport = XPORT_SPI;
- ccb->cts.transport_version = 2;
- ccb->cts.xport_specific.spi.valid = CTS_SPI_VALID_DISC;
- ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB;
- ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
- ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- case XPT_SET_TRAN_SETTINGS:
- {
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- xpt_done(ccb);
- break;
- }
- case XPT_CALC_GEOMETRY:
- {
- cam_calc_geometry(&ccb->ccg, 1);
- xpt_done(ccb);
- break;
- }
- case XPT_PATH_INQ:
- {
- ccb->cpi.version_num = 1;
- ccb->cpi.hba_inquiry = 0;
- ccb->cpi.target_sprt = 0;
- ccb->cpi.hba_misc = 0;
- ccb->cpi.hba_eng_cnt = 0;
- ccb->cpi.max_lun = MRSAS_SCSI_MAX_LUNS;
- ccb->cpi.unit_number = cam_sim_unit(sim);
- ccb->cpi.bus_id = cam_sim_bus(sim);
- ccb->cpi.initiator_id = MRSAS_SCSI_INITIATOR_ID;
- ccb->cpi.base_transfer_speed = 150000;
- strncpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN);
- strncpy(ccb->cpi.hba_vid, "LSI", HBA_IDLEN);
- strncpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN);
- ccb->cpi.transport = XPORT_SPI;
- ccb->cpi.transport_version = 2;
- ccb->cpi.protocol = PROTO_SCSI;
- ccb->cpi.protocol_version = SCSI_REV_2;
- if (ccb->cpi.bus_id == 0)
- ccb->cpi.max_target = MRSAS_MAX_LD-1;
- else
- ccb->cpi.max_target = MRSAS_MAX_PD-1;
+ struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim);
+ struct ccb_hdr *ccb_h = &(ccb->ccb_h);
+ u_int32_t device_id;
+
+ switch (ccb->ccb_h.func_code) {
+ case XPT_SCSI_IO:
+ {
+ device_id = ccb_h->target_id;
+
+ /*
+ * bus 0 is LD, bus 1 is for system-PD
+ */
+ if (cam_sim_bus(sim) == 1 &&
+ sc->pd_list[device_id].driveState != MR_PD_STATE_SYSTEM) {
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ xpt_done(ccb);
+ } else {
+ if (mrsas_startio(sc, sim, ccb)) {
+ ccb->ccb_h.status |= CAM_REQ_INVALID;
+ xpt_done(ccb);
+ }
+ }
+ break;
+ }
+ case XPT_ABORT:
+ {
+ ccb->ccb_h.status = CAM_UA_ABORT;
+ xpt_done(ccb);
+ break;
+ }
+ case XPT_RESET_BUS:
+ {
+ xpt_done(ccb);
+ break;
+ }
+ case XPT_GET_TRAN_SETTINGS:
+ {
+ ccb->cts.protocol = PROTO_SCSI;
+ ccb->cts.protocol_version = SCSI_REV_2;
+ ccb->cts.transport = XPORT_SPI;
+ ccb->cts.transport_version = 2;
+ ccb->cts.xport_specific.spi.valid = CTS_SPI_VALID_DISC;
+ ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB;
+ ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
+ ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ break;
+ }
+ case XPT_SET_TRAN_SETTINGS:
+ {
+ ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+ xpt_done(ccb);
+ break;
+ }
+ case XPT_CALC_GEOMETRY:
+ {
+ cam_calc_geometry(&ccb->ccg, 1);
+ xpt_done(ccb);
+ break;
+ }
+ case XPT_PATH_INQ:
+ {
+ ccb->cpi.version_num = 1;
+ ccb->cpi.hba_inquiry = 0;
+ ccb->cpi.target_sprt = 0;
+ ccb->cpi.hba_misc = 0;
+ ccb->cpi.hba_eng_cnt = 0;
+ ccb->cpi.max_lun = MRSAS_SCSI_MAX_LUNS;
+ ccb->cpi.unit_number = cam_sim_unit(sim);
+ ccb->cpi.bus_id = cam_sim_bus(sim);
+ ccb->cpi.initiator_id = MRSAS_SCSI_INITIATOR_ID;
+ ccb->cpi.base_transfer_speed = 150000;
+ strncpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN);
+ strncpy(ccb->cpi.hba_vid, "LSI", HBA_IDLEN);
+ strncpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN);
+ ccb->cpi.transport = XPORT_SPI;
+ ccb->cpi.transport_version = 2;
+ ccb->cpi.protocol = PROTO_SCSI;
+ ccb->cpi.protocol_version = SCSI_REV_2;
+ if (ccb->cpi.bus_id == 0)
+ ccb->cpi.max_target = MRSAS_MAX_PD - 1;
+ else
+ ccb->cpi.max_target = MRSAS_MAX_LD_IDS - 1;
#if (__FreeBSD_version > 704000)
- ccb->cpi.maxio = MRSAS_MAX_IO_SIZE;
+ ccb->cpi.maxio = MRSAS_MAX_IO_SIZE;
#endif
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- default:
- {
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- break;
- }
- }
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ break;
+ }
+ default:
+ {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ break;
+ }
+ }
}
-/**
- * mrsas_scsiio_timeout Callback function for IO timed out
- * input: mpt command context
+/*
+ * mrsas_scsiio_timeout: Callback function for IO timed out
+ * input: mpt command context
*
- * This function will execute after timeout value
- * provided by ccb header from CAM layer, if timer expires.
- * Driver will run timer for all DCDM and LDIO comming from CAM layer.
- * This function is callback function for IO timeout and it runs in
- * no-sleep context. Set do_timedout_reset in Adapter context so that
- * it will execute OCR/Kill adpter from ocr_thread context.
+ * This function will execute after timeout value provided by ccb header from
+ * CAM layer, if timer expires. Driver will run timer for all DCDM and LDIO
+ * comming from CAM layer. This function is callback function for IO timeout
+ * and it runs in no-sleep context. Set do_timedout_reset in Adapter context
+ * so that it will execute OCR/Kill adpter from ocr_thread context.
*/
static void
mrsas_scsiio_timeout(void *data)
{
- struct mrsas_mpt_cmd *cmd;
- struct mrsas_softc *sc;
-
- cmd = (struct mrsas_mpt_cmd *)data;
- sc = cmd->sc;
-
- if (cmd->ccb_ptr == NULL) {
- printf("command timeout with NULL ccb\n");
- return;
- }
-
- /* Below callout is dummy entry so that it will be
- * cancelled from mrsas_cmd_done(). Now Controller will
- * go to OCR/Kill Adapter based on OCR enable/disable
- * property of Controller from ocr_thread context.
- */
- callout_reset(&cmd->cm_callout, (600000 * hz) / 1000,
- mrsas_scsiio_timeout, cmd);
- sc->do_timedout_reset = 1;
- if(sc->ocr_thread_active)
- wakeup(&sc->ocr_chan);
+ struct mrsas_mpt_cmd *cmd;
+ struct mrsas_softc *sc;
+
+ cmd = (struct mrsas_mpt_cmd *)data;
+ sc = cmd->sc;
+
+ if (cmd->ccb_ptr == NULL) {
+ printf("command timeout with NULL ccb\n");
+ return;
+ }
+ /*
+ * Below callout is dummy entry so that it will be cancelled from
+ * mrsas_cmd_done(). Now Controller will go to OCR/Kill Adapter based
+ * on OCR enable/disable property of Controller from ocr_thread
+ * context.
+ */
+ callout_reset(&cmd->cm_callout, (600000 * hz) / 1000,
+ mrsas_scsiio_timeout, cmd);
+ sc->do_timedout_reset = 1;
+ if (sc->ocr_thread_active)
+ wakeup(&sc->ocr_chan);
}
-/**
- * mrsas_startio: SCSI IO entry point
- * input: Adapter instance soft state
- * pointer to CAM Control Block
+/*
+ * mrsas_startio: SCSI IO entry point
+ * input: Adapter instance soft state
+ * pointer to CAM Control Block
*
- * This function is the SCSI IO entry point and it initiates IO processing.
- * It copies the IO and depending if the IO is read/write or inquiry, it would
- * call mrsas_build_ldio() or mrsas_build_dcdb(), respectively. It returns
- * 0 if the command is sent to firmware successfully, otherwise it returns 1.
+ * This function is the SCSI IO entry point and it initiates IO processing. It
+ * copies the IO and depending if the IO is read/write or inquiry, it would
+ * call mrsas_build_ldio() or mrsas_build_dcdb(), respectively. It returns 0
+ * if the command is sent to firmware successfully, otherwise it returns 1.
*/
-static int32_t mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim,
- union ccb *ccb)
+static int32_t
+mrsas_startio(struct mrsas_softc *sc, struct cam_sim *sim,
+ union ccb *ccb)
{
- struct mrsas_mpt_cmd *cmd;
- struct ccb_hdr *ccb_h = &(ccb->ccb_h);
- struct ccb_scsiio *csio = &(ccb->csio);
- MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
-
- if ((csio->cdb_io.cdb_bytes[0]) == SYNCHRONIZE_CACHE){
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- return(0);
- }
-
- ccb_h->status |= CAM_SIM_QUEUED;
- cmd = mrsas_get_mpt_cmd(sc);
-
- if (!cmd) {
- ccb_h->status |= CAM_REQUEUE_REQ;
- xpt_done(ccb);
- return(0);
- }
-
- if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
- if(ccb_h->flags & CAM_DIR_IN)
- cmd->flags |= MRSAS_DIR_IN;
- if(ccb_h->flags & CAM_DIR_OUT)
- cmd->flags |= MRSAS_DIR_OUT;
- }
- else
- cmd->flags = MRSAS_DIR_NONE; /* no data */
-
-/* For FreeBSD 10.0 and higher */
+ struct mrsas_mpt_cmd *cmd;
+ struct ccb_hdr *ccb_h = &(ccb->ccb_h);
+ struct ccb_scsiio *csio = &(ccb->csio);
+ MRSAS_REQUEST_DESCRIPTOR_UNION *req_desc;
+
+ if ((csio->cdb_io.cdb_bytes[0]) == SYNCHRONIZE_CACHE) {
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ return (0);
+ }
+ ccb_h->status |= CAM_SIM_QUEUED;
+ cmd = mrsas_get_mpt_cmd(sc);
+
+ if (!cmd) {
+ ccb_h->status |= CAM_REQUEUE_REQ;
+ xpt_done(ccb);
+ return (0);
+ }
+ if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+ if (ccb_h->flags & CAM_DIR_IN)
+ cmd->flags |= MRSAS_DIR_IN;
+ if (ccb_h->flags & CAM_DIR_OUT)
+ cmd->flags |= MRSAS_DIR_OUT;
+ } else
+ cmd->flags = MRSAS_DIR_NONE; /* no data */
+
+ /* For FreeBSD 10.0 and higher */
#if (__FreeBSD_version >= 1000000)
-/*
- * * XXX We don't yet support physical addresses here.
- */
- switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) {
- case CAM_DATA_PADDR:
- case CAM_DATA_SG_PADDR:
- printf("%s: physical addresses not supported\n",
- __func__);
- mrsas_release_mpt_cmd(cmd);
- ccb_h->status = CAM_REQ_INVALID;
- ccb_h->status &= ~CAM_SIM_QUEUED;
- goto done;
- case CAM_DATA_SG:
- printf("%s: scatter gather is not supported\n",
- __func__);
- mrsas_release_mpt_cmd(cmd);
- ccb_h->status = CAM_REQ_INVALID;
- goto done;
+ /*
+ * XXX We don't yet support physical addresses here.
+ */
+ switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) {
+ case CAM_DATA_PADDR:
+ case CAM_DATA_SG_PADDR:
+ device_printf(sc->mrsas_dev, "%s: physical addresses not supported\n",
+ __func__);
+ mrsas_release_mpt_cmd(cmd);
+ ccb_h->status = CAM_REQ_INVALID;
+ ccb_h->status &= ~CAM_SIM_QUEUED;
+ goto done;
+ case CAM_DATA_SG:
+ device_printf(sc->mrsas_dev, "%s: scatter gather is not supported\n",
+ __func__);
+ mrsas_release_mpt_cmd(cmd);
+ ccb_h->status = CAM_REQ_INVALID;
+ goto done;
case CAM_DATA_VADDR:
- if (csio->dxfer_len > MRSAS_MAX_IO_SIZE) {
- mrsas_release_mpt_cmd(cmd);
- ccb_h->status = CAM_REQ_TOO_BIG;
- goto done;
- }
- cmd->length = csio->dxfer_len;
- if (cmd->length)
- cmd->data = csio->data_ptr;
- break;
- default:
- ccb->ccb_h.status = CAM_REQ_INVALID;
- goto done;
- }
+ if (csio->dxfer_len > MRSAS_MAX_IO_SIZE) {
+ mrsas_release_mpt_cmd(cmd);
+ ccb_h->status = CAM_REQ_TOO_BIG;
+ goto done;
+ }
+ cmd->length = csio->dxfer_len;
+ if (cmd->length)
+ cmd->data = csio->data_ptr;
+ break;
+ default:
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ goto done;
+ }
#else
- if (!(ccb_h->flags & CAM_DATA_PHYS)) { //Virtual data address
- if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
- if (csio->dxfer_len > MRSAS_MAX_IO_SIZE) {
- mrsas_release_mpt_cmd(cmd);
- ccb_h->status = CAM_REQ_TOO_BIG;
- goto done;
- }
- cmd->length = csio->dxfer_len;
- if (cmd->length)
- cmd->data = csio->data_ptr;
- }
- else {
- mrsas_release_mpt_cmd(cmd);
- ccb_h->status = CAM_REQ_INVALID;
- goto done;
- }
- }
- else { //Data addresses are physical.
- mrsas_release_mpt_cmd(cmd);
- ccb_h->status = CAM_REQ_INVALID;
- ccb_h->status &= ~CAM_SIM_QUEUED;
- goto done;
- }
+ if (!(ccb_h->flags & CAM_DATA_PHYS)) { /* Virtual data address */
+ if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
+ if (csio->dxfer_len > MRSAS_MAX_IO_SIZE) {
+ mrsas_release_mpt_cmd(cmd);
+ ccb_h->status = CAM_REQ_TOO_BIG;
+ goto done;
+ }
+ cmd->length = csio->dxfer_len;
+ if (cmd->length)
+ cmd->data = csio->data_ptr;
+ } else {
+ mrsas_release_mpt_cmd(cmd);
+ ccb_h->status = CAM_REQ_INVALID;
+ goto done;
+ }
+ } else { /* Data addresses are physical. */
+ mrsas_release_mpt_cmd(cmd);
+ ccb_h->status = CAM_REQ_INVALID;
+ ccb_h->status &= ~CAM_SIM_QUEUED;
+ goto done;
+ }
#endif
- /* save ccb ptr */
- cmd->ccb_ptr = ccb;
-
- req_desc = mrsas_get_request_desc(sc, (cmd->index)-1);
- if (!req_desc) {
- device_printf(sc->mrsas_dev, "Cannot get request_descriptor.\n");
- return (FAIL);
- }
- memset(req_desc, 0, sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION));
- cmd->request_desc = req_desc;
-
- if (ccb_h->flags & CAM_CDB_POINTER)
- bcopy(csio->cdb_io.cdb_ptr, cmd->io_request->CDB.CDB32, csio->cdb_len);
- else
- bcopy(csio->cdb_io.cdb_bytes, cmd->io_request->CDB.CDB32, csio->cdb_len);
- mtx_lock(&sc->raidmap_lock);
-
- if (mrsas_ldio_inq(sim, ccb)) {
- if (mrsas_build_ldio(sc, cmd, ccb)){
- device_printf(sc->mrsas_dev, "Build LDIO failed.\n");
- mtx_unlock(&sc->raidmap_lock);
- return(1);
- }
- }
- else {
- if (mrsas_build_dcdb(sc, cmd, ccb, sim)) {
- device_printf(sc->mrsas_dev, "Build DCDB failed.\n");
- mtx_unlock(&sc->raidmap_lock);
- return(1);
- }
- }
- mtx_unlock(&sc->raidmap_lock);
-
- if (cmd->flags == MRSAS_DIR_IN) //from device
- cmd->io_request->Control |= MPI2_SCSIIO_CONTROL_READ;
- else if (cmd->flags == MRSAS_DIR_OUT) //to device
- cmd->io_request->Control |= MPI2_SCSIIO_CONTROL_WRITE;
-
- cmd->io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
- cmd->io_request->SGLOffset0 = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL)/4;
- cmd->io_request->SenseBufferLowAddress = cmd->sense_phys_addr;
- cmd->io_request->SenseBufferLength = MRSAS_SCSI_SENSE_BUFFERSIZE;
-
- req_desc = cmd->request_desc;
- req_desc->SCSIIO.SMID = cmd->index;
-
- /*
- * Start timer for IO timeout. Default timeout value is 90 second.
- */
- callout_reset(&cmd->cm_callout, (sc->mrsas_io_timeout * hz) / 1000,
- mrsas_scsiio_timeout, cmd);
- atomic_inc(&sc->fw_outstanding);
-
- if(atomic_read(&sc->fw_outstanding) > sc->io_cmds_highwater)
- sc->io_cmds_highwater++;
-
- mrsas_fire_cmd(sc, req_desc->addr.u.low, req_desc->addr.u.high);
- return(0);
+ /* save ccb ptr */
+ cmd->ccb_ptr = ccb;
+
+ req_desc = mrsas_get_request_desc(sc, (cmd->index) - 1);
+ if (!req_desc) {
+ device_printf(sc->mrsas_dev, "Cannot get request_descriptor.\n");
+ return (FAIL);
+ }
+ memset(req_desc, 0, sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION));
+ cmd->request_desc = req_desc;
+
+ if (ccb_h->flags & CAM_CDB_POINTER)
+ bcopy(csio->cdb_io.cdb_ptr, cmd->io_request->CDB.CDB32, csio->cdb_len);
+ else
+ bcopy(csio->cdb_io.cdb_bytes, cmd->io_request->CDB.CDB32, csio->cdb_len);
+ mtx_lock(&sc->raidmap_lock);
+
+ if (mrsas_ldio_inq(sim, ccb)) {
+ if (mrsas_build_ldio(sc, cmd, ccb)) {
+ device_printf(sc->mrsas_dev, "Build LDIO failed.\n");
+ mtx_unlock(&sc->raidmap_lock);
+ return (1);
+ }
+ } else {
+ if (mrsas_build_dcdb(sc, cmd, ccb, sim)) {
+ device_printf(sc->mrsas_dev, "Build DCDB failed.\n");
+ mtx_unlock(&sc->raidmap_lock);
+ return (1);
+ }
+ }
+ mtx_unlock(&sc->raidmap_lock);
+
+ if (cmd->flags == MRSAS_DIR_IN) /* from device */
+ cmd->io_request->Control |= MPI2_SCSIIO_CONTROL_READ;
+ else if (cmd->flags == MRSAS_DIR_OUT) /* to device */
+ cmd->io_request->Control |= MPI2_SCSIIO_CONTROL_WRITE;
+
+ cmd->io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
+ cmd->io_request->SGLOffset0 = offsetof(MRSAS_RAID_SCSI_IO_REQUEST, SGL) / 4;
+ cmd->io_request->SenseBufferLowAddress = cmd->sense_phys_addr;
+ cmd->io_request->SenseBufferLength = MRSAS_SCSI_SENSE_BUFFERSIZE;
+
+ req_desc = cmd->request_desc;
+ req_desc->SCSIIO.SMID = cmd->index;
+
+ /*
+ * Start timer for IO timeout. Default timeout value is 90 second.
+ */
+ callout_reset(&cmd->cm_callout, (sc->mrsas_io_timeout * hz) / 1000,
+ mrsas_scsiio_timeout, cmd);
+ atomic_inc(&sc->fw_outstanding);
+
+ if (atomic_read(&sc->fw_outstanding) > sc->io_cmds_highwater)
+ sc->io_cmds_highwater++;
+
+ mrsas_fire_cmd(sc, req_desc->addr.u.low, req_desc->addr.u.high);
+ return (0);
done:
- xpt_done(ccb);
- return(0);
+ xpt_done(ccb);
+ return (0);
}
-/**
- * mrsas_ldio_inq: Determines if IO is read/write or inquiry
- * input: pointer to CAM Control Block
+/*
+ * mrsas_ldio_inq: Determines if IO is read/write or inquiry
+ * input: pointer to CAM Control Block
*
- * This function determines if the IO is read/write or inquiry. It returns a
- * 1 if the IO is read/write and 0 if it is inquiry.
+ * This function determines if the IO is read/write or inquiry. It returns a 1
+ * if the IO is read/write and 0 if it is inquiry.
*/
-int mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb)
+int
+mrsas_ldio_inq(struct cam_sim *sim, union ccb *ccb)
{
- struct ccb_scsiio *csio = &(ccb->csio);
-
- if (cam_sim_bus(sim) == 1)
- return(0);
-
- switch (csio->cdb_io.cdb_bytes[0]) {
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- case READ_6:
- case WRITE_6:
- case READ_16:
- case WRITE_16:
- return 1;
- default:
- return 0;
- }
+ struct ccb_scsiio *csio = &(ccb->csio);
+
+ if (cam_sim_bus(sim) == 1)
+ return (0);
+
+ switch (csio->cdb_io.cdb_bytes[0]) {
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ case READ_6:
+ case WRITE_6:
+ case READ_16:
+ case WRITE_16:
+ return 1;
+ default:
+ return 0;
+ }
}
-/**
- * mrsas_get_mpt_cmd: Get a cmd from free command pool
- * input: Adapter instance soft state
+/*
+ * mrsas_get_mpt_cmd: Get a cmd from free command pool
+ * input: Adapter instance soft state
*
- * This function removes an MPT command from the command free list and
+ * This function removes an MPT command from the command free list and
* initializes it.
*/
-struct mrsas_mpt_cmd* mrsas_get_mpt_cmd(struct mrsas_softc *sc)
+struct mrsas_mpt_cmd *
+mrsas_get_mpt_cmd(struct mrsas_softc *sc)
{
- struct mrsas_mpt_cmd *cmd = NULL;
-
- mtx_lock(&sc->mpt_cmd_pool_lock);
- if (!TAILQ_EMPTY(&sc->mrsas_mpt_cmd_list_head)){
- cmd = TAILQ_FIRST(&sc->mrsas_mpt_cmd_list_head);
- TAILQ_REMOVE(&sc->mrsas_mpt_cmd_list_head, cmd, next);
- }
- memset((uint8_t *)cmd->io_request, 0, MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE);
- cmd->data = NULL;
- cmd->length = 0;
- cmd->flags = 0;
- cmd->error_code = 0;
- cmd->load_balance = 0;
- cmd->ccb_ptr = NULL;
- mtx_unlock(&sc->mpt_cmd_pool_lock);
-
- return cmd;
+ struct mrsas_mpt_cmd *cmd = NULL;
+
+ mtx_lock(&sc->mpt_cmd_pool_lock);
+ if (!TAILQ_EMPTY(&sc->mrsas_mpt_cmd_list_head)) {
+ cmd = TAILQ_FIRST(&sc->mrsas_mpt_cmd_list_head);
+ TAILQ_REMOVE(&sc->mrsas_mpt_cmd_list_head, cmd, next);
+ }
+ memset((uint8_t *)cmd->io_request, 0, MRSAS_MPI2_RAID_DEFAULT_IO_FRAME_SIZE);
+ cmd->data = NULL;
+ cmd->length = 0;
+ cmd->flags = 0;
+ cmd->error_code = 0;
+ cmd->load_balance = 0;
+ cmd->ccb_ptr = NULL;
+ mtx_unlock(&sc->mpt_cmd_pool_lock);
+
+ return cmd;
}
-/**
- * mrsas_release_mpt_cmd: Return a cmd to free command pool
- * input: Command packet for return to free command pool
+/*
+ * mrsas_release_mpt_cmd: Return a cmd to free command pool
+ * input: Command packet for return to free command pool
*
* This function returns an MPT command to the free command list.
*/
-void mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd)
+void
+mrsas_release_mpt_cmd(struct mrsas_mpt_cmd *cmd)
{
- struct mrsas_softc *sc = cmd->sc;
+ struct mrsas_softc *sc = cmd->sc;
- mtx_lock(&sc->mpt_cmd_pool_lock);
- cmd->sync_cmd_idx = (u_int32_t)MRSAS_ULONG_MAX;
- TAILQ_INSERT_TAIL(&(sc->mrsas_mpt_cmd_list_head), cmd, next);
- mtx_unlock(&sc->mpt_cmd_pool_lock);
+ mtx_lock(&sc->mpt_cmd_pool_lock);
+ cmd->sync_cmd_idx = (u_int32_t)MRSAS_ULONG_MAX;
+ TAILQ_INSERT_TAIL(&(sc->mrsas_mpt_cmd_list_head), cmd, next);
+ mtx_unlock(&sc->mpt_cmd_pool_lock);
- return;
+ return;
}
-/**
- * mrsas_get_request_desc: Get request descriptor from array
- * input: Adapter instance soft state
- * SMID index
+/*
+ * mrsas_get_request_desc: Get request descriptor from array
+ * input: Adapter instance soft state
+ * SMID index
*
* This function returns a pointer to the request descriptor.
*/
MRSAS_REQUEST_DESCRIPTOR_UNION *
mrsas_get_request_desc(struct mrsas_softc *sc, u_int16_t index)
{
- u_int8_t *p;
+ u_int8_t *p;
- if (index >= sc->max_fw_cmds) {
- device_printf(sc->mrsas_dev, "Invalid SMID (0x%x)request for desc\n", index);
- return NULL;
- }
- p = sc->req_desc + sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * index;
+ if (index >= sc->max_fw_cmds) {
+ device_printf(sc->mrsas_dev, "Invalid SMID (0x%x)request for desc\n", index);
+ return NULL;
+ }
+ p = sc->req_desc + sizeof(MRSAS_REQUEST_DESCRIPTOR_UNION) * index;
- return (MRSAS_REQUEST_DESCRIPTOR_UNION *)p;
+ return (MRSAS_REQUEST_DESCRIPTOR_UNION *) p;
}
-/**
- * mrsas_build_ldio: Builds an LDIO command
- * input: Adapter instance soft state
- * Pointer to command packet
- * Pointer to CCB
+/*
+ * mrsas_build_ldio: Builds an LDIO command
+ * input: Adapter instance soft state
+ * Pointer to command packet
+ * Pointer to CCB
*
- * This function builds the LDIO command packet. It returns 0 if the
- * command is built successfully, otherwise it returns a 1.
+ * This function builds the LDIO command packet. It returns 0 if the command is
+ * built successfully, otherwise it returns a 1.
*/
-int mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
- union ccb *ccb)
+int
+mrsas_build_ldio(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
+ union ccb *ccb)
{
- struct ccb_hdr *ccb_h = &(ccb->ccb_h);
- struct ccb_scsiio *csio = &(ccb->csio);
- u_int32_t device_id;
- MRSAS_RAID_SCSI_IO_REQUEST *io_request;
-
- device_id = ccb_h->target_id;
-
- io_request = cmd->io_request;
- io_request->RaidContext.VirtualDiskTgtId = device_id;
- io_request->RaidContext.status = 0;
- io_request->RaidContext.exStatus = 0;
-
- /* just the cdb len, other flags zero, and ORed-in later for FP */
- io_request->IoFlags = csio->cdb_len;
-
- if (mrsas_setup_io(sc, cmd, ccb, device_id, io_request) != SUCCESS)
- device_printf(sc->mrsas_dev, "Build ldio or fpio error\n");
-
- io_request->DataLength = cmd->length;
-
- if (mrsas_map_request(sc, cmd) == SUCCESS) {
- if (cmd->sge_count > MRSAS_MAX_SGL) {
- device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds"
- "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge);
- return (FAIL);
- }
- io_request->RaidContext.numSGE = cmd->sge_count;
- }
- else {
- device_printf(sc->mrsas_dev, "Data map/load failed.\n");
- return(FAIL);
- }
- return(0);
+ struct ccb_hdr *ccb_h = &(ccb->ccb_h);
+ struct ccb_scsiio *csio = &(ccb->csio);
+ u_int32_t device_id;
+ MRSAS_RAID_SCSI_IO_REQUEST *io_request;
+
+ device_id = ccb_h->target_id;
+
+ io_request = cmd->io_request;
+ io_request->RaidContext.VirtualDiskTgtId = device_id;
+ io_request->RaidContext.status = 0;
+ io_request->RaidContext.exStatus = 0;
+
+ /* just the cdb len, other flags zero, and ORed-in later for FP */
+ io_request->IoFlags = csio->cdb_len;
+
+ if (mrsas_setup_io(sc, cmd, ccb, device_id, io_request) != SUCCESS)
+ device_printf(sc->mrsas_dev, "Build ldio or fpio error\n");
+
+ io_request->DataLength = cmd->length;
+
+ if (mrsas_map_request(sc, cmd) == SUCCESS) {
+ if (cmd->sge_count > MRSAS_MAX_SGL) {
+ device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds"
+ "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge);
+ return (FAIL);
+ }
+ io_request->RaidContext.numSGE = cmd->sge_count;
+ } else {
+ device_printf(sc->mrsas_dev, "Data map/load failed.\n");
+ return (FAIL);
+ }
+ return (0);
}
-/**
- * mrsas_setup_io: Set up data including Fast Path I/O
- * input: Adapter instance soft state
- * Pointer to command packet
- * Pointer to CCB
+/*
+ * mrsas_setup_io: Set up data including Fast Path I/O
+ * input: Adapter instance soft state
+ * Pointer to command packet
+ * Pointer to CCB
*
- * This function builds the DCDB inquiry command. It returns 0 if the
- * command is built successfully, otherwise it returns a 1.
+ * This function builds the DCDB inquiry command. It returns 0 if the command
+ * is built successfully, otherwise it returns a 1.
*/
-int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
- union ccb *ccb, u_int32_t device_id,
- MRSAS_RAID_SCSI_IO_REQUEST *io_request)
+int
+mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
+ union ccb *ccb, u_int32_t device_id,
+ MRSAS_RAID_SCSI_IO_REQUEST * io_request)
{
- struct ccb_hdr *ccb_h = &(ccb->ccb_h);
- struct ccb_scsiio *csio = &(ccb->csio);
- struct IO_REQUEST_INFO io_info;
- MR_FW_RAID_MAP_ALL *map_ptr;
- u_int8_t fp_possible;
- u_int32_t start_lba_hi, start_lba_lo, ld_block_size;
- u_int32_t datalength = 0;
-
- start_lba_lo = 0;
- start_lba_hi = 0;
- fp_possible = 0;
-
- /*
- * READ_6 (0x08) or WRITE_6 (0x0A) cdb
- */
- if (csio->cdb_len == 6) {
- datalength = (u_int32_t)csio->cdb_io.cdb_bytes[4];
- start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[1] << 16) |
- ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 8) |
- (u_int32_t) csio->cdb_io.cdb_bytes[3];
- start_lba_lo &= 0x1FFFFF;
- }
- /*
- * READ_10 (0x28) or WRITE_6 (0x2A) cdb
- */
- else if (csio->cdb_len == 10) {
- datalength = (u_int32_t)csio->cdb_io.cdb_bytes[8] |
- ((u_int32_t)csio->cdb_io.cdb_bytes[7] << 8);
- start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 24) |
- ((u_int32_t) csio->cdb_io.cdb_bytes[3] << 16) |
- (u_int32_t) csio->cdb_io.cdb_bytes[4] << 8 |
- ((u_int32_t) csio->cdb_io.cdb_bytes[5]);
- }
- /*
- * READ_12 (0xA8) or WRITE_12 (0xAA) cdb
- */
- else if (csio->cdb_len == 12) {
- datalength = (u_int32_t)csio->cdb_io.cdb_bytes[6] << 24 |
- ((u_int32_t)csio->cdb_io.cdb_bytes[7] << 16) |
- ((u_int32_t)csio->cdb_io.cdb_bytes[8] << 8) |
- ((u_int32_t)csio->cdb_io.cdb_bytes[9]);
- start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 24) |
- ((u_int32_t) csio->cdb_io.cdb_bytes[3] << 16) |
- (u_int32_t) csio->cdb_io.cdb_bytes[4] << 8 |
- ((u_int32_t) csio->cdb_io.cdb_bytes[5]);
- }
- /*
- * READ_16 (0x88) or WRITE_16 (0xx8A) cdb
- */
- else if (csio->cdb_len == 16) {
- datalength = (u_int32_t)csio->cdb_io.cdb_bytes[10] << 24 |
- ((u_int32_t)csio->cdb_io.cdb_bytes[11] << 16) |
- ((u_int32_t)csio->cdb_io.cdb_bytes[12] << 8) |
- ((u_int32_t)csio->cdb_io.cdb_bytes[13]);
- start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[6] << 24) |
- ((u_int32_t) csio->cdb_io.cdb_bytes[7] << 16) |
- (u_int32_t) csio->cdb_io.cdb_bytes[8] << 8 |
- ((u_int32_t) csio->cdb_io.cdb_bytes[9]);
- start_lba_hi = ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 24) |
- ((u_int32_t) csio->cdb_io.cdb_bytes[3] << 16) |
- (u_int32_t) csio->cdb_io.cdb_bytes[4] << 8 |
- ((u_int32_t) csio->cdb_io.cdb_bytes[5]);
- }
-
- memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
- io_info.ldStartBlock = ((u_int64_t)start_lba_hi << 32) | start_lba_lo;
- io_info.numBlocks = datalength;
- io_info.ldTgtId = device_id;
-
- switch (ccb_h->flags & CAM_DIR_MASK) {
+ struct ccb_hdr *ccb_h = &(ccb->ccb_h);
+ struct ccb_scsiio *csio = &(ccb->csio);
+ struct IO_REQUEST_INFO io_info;
+ MR_DRV_RAID_MAP_ALL *map_ptr;
+ u_int8_t fp_possible;
+ u_int32_t start_lba_hi, start_lba_lo, ld_block_size;
+ u_int32_t datalength = 0;
+
+ start_lba_lo = 0;
+ start_lba_hi = 0;
+ fp_possible = 0;
+
+ /*
+ * READ_6 (0x08) or WRITE_6 (0x0A) cdb
+ */
+ if (csio->cdb_len == 6) {
+ datalength = (u_int32_t)csio->cdb_io.cdb_bytes[4];
+ start_lba_lo = ((u_int32_t)csio->cdb_io.cdb_bytes[1] << 16) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[2] << 8) |
+ (u_int32_t)csio->cdb_io.cdb_bytes[3];
+ start_lba_lo &= 0x1FFFFF;
+ }
+ /*
+ * READ_10 (0x28) or WRITE_6 (0x2A) cdb
+ */
+ else if (csio->cdb_len == 10) {
+ datalength = (u_int32_t)csio->cdb_io.cdb_bytes[8] |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[7] << 8);
+ start_lba_lo = ((u_int32_t)csio->cdb_io.cdb_bytes[2] << 24) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[3] << 16) |
+ (u_int32_t)csio->cdb_io.cdb_bytes[4] << 8 |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[5]);
+ }
+ /*
+ * READ_12 (0xA8) or WRITE_12 (0xAA) cdb
+ */
+ else if (csio->cdb_len == 12) {
+ datalength = (u_int32_t)csio->cdb_io.cdb_bytes[6] << 24 |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[7] << 16) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[8] << 8) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[9]);
+ start_lba_lo = ((u_int32_t)csio->cdb_io.cdb_bytes[2] << 24) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[3] << 16) |
+ (u_int32_t)csio->cdb_io.cdb_bytes[4] << 8 |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[5]);
+ }
+ /*
+ * READ_16 (0x88) or WRITE_16 (0xx8A) cdb
+ */
+ else if (csio->cdb_len == 16) {
+ datalength = (u_int32_t)csio->cdb_io.cdb_bytes[10] << 24 |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[11] << 16) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[12] << 8) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[13]);
+ start_lba_lo = ((u_int32_t)csio->cdb_io.cdb_bytes[6] << 24) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[7] << 16) |
+ (u_int32_t)csio->cdb_io.cdb_bytes[8] << 8 |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[9]);
+ start_lba_hi = ((u_int32_t)csio->cdb_io.cdb_bytes[2] << 24) |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[3] << 16) |
+ (u_int32_t)csio->cdb_io.cdb_bytes[4] << 8 |
+ ((u_int32_t)csio->cdb_io.cdb_bytes[5]);
+ }
+ memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
+ io_info.ldStartBlock = ((u_int64_t)start_lba_hi << 32) | start_lba_lo;
+ io_info.numBlocks = datalength;
+ io_info.ldTgtId = device_id;
+
+ switch (ccb_h->flags & CAM_DIR_MASK) {
case CAM_DIR_IN:
io_info.isRead = 1;
break;
@@ -776,401 +782,418 @@ int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
break;
case CAM_DIR_NONE:
default:
- mrsas_dprint(sc, MRSAS_TRACE, "From %s : DMA Flag is %d \n", __func__, ccb_h->flags & CAM_DIR_MASK);
+ mrsas_dprint(sc, MRSAS_TRACE, "From %s : DMA Flag is %d \n", __func__, ccb_h->flags & CAM_DIR_MASK);
break;
- }
-
- map_ptr = sc->raidmap_mem[(sc->map_id & 1)];
- ld_block_size = MR_LdBlockSizeGet(device_id, map_ptr, sc);
-
- if ((MR_TargetIdToLdGet(device_id, map_ptr) >= MAX_LOGICAL_DRIVES) ||
- (!sc->fast_path_io)) {
- io_request->RaidContext.regLockFlags = 0;
- fp_possible = 0;
- }
- else
- {
- if (MR_BuildRaidContext(sc, &io_info, &io_request->RaidContext, map_ptr))
- fp_possible = io_info.fpOkForIo;
- }
-
- if (fp_possible) {
- mrsas_set_pd_lba(io_request, csio->cdb_len, &io_info, ccb, map_ptr,
- start_lba_lo, ld_block_size);
- io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
- cmd->request_desc->SCSIIO.RequestFlags =
- (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
- << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
- if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
- cmd->request_desc->SCSIIO.RequestFlags = (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- io_request->RaidContext.Type = MPI2_TYPE_CUDA;
- io_request->RaidContext.nseg = 0x1;
- io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
- io_request->RaidContext.regLockFlags |= (MR_RL_FLAGS_GRANT_DESTINATION_CUDA | MR_RL_FLAGS_SEQ_NUM_ENABLE);
- }
- if ((sc->load_balance_info[device_id].loadBalanceFlag) && (io_info.isRead)) {
- io_info.devHandle = mrsas_get_updated_dev_handle(&sc->load_balance_info[device_id],
- &io_info);
- cmd->load_balance = MRSAS_LOAD_BALANCE_FLAG;
- }
- else
- cmd->load_balance = 0;
- cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
- io_request->DevHandle = io_info.devHandle;
- }
- else {
- /* Not FP IO */
- io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec;
- cmd->request_desc->SCSIIO.RequestFlags =
- (MRSAS_REQ_DESCRIPT_FLAGS_LD_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
- if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
- cmd->request_desc->SCSIIO.RequestFlags = (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- io_request->RaidContext.Type = MPI2_TYPE_CUDA;
- io_request->RaidContext.regLockFlags |= (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 | MR_RL_FLAGS_SEQ_NUM_ENABLE);
- io_request->RaidContext.nseg = 0x1;
- }
- io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST;
- io_request->DevHandle = device_id;
- }
- return(0);
+ }
+
+ map_ptr = sc->ld_drv_map[(sc->map_id & 1)];
+ ld_block_size = MR_LdBlockSizeGet(device_id, map_ptr, sc);
+
+ if ((MR_TargetIdToLdGet(device_id, map_ptr) >= MAX_LOGICAL_DRIVES_EXT) ||
+ (!sc->fast_path_io)) {
+ io_request->RaidContext.regLockFlags = 0;
+ fp_possible = 0;
+ } else {
+ if (MR_BuildRaidContext(sc, &io_info, &io_request->RaidContext, map_ptr))
+ fp_possible = io_info.fpOkForIo;
+ }
+
+ cmd->request_desc->SCSIIO.MSIxIndex =
+ sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0;
+
+
+ if (fp_possible) {
+ mrsas_set_pd_lba(io_request, csio->cdb_len, &io_info, ccb, map_ptr,
+ start_lba_lo, ld_block_size);
+ io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
+ MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
+ if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
+ MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ io_request->RaidContext.Type = MPI2_TYPE_CUDA;
+ io_request->RaidContext.nseg = 0x1;
+ io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
+ io_request->RaidContext.regLockFlags |=
+ (MR_RL_FLAGS_GRANT_DESTINATION_CUDA |
+ MR_RL_FLAGS_SEQ_NUM_ENABLE);
+ }
+ if ((sc->load_balance_info[device_id].loadBalanceFlag) &&
+ (io_info.isRead)) {
+ io_info.devHandle =
+ mrsas_get_updated_dev_handle(&sc->load_balance_info[device_id],
+ &io_info);
+ cmd->load_balance = MRSAS_LOAD_BALANCE_FLAG;
+ } else
+ cmd->load_balance = 0;
+ cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
+ io_request->DevHandle = io_info.devHandle;
+ } else {
+ /* Not FP IO */
+ io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MRSAS_REQ_DESCRIPT_FLAGS_LD_IO <<
+ MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
+ if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
+ MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ io_request->RaidContext.Type = MPI2_TYPE_CUDA;
+ io_request->RaidContext.regLockFlags |=
+ (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 |
+ MR_RL_FLAGS_SEQ_NUM_ENABLE);
+ io_request->RaidContext.nseg = 0x1;
+ }
+ io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST;
+ io_request->DevHandle = device_id;
+ }
+ return (0);
}
-/**
- * mrsas_build_dcdb: Builds an DCDB command
- * input: Adapter instance soft state
- * Pointer to command packet
- * Pointer to CCB
+/*
+ * mrsas_build_dcdb: Builds an DCDB command
+ * input: Adapter instance soft state
+ * Pointer to command packet
+ * Pointer to CCB
*
- * This function builds the DCDB inquiry command. It returns 0 if the
- * command is built successfully, otherwise it returns a 1.
+ * This function builds the DCDB inquiry command. It returns 0 if the command
+ * is built successfully, otherwise it returns a 1.
*/
-int mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
- union ccb *ccb, struct cam_sim *sim)
+int
+mrsas_build_dcdb(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
+ union ccb *ccb, struct cam_sim *sim)
{
- struct ccb_hdr *ccb_h = &(ccb->ccb_h);
- u_int32_t device_id;
- MR_FW_RAID_MAP_ALL *map_ptr;
- MRSAS_RAID_SCSI_IO_REQUEST *io_request;
-
- io_request = cmd->io_request;
- device_id = ccb_h->target_id;
- map_ptr = sc->raidmap_mem[(sc->map_id & 1)];
-
- /* Check if this is for system PD */
- if (cam_sim_bus(sim) == 1 &&
- sc->pd_list[device_id].driveState == MR_PD_STATE_SYSTEM) {
- io_request->Function = 0;
- io_request->DevHandle = map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
- io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec;
- io_request->RaidContext.regLockFlags = 0;
- io_request->RaidContext.regLockRowLBA = 0;
- io_request->RaidContext.regLockLength = 0;
- io_request->RaidContext.RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD <<
- MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
- io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
- cmd->request_desc->SCSIIO.RequestFlags =
- (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
- MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- cmd->request_desc->SCSIIO.DevHandle =
- map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
- }
- else {
- io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST;
- io_request->DevHandle = device_id;
- cmd->request_desc->SCSIIO.RequestFlags =
- (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
- }
-
- io_request->RaidContext.VirtualDiskTgtId = device_id;
- io_request->LUN[1] = ccb_h->target_lun & 0xF;
- io_request->DataLength = cmd->length;
-
- if (mrsas_map_request(sc, cmd) == SUCCESS) {
- if (cmd->sge_count > sc->max_num_sge) {
- device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds"
- "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge);
- return (1);
- }
- io_request->RaidContext.numSGE = cmd->sge_count;
- }
- else {
- device_printf(sc->mrsas_dev, "Data map/load failed.\n");
- return(1);
- }
- return(0);
+ struct ccb_hdr *ccb_h = &(ccb->ccb_h);
+ u_int32_t device_id;
+ MR_DRV_RAID_MAP_ALL *map_ptr;
+ MRSAS_RAID_SCSI_IO_REQUEST *io_request;
+
+ io_request = cmd->io_request;
+ device_id = ccb_h->target_id;
+ map_ptr = sc->ld_drv_map[(sc->map_id & 1)];
+
+ /* Check if this is for system PD */
+ if (cam_sim_bus(sim) == 1 &&
+ sc->pd_list[device_id].driveState == MR_PD_STATE_SYSTEM) {
+ io_request->Function = 0;
+ io_request->DevHandle = map_ptr->raidMap.devHndlInfo[device_id].
+ curDevHdl;
+ io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec;
+ io_request->RaidContext.regLockFlags = 0;
+ io_request->RaidContext.regLockRowLBA = 0;
+ io_request->RaidContext.regLockLength = 0;
+
+ io_request->RaidContext.RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD
+ << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
+ io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
+ MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ cmd->request_desc->SCSIIO.DevHandle =
+ map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+ cmd->request_desc->SCSIIO.MSIxIndex =
+ sc->msix_vectors ? smp_processor_id() % sc->msix_vectors : 0;
+
+ } else {
+ io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST;
+ io_request->DevHandle = device_id;
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
+ MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ }
+
+ io_request->RaidContext.VirtualDiskTgtId = device_id;
+ io_request->LUN[1] = ccb_h->target_lun & 0xF;
+ io_request->DataLength = cmd->length;
+
+ if (mrsas_map_request(sc, cmd) == SUCCESS) {
+ if (cmd->sge_count > sc->max_num_sge) {
+ device_printf(sc->mrsas_dev, "Error: sge_count (0x%x) exceeds"
+ "max (0x%x) allowed\n", cmd->sge_count, sc->max_num_sge);
+ return (1);
+ }
+ io_request->RaidContext.numSGE = cmd->sge_count;
+ } else {
+ device_printf(sc->mrsas_dev, "Data map/load failed.\n");
+ return (1);
+ }
+ return (0);
}
-/**
- * mrsas_map_request: Map and load data
- * input: Adapter instance soft state
- * Pointer to command packet
+/*
+ * mrsas_map_request: Map and load data
+ * input: Adapter instance soft state
+ * Pointer to command packet
*
- * For data from OS, map and load the data buffer into bus space. The
- * SG list is built in the callback. If the bus dmamap load is not
- * successful, cmd->error_code will contain the error code and a 1 is
- * returned.
+ * For data from OS, map and load the data buffer into bus space. The SG list
+ * is built in the callback. If the bus dmamap load is not successful,
+ * cmd->error_code will contain the error code and a 1 is returned.
*/
-int mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd)
+int
+mrsas_map_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd)
{
- u_int32_t retcode = 0;
- struct cam_sim *sim;
- int flag = BUS_DMA_NOWAIT;
-
- sim = xpt_path_sim(cmd->ccb_ptr->ccb_h.path);
-
- if (cmd->data != NULL) {
- mtx_lock(&sc->io_lock);
- /* Map data buffer into bus space */
- retcode = bus_dmamap_load(sc->data_tag, cmd->data_dmamap, cmd->data,
- cmd->length, mrsas_data_load_cb, cmd, flag);
- mtx_unlock(&sc->io_lock);
- if (retcode)
- device_printf(sc->mrsas_dev, "bus_dmamap_load(): retcode = %d\n", retcode);
- if (retcode == EINPROGRESS) {
- device_printf(sc->mrsas_dev, "request load in progress\n");
- mrsas_freeze_simq(cmd, sim);
- }
- }
- if (cmd->error_code)
- return(1);
- return(retcode);
+ u_int32_t retcode = 0;
+ struct cam_sim *sim;
+ int flag = BUS_DMA_NOWAIT;
+
+ sim = xpt_path_sim(cmd->ccb_ptr->ccb_h.path);
+
+ if (cmd->data != NULL) {
+ mtx_lock(&sc->io_lock);
+ /* Map data buffer into bus space */
+ retcode = bus_dmamap_load(sc->data_tag, cmd->data_dmamap, cmd->data,
+ cmd->length, mrsas_data_load_cb, cmd, flag);
+ mtx_unlock(&sc->io_lock);
+ if (retcode)
+ device_printf(sc->mrsas_dev, "bus_dmamap_load(): retcode = %d\n", retcode);
+ if (retcode == EINPROGRESS) {
+ device_printf(sc->mrsas_dev, "request load in progress\n");
+ mrsas_freeze_simq(cmd, sim);
+ }
+ }
+ if (cmd->error_code)
+ return (1);
+ return (retcode);
}
-/**
- * mrsas_unmap_request: Unmap and unload data
- * input: Adapter instance soft state
- * Pointer to command packet
+/*
+ * mrsas_unmap_request: Unmap and unload data
+ * input: Adapter instance soft state
+ * Pointer to command packet
*
* This function unmaps and unloads data from OS.
*/
-void mrsas_unmap_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd)
+void
+mrsas_unmap_request(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd)
{
- if (cmd->data != NULL) {
- if (cmd->flags & MRSAS_DIR_IN)
- bus_dmamap_sync(sc->data_tag, cmd->data_dmamap, BUS_DMASYNC_POSTREAD);
- if (cmd->flags & MRSAS_DIR_OUT)
- bus_dmamap_sync(sc->data_tag, cmd->data_dmamap, BUS_DMASYNC_POSTWRITE);
- mtx_lock(&sc->io_lock);
- bus_dmamap_unload(sc->data_tag, cmd->data_dmamap);
- mtx_unlock(&sc->io_lock);
- }
+ if (cmd->data != NULL) {
+ if (cmd->flags & MRSAS_DIR_IN)
+ bus_dmamap_sync(sc->data_tag, cmd->data_dmamap, BUS_DMASYNC_POSTREAD);
+ if (cmd->flags & MRSAS_DIR_OUT)
+ bus_dmamap_sync(sc->data_tag, cmd->data_dmamap, BUS_DMASYNC_POSTWRITE);
+ mtx_lock(&sc->io_lock);
+ bus_dmamap_unload(sc->data_tag, cmd->data_dmamap);
+ mtx_unlock(&sc->io_lock);
+ }
}
-/**
- * mrsas_data_load_cb: Callback entry point
- * input: Pointer to command packet as argument
- * Pointer to segment
- * Number of segments
- * Error
+/*
+ * mrsas_data_load_cb: Callback entry point
+ * input: Pointer to command packet as argument
+ * Pointer to segment
+ * Number of segments Error
*
- * This is the callback function of the bus dma map load. It builds
- * the SG list.
+ * This is the callback function of the bus dma map load. It builds the SG
+ * list.
*/
static void
mrsas_data_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- struct mrsas_mpt_cmd *cmd = (struct mrsas_mpt_cmd *)arg;
- struct mrsas_softc *sc = cmd->sc;
- MRSAS_RAID_SCSI_IO_REQUEST *io_request;
- pMpi25IeeeSgeChain64_t sgl_ptr;
- int i=0, sg_processed=0;
-
- if (error)
- {
- cmd->error_code = error;
- device_printf(sc->mrsas_dev, "mrsas_data_load_cb: error=%d\n", error);
- if (error == EFBIG) {
- cmd->ccb_ptr->ccb_h.status = CAM_REQ_TOO_BIG;
- return;
- }
- }
-
- if (cmd->flags & MRSAS_DIR_IN)
- bus_dmamap_sync(cmd->sc->data_tag, cmd->data_dmamap,
- BUS_DMASYNC_PREREAD);
- if (cmd->flags & MRSAS_DIR_OUT)
- bus_dmamap_sync(cmd->sc->data_tag, cmd->data_dmamap,
- BUS_DMASYNC_PREWRITE);
- if (nseg > sc->max_num_sge) {
- device_printf(sc->mrsas_dev, "SGE count is too large or 0.\n");
- return;
- }
-
- io_request = cmd->io_request;
- sgl_ptr = (pMpi25IeeeSgeChain64_t)&io_request->SGL;
-
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
- pMpi25IeeeSgeChain64_t sgl_ptr_end = sgl_ptr;
- sgl_ptr_end += sc->max_sge_in_main_msg - 1;
- sgl_ptr_end->Flags = 0;
- }
-
- if (nseg != 0) {
- for (i=0; i < nseg; i++) {
- sgl_ptr->Address = segs[i].ds_addr;
- sgl_ptr->Length = segs[i].ds_len;
- sgl_ptr->Flags = 0;
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
- if (i == nseg - 1)
- sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
- }
- sgl_ptr++;
- sg_processed = i + 1;
- /*
- * Prepare chain element
- */
+ struct mrsas_mpt_cmd *cmd = (struct mrsas_mpt_cmd *)arg;
+ struct mrsas_softc *sc = cmd->sc;
+ MRSAS_RAID_SCSI_IO_REQUEST *io_request;
+ pMpi25IeeeSgeChain64_t sgl_ptr;
+ int i = 0, sg_processed = 0;
+
+ if (error) {
+ cmd->error_code = error;
+ device_printf(sc->mrsas_dev, "mrsas_data_load_cb: error=%d\n", error);
+ if (error == EFBIG) {
+ cmd->ccb_ptr->ccb_h.status = CAM_REQ_TOO_BIG;
+ return;
+ }
+ }
+ if (cmd->flags & MRSAS_DIR_IN)
+ bus_dmamap_sync(cmd->sc->data_tag, cmd->data_dmamap,
+ BUS_DMASYNC_PREREAD);
+ if (cmd->flags & MRSAS_DIR_OUT)
+ bus_dmamap_sync(cmd->sc->data_tag, cmd->data_dmamap,
+ BUS_DMASYNC_PREWRITE);
+ if (nseg > sc->max_num_sge) {
+ device_printf(sc->mrsas_dev, "SGE count is too large or 0.\n");
+ return;
+ }
+ io_request = cmd->io_request;
+ sgl_ptr = (pMpi25IeeeSgeChain64_t)&io_request->SGL;
+
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
+ pMpi25IeeeSgeChain64_t sgl_ptr_end = sgl_ptr;
+
+ sgl_ptr_end += sc->max_sge_in_main_msg - 1;
+ sgl_ptr_end->Flags = 0;
+ }
+ if (nseg != 0) {
+ for (i = 0; i < nseg; i++) {
+ sgl_ptr->Address = segs[i].ds_addr;
+ sgl_ptr->Length = segs[i].ds_len;
+ sgl_ptr->Flags = 0;
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
+ if (i == nseg - 1)
+ sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
+ }
+ sgl_ptr++;
+ sg_processed = i + 1;
if ((sg_processed == (sc->max_sge_in_main_msg - 1)) &&
- (nseg > sc->max_sge_in_main_msg)) {
- pMpi25IeeeSgeChain64_t sg_chain;
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
- if ((cmd->io_request->IoFlags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
- != MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
- cmd->io_request->ChainOffset = sc->chain_offset_io_request;
- else
- cmd->io_request->ChainOffset = 0;
- } else
- cmd->io_request->ChainOffset = sc->chain_offset_io_request;
- sg_chain = sgl_ptr;
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
- sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
- else
- sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
- sg_chain->Length = (sizeof(MPI2_SGE_IO_UNION) * (nseg - sg_processed));
- sg_chain->Address = cmd->chain_frame_phys_addr;
- sgl_ptr = (pMpi25IeeeSgeChain64_t)cmd->chain_frame;
+ (nseg > sc->max_sge_in_main_msg)) {
+ pMpi25IeeeSgeChain64_t sg_chain;
+
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
+ if ((cmd->io_request->IoFlags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
+ != MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
+ cmd->io_request->ChainOffset = sc->chain_offset_io_request;
+ else
+ cmd->io_request->ChainOffset = 0;
+ } else
+ cmd->io_request->ChainOffset = sc->chain_offset_io_request;
+ sg_chain = sgl_ptr;
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
+ sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
+ else
+ sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
+ sg_chain->Length = (sizeof(MPI2_SGE_IO_UNION) * (nseg - sg_processed));
+ sg_chain->Address = cmd->chain_frame_phys_addr;
+ sgl_ptr = (pMpi25IeeeSgeChain64_t)cmd->chain_frame;
}
- }
- }
- cmd->sge_count = nseg;
+ }
+ }
+ cmd->sge_count = nseg;
}
-/**
- * mrsas_freeze_simq: Freeze SIM queue
- * input: Pointer to command packet
- * Pointer to SIM
+/*
+ * mrsas_freeze_simq: Freeze SIM queue
+ * input: Pointer to command packet
+ * Pointer to SIM
*
* This function freezes the sim queue.
*/
-static void mrsas_freeze_simq(struct mrsas_mpt_cmd *cmd, struct cam_sim *sim)
+static void
+mrsas_freeze_simq(struct mrsas_mpt_cmd *cmd, struct cam_sim *sim)
{
- union ccb *ccb = (union ccb *)(cmd->ccb_ptr);
+ union ccb *ccb = (union ccb *)(cmd->ccb_ptr);
- xpt_freeze_simq(sim, 1);
- ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
- ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ xpt_freeze_simq(sim, 1);
+ ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+ ccb->ccb_h.status |= CAM_REQUEUE_REQ;
}
-void mrsas_xpt_freeze(struct mrsas_softc *sc) {
- xpt_freeze_simq(sc->sim_0, 1);
- xpt_freeze_simq(sc->sim_1, 1);
+void
+mrsas_xpt_freeze(struct mrsas_softc *sc)
+{
+ xpt_freeze_simq(sc->sim_0, 1);
+ xpt_freeze_simq(sc->sim_1, 1);
}
-
-void mrsas_xpt_release(struct mrsas_softc *sc) {
- xpt_release_simq(sc->sim_0, 1);
- xpt_release_simq(sc->sim_1, 1);
+
+void
+mrsas_xpt_release(struct mrsas_softc *sc)
+{
+ xpt_release_simq(sc->sim_0, 1);
+ xpt_release_simq(sc->sim_1, 1);
}
-/**
- * mrsas_cmd_done: Perform remaining command completion
- * input: Adapter instance soft state
- * Pointer to command packet
+/*
+ * mrsas_cmd_done: Perform remaining command completion
+ * input: Adapter instance soft state Pointer to command packet
*
- * This function calls ummap request and releases the MPT command.
+ * This function calls ummap request and releases the MPT command.
*/
-void mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd)
+void
+mrsas_cmd_done(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd)
{
- callout_stop(&cmd->cm_callout);
- mrsas_unmap_request(sc, cmd);
- mtx_lock(&sc->sim_lock);
- xpt_done(cmd->ccb_ptr);
- cmd->ccb_ptr = NULL;
- mtx_unlock(&sc->sim_lock);
- mrsas_release_mpt_cmd(cmd);
+ callout_stop(&cmd->cm_callout);
+ mrsas_unmap_request(sc, cmd);
+ mtx_lock(&sc->sim_lock);
+ xpt_done(cmd->ccb_ptr);
+ cmd->ccb_ptr = NULL;
+ mtx_unlock(&sc->sim_lock);
+ mrsas_release_mpt_cmd(cmd);
}
-/**
- * mrsas_poll: Polling entry point
- * input: Pointer to SIM
+/*
+ * mrsas_cam_poll: Polling entry point
+ * input: Pointer to SIM
*
* This is currently a stub function.
*/
-static void mrsas_poll(struct cam_sim *sim)
+static void
+mrsas_cam_poll(struct cam_sim *sim)
{
- struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim);
- mrsas_isr((void *) sc);
+ struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim);
+
+ mrsas_isr((void *)sc);
}
/*
- * mrsas_bus_scan: Perform bus scan
- * input: Adapter instance soft state
+ * mrsas_bus_scan: Perform bus scan
+ * input: Adapter instance soft state
*
- * This mrsas_bus_scan function is needed for FreeBSD 7.x. Also, it should
- * not be called in FreeBSD 8.x and later versions, where the bus scan is
- * automatic.
- */
-int mrsas_bus_scan(struct mrsas_softc *sc)
+ * This mrsas_bus_scan function is needed for FreeBSD 7.x. Also, it should not
+ * be called in FreeBSD 8.x and later versions, where the bus scan is
+ * automatic.
+ */
+int
+mrsas_bus_scan(struct mrsas_softc *sc)
{
- union ccb *ccb_0;
- union ccb *ccb_1;
-
- if ((ccb_0 = xpt_alloc_ccb()) == NULL) {
- return(ENOMEM);
- }
-
- if ((ccb_1 = xpt_alloc_ccb()) == NULL) {
- xpt_free_ccb(ccb_0);
- return(ENOMEM);
- }
-
- mtx_lock(&sc->sim_lock);
- if (xpt_create_path(&ccb_0->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_0),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP){
- xpt_free_ccb(ccb_0);
- xpt_free_ccb(ccb_1);
- mtx_unlock(&sc->sim_lock);
- return(EIO);
- }
-
- if (xpt_create_path(&ccb_1->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_1),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP){
- xpt_free_ccb(ccb_0);
- xpt_free_ccb(ccb_1);
- mtx_unlock(&sc->sim_lock);
- return(EIO);
- }
-
- mtx_unlock(&sc->sim_lock);
- xpt_rescan(ccb_0);
- xpt_rescan(ccb_1);
-
- return(0);
+ union ccb *ccb_0;
+ union ccb *ccb_1;
+
+ if ((ccb_0 = xpt_alloc_ccb()) == NULL) {
+ return (ENOMEM);
+ }
+ if ((ccb_1 = xpt_alloc_ccb()) == NULL) {
+ xpt_free_ccb(ccb_0);
+ return (ENOMEM);
+ }
+ mtx_lock(&sc->sim_lock);
+ if (xpt_create_path(&ccb_0->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_0),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb_0);
+ xpt_free_ccb(ccb_1);
+ mtx_unlock(&sc->sim_lock);
+ return (EIO);
+ }
+ if (xpt_create_path(&ccb_1->ccb_h.path, xpt_periph, cam_sim_path(sc->sim_1),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb_0);
+ xpt_free_ccb(ccb_1);
+ mtx_unlock(&sc->sim_lock);
+ return (EIO);
+ }
+ mtx_unlock(&sc->sim_lock);
+ xpt_rescan(ccb_0);
+ xpt_rescan(ccb_1);
+
+ return (0);
}
/*
- * mrsas_bus_scan_sim: Perform bus scan per SIM
- * input: Adapter instance soft state
- * This function will be called from Event handler
- * on LD creation/deletion, JBOD on/off.
- */
-int mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim)
+ * mrsas_bus_scan_sim: Perform bus scan per SIM
+ * input: adapter instance soft state
+ *
+ * This function will be called from Event handler on LD creation/deletion,
+ * JBOD on/off.
+ */
+int
+mrsas_bus_scan_sim(struct mrsas_softc *sc, struct cam_sim *sim)
{
- union ccb *ccb;
-
- if ((ccb = xpt_alloc_ccb()) == NULL) {
- return(ENOMEM);
- }
- mtx_lock(&sc->sim_lock);
- if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP){
- xpt_free_ccb(ccb);
- mtx_unlock(&sc->sim_lock);
- return(EIO);
- }
- mtx_unlock(&sc->sim_lock);
- xpt_rescan(ccb);
-
- return(0);
+ union ccb *ccb;
+
+ if ((ccb = xpt_alloc_ccb()) == NULL) {
+ return (ENOMEM);
+ }
+ mtx_lock(&sc->sim_lock);
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ mtx_unlock(&sc->sim_lock);
+ return (EIO);
+ }
+ mtx_unlock(&sc->sim_lock);
+ xpt_rescan(ccb);
+
+ return (0);
}
diff --git a/sys/dev/mrsas/mrsas_fp.c b/sys/dev/mrsas/mrsas_fp.c
index 91005a5..19bb4e4 100644
--- a/sys/dev/mrsas/mrsas_fp.c
+++ b/sys/dev/mrsas/mrsas_fp.c
@@ -1,43 +1,38 @@
/*
- * Copyright (c) 2014, LSI Corp.
- * All rights reserved.
- * Author: Marian Choy
+ * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
* Support: freebsdraid@lsi.com
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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 <ORGANIZATION> nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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
+ * <ORGANIZATION> 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 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 HOLDER 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
+ * 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 HOLDER 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.
*
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing
* official policies,either expressed or implied, of the FreeBSD Project.
*
- * Send feedback to: <megaraidfbsd@lsi.com>
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: MegaRaid FreeBSD
+ * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621
+ * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
*
*/
@@ -59,88 +54,106 @@ __FBSDID("$FreeBSD$");
* Function prototypes
*/
u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc);
-u_int8_t mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm,
- u_int64_t block, u_int32_t count);
-u_int8_t MR_BuildRaidContext(struct mrsas_softc *sc,
- struct IO_REQUEST_INFO *io_info,
- RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map);
-u_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld,
- u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
- RAID_CONTEXT *pRAID_Context,
- MR_FW_RAID_MAP_ALL *map);
-u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map);
-u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map);
-u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_FW_RAID_MAP_ALL *map);
-u_int16_t mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo,
- struct IO_REQUEST_INFO *io_info);
+u_int8_t
+mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm,
+ u_int64_t block, u_int32_t count);
+u_int8_t
+MR_BuildRaidContext(struct mrsas_softc *sc,
+ struct IO_REQUEST_INFO *io_info,
+ RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map);
+u_int8_t
+MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld,
+ u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
+ RAID_CONTEXT * pRAID_Context,
+ MR_DRV_RAID_MAP_ALL * map);
+u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map);
+u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map);
+u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map);
+u_int16_t
+mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo,
+ struct IO_REQUEST_INFO *io_info);
u_int32_t mega_mod64(u_int64_t dividend, u_int32_t divisor);
-u_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk,
- MR_FW_RAID_MAP_ALL *map, int *div_error);
+u_int32_t
+MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk,
+ MR_DRV_RAID_MAP_ALL * map, int *div_error);
u_int64_t mega_div64_32(u_int64_t dividend, u_int32_t divisor);
-void mrsas_update_load_balance_params(MR_FW_RAID_MAP_ALL *map,
- PLD_LOAD_BALANCE_INFO lbInfo);
-void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST *io_request,
- u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb,
- MR_FW_RAID_MAP_ALL *local_map_ptr, u_int32_t ref_tag,
- u_int32_t ld_block_size);
-static u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span,
- MR_FW_RAID_MAP_ALL *map);
-static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_FW_RAID_MAP_ALL *map);
-static u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm,
- MR_FW_RAID_MAP_ALL *map);
-static MR_LD_SPAN *MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span,
- MR_FW_RAID_MAP_ALL *map);
-static u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx,
- MR_FW_RAID_MAP_ALL *map);
-static MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u_int32_t ld,
- MR_FW_RAID_MAP_ALL *map);
-MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_FW_RAID_MAP_ALL *map);
+void
+mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map,
+ PLD_LOAD_BALANCE_INFO lbInfo);
+void
+mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request,
+ u_int8_t cdb_len, struct IO_REQUEST_INFO *io_info, union ccb *ccb,
+ MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag,
+ u_int32_t ld_block_size);
+static u_int16_t
+MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span,
+ MR_DRV_RAID_MAP_ALL * map);
+static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map);
+static u_int16_t
+MR_ArPdGet(u_int32_t ar, u_int32_t arm,
+ MR_DRV_RAID_MAP_ALL * map);
+static MR_LD_SPAN *
+MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span,
+ MR_DRV_RAID_MAP_ALL * map);
+static u_int8_t
+MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx,
+ MR_DRV_RAID_MAP_ALL * map);
+static MR_SPAN_BLOCK_INFO *
+MR_LdSpanInfoGet(u_int32_t ld,
+ MR_DRV_RAID_MAP_ALL * map);
+MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map);
+void MR_PopulateDrvRaidMap(struct mrsas_softc *sc);
+
/*
- * Spanset related function prototypes
- * Added for PRL11 configuration (Uneven span support)
+ * Spanset related function prototypes Added for PRL11 configuration (Uneven
+ * span support)
*/
-void mr_update_span_set(MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo);
-static u_int8_t mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld,
- u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
- RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map);
-static u_int64_t get_row_from_strip(struct mrsas_softc *sc, u_int32_t ld,
- u_int64_t strip, MR_FW_RAID_MAP_ALL *map);
-static u_int32_t mr_spanset_get_span_block(struct mrsas_softc *sc,
- u_int32_t ld, u_int64_t row, u_int64_t *span_blk,
- MR_FW_RAID_MAP_ALL *map, int *div_error);
-static u_int8_t get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span,
- u_int64_t stripe, MR_FW_RAID_MAP_ALL *map);
+void mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo);
+static u_int8_t
+mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld,
+ u_int64_t stripRow, u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
+ RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map);
+static u_int64_t
+get_row_from_strip(struct mrsas_softc *sc, u_int32_t ld,
+ u_int64_t strip, MR_DRV_RAID_MAP_ALL * map);
+static u_int32_t
+mr_spanset_get_span_block(struct mrsas_softc *sc,
+ u_int32_t ld, u_int64_t row, u_int64_t *span_blk,
+ MR_DRV_RAID_MAP_ALL * map, int *div_error);
+static u_int8_t
+get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span,
+ u_int64_t stripe, MR_DRV_RAID_MAP_ALL * map);
/*
- * Spanset related defines
- * Added for PRL11 configuration(Uneven span support)
+ * Spanset related defines Added for PRL11 configuration(Uneven span support)
*/
-#define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize
-#define SPAN_ROW_DATA_SIZE(map_, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize
-#define SPAN_INVALID 0xff
-#define SPAN_DEBUG 0
+#define SPAN_ROW_SIZE(map, ld, index_) MR_LdSpanPtrGet(ld, index_, map)->spanRowSize
+#define SPAN_ROW_DATA_SIZE(map_, ld, index_) \
+ MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize
+#define SPAN_INVALID 0xff
+#define SPAN_DEBUG 0
/*
* Related Defines
*/
-typedef u_int64_t REGION_KEY;
-typedef u_int32_t REGION_LEN;
+typedef u_int64_t REGION_KEY;
+typedef u_int32_t REGION_LEN;
-#define MR_LD_STATE_OPTIMAL 3
-#define FALSE 0
-#define TRUE 1
+#define MR_LD_STATE_OPTIMAL 3
+#define FALSE 0
+#define TRUE 1
/*
* Related Macros
*/
-#define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) )
+#define ABS_DIFF(a,b) ( ((a) > (b)) ? ((a) - (b)) : ((b) - (a)) )
-#define swap32(x) \
+#define swap32(x) \
((unsigned int)( \
(((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
(((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \
@@ -149,20 +162,20 @@ typedef u_int32_t REGION_LEN;
/*
- * In-line functions for mod and divide of 64-bit dividend and 32-bit divisor.
- * Assumes a check for a divisor of zero is not possible.
- *
- * @param dividend : Dividend
- * @param divisor : Divisor
- * @return remainder
+ * In-line functions for mod and divide of 64-bit dividend and 32-bit
+ * divisor. Assumes a check for a divisor of zero is not possible.
+ *
+ * @param dividend: Dividend
+ * @param divisor: Divisor
+ * @return remainder
*/
-#define mega_mod64(dividend, divisor) ({ \
+#define mega_mod64(dividend, divisor) ({ \
int remainder; \
remainder = ((u_int64_t) (dividend)) % (u_int32_t) (divisor); \
remainder;})
-#define mega_div64_32(dividend, divisor) ({ \
+#define mega_div64_32(dividend, divisor) ({ \
int quotient; \
quotient = ((u_int64_t) (dividend)) / (u_int32_t) (divisor); \
quotient;})
@@ -170,1282 +183,1336 @@ quotient;})
/*
* Various RAID map access functions. These functions access the various
- * parts of the RAID map and returns the appropriate parameters.
+ * parts of the RAID map and returns the appropriate parameters.
*/
-MR_LD_RAID *MR_LdRaidGet(u_int32_t ld, MR_FW_RAID_MAP_ALL *map)
+MR_LD_RAID *
+MR_LdRaidGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map)
{
- return (&map->raidMap.ldSpanMap[ld].ldRaid);
+ return (&map->raidMap.ldSpanMap[ld].ldRaid);
}
-u_int16_t MR_GetLDTgtId(u_int32_t ld, MR_FW_RAID_MAP_ALL *map)
+u_int16_t
+MR_GetLDTgtId(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map)
{
- return (map->raidMap.ldSpanMap[ld].ldRaid.targetId);
+ return (map->raidMap.ldSpanMap[ld].ldRaid.targetId);
}
-static u_int16_t MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_FW_RAID_MAP_ALL *map)
+static u_int16_t
+MR_LdSpanArrayGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map)
{
- return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef;
+ return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef;
}
-static u_int8_t MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_FW_RAID_MAP_ALL *map)
+static u_int8_t
+MR_LdDataArmGet(u_int32_t ld, u_int32_t armIdx, MR_DRV_RAID_MAP_ALL * map)
{
- return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
+ return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
}
-static u_int16_t MR_PdDevHandleGet(u_int32_t pd, MR_FW_RAID_MAP_ALL *map)
+static u_int16_t
+MR_PdDevHandleGet(u_int32_t pd, MR_DRV_RAID_MAP_ALL * map)
{
- return map->raidMap.devHndlInfo[pd].curDevHdl;
+ return map->raidMap.devHndlInfo[pd].curDevHdl;
}
-static u_int16_t MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_FW_RAID_MAP_ALL *map)
+static u_int16_t
+MR_ArPdGet(u_int32_t ar, u_int32_t arm, MR_DRV_RAID_MAP_ALL * map)
{
- return map->raidMap.arMapInfo[ar].pd[arm];
+ return map->raidMap.arMapInfo[ar].pd[arm];
}
-static MR_LD_SPAN *MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_FW_RAID_MAP_ALL *map)
+static MR_LD_SPAN *
+MR_LdSpanPtrGet(u_int32_t ld, u_int32_t span, MR_DRV_RAID_MAP_ALL * map)
{
- return &map->raidMap.ldSpanMap[ld].spanBlock[span].span;
+ return &map->raidMap.ldSpanMap[ld].spanBlock[span].span;
}
-static MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u_int32_t ld, MR_FW_RAID_MAP_ALL *map)
+static MR_SPAN_BLOCK_INFO *
+MR_LdSpanInfoGet(u_int32_t ld, MR_DRV_RAID_MAP_ALL * map)
{
- return &map->raidMap.ldSpanMap[ld].spanBlock[0];
+ return &map->raidMap.ldSpanMap[ld].spanBlock[0];
}
-u_int16_t MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map)
+u_int16_t
+MR_TargetIdToLdGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map)
{
- return map->raidMap.ldTgtIdToLd[ldTgtId];
+ return map->raidMap.ldTgtIdToLd[ldTgtId];
}
-u_int32_t MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_FW_RAID_MAP_ALL *map)
+u_int32_t
+MR_LdBlockSizeGet(u_int32_t ldTgtId, MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid;
- u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE;
+ MR_LD_RAID *raid;
+ u_int32_t ld, ldBlockSize = MRSAS_SCSIBLOCKSIZE;
+
+ ld = MR_TargetIdToLdGet(ldTgtId, map);
+
+ /*
+ * Check if logical drive was removed.
+ */
+ if (ld >= MAX_LOGICAL_DRIVES)
+ return ldBlockSize;
- ld = MR_TargetIdToLdGet(ldTgtId, map);
+ raid = MR_LdRaidGet(ld, map);
+ ldBlockSize = raid->logicalBlockLength;
+ if (!ldBlockSize)
+ ldBlockSize = MRSAS_SCSIBLOCKSIZE;
- /*
- * Check if logical drive was removed.
- */
- if (ld >= MAX_LOGICAL_DRIVES)
- return ldBlockSize;
+ return ldBlockSize;
+}
- raid = MR_LdRaidGet(ld, map);
- ldBlockSize = raid->logicalBlockLength;
- if (!ldBlockSize)
- ldBlockSize = MRSAS_SCSIBLOCKSIZE;
+/*
+ * This function will Populate Driver Map using firmware raid map
+ */
+void
+MR_PopulateDrvRaidMap(struct mrsas_softc *sc)
+{
+ MR_FW_RAID_MAP_ALL *fw_map_old = NULL;
+ MR_FW_RAID_MAP *pFwRaidMap = NULL;
+ unsigned int i;
+
+ MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)];
+ MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap;
+
+ if (sc->max256vdSupport) {
+ memcpy(sc->ld_drv_map[sc->map_id & 1],
+ sc->raidmap_mem[sc->map_id & 1],
+ sc->current_map_sz);
+ /*
+ * New Raid map will not set totalSize, so keep expected
+ * value for legacy code in ValidateMapInfo
+ */
+ pDrvRaidMap->totalSize = sizeof(MR_FW_RAID_MAP_EXT);
+ } else {
+ fw_map_old = (MR_FW_RAID_MAP_ALL *) sc->raidmap_mem[(sc->map_id & 1)];
+ pFwRaidMap = &fw_map_old->raidMap;
+
+#if VD_EXT_DEBUG
+ for (i = 0; i < pFwRaidMap->ldCount; i++) {
+ device_printf(sc->mrsas_dev,
+ "Index 0x%x Target Id 0x%x Seq Num 0x%x Size 0/%lx\n", i,
+ fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId,
+ fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum,
+ fw_map_old->raidMap.ldSpanMap[i].ldRaid.size);
+ }
+#endif
+
+ memset(drv_map, 0, sc->drv_map_sz);
+ pDrvRaidMap->totalSize = pFwRaidMap->totalSize;
+ pDrvRaidMap->ldCount = pFwRaidMap->ldCount;
+ pDrvRaidMap->fpPdIoTimeoutSec =
+ pFwRaidMap->fpPdIoTimeoutSec;
+
+ for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) {
+ pDrvRaidMap->ldTgtIdToLd[i] =
+ (u_int8_t)pFwRaidMap->ldTgtIdToLd[i];
+ }
+
+ for (i = 0; i < pDrvRaidMap->ldCount; i++) {
+ pDrvRaidMap->ldSpanMap[i] =
+ pFwRaidMap->ldSpanMap[i];
+
+#if VD_EXT_DEBUG
+ device_printf(sc->mrsas_dev, "pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x "
+ "pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n",
+ i, i, pFwRaidMap->ldSpanMap[i].ldRaid.targetId,
+ pFwRaidMap->ldSpanMap[i].ldRaid.seqNum,
+ (u_int32_t)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize);
+ device_printf(sc->mrsas_dev, "pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x"
+ "pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x size 0x%x\n", i, i,
+ pDrvRaidMap->ldSpanMap[i].ldRaid.targetId,
+ pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum,
+ (u_int32_t)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize);
+ device_printf(sc->mrsas_dev, "drv raid map all %p raid map %p LD RAID MAP %p/%p\n",
+ drv_map, pDrvRaidMap,
+ &pFwRaidMap->ldSpanMap[i].ldRaid, &pDrvRaidMap->ldSpanMap[i].ldRaid);
+#endif
+ }
- return ldBlockSize;
+ memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo,
+ sizeof(MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS);
+ memcpy(pDrvRaidMap->devHndlInfo, pFwRaidMap->devHndlInfo,
+ sizeof(MR_DEV_HANDLE_INFO) *
+ MAX_RAIDMAP_PHYSICAL_DEVICES);
+ }
}
-/**
- * MR_ValidateMapInfo: Validate RAID map
- * input: Adapter instance soft state
+/*
+ * MR_ValidateMapInfo: Validate RAID map
+ * input: Adapter instance soft state
*
- * This function checks and validates the loaded RAID map. It returns 0 if
+ * This function checks and validates the loaded RAID map. It returns 0 if
* successful, and 1 otherwise.
*/
-u_int8_t MR_ValidateMapInfo(struct mrsas_softc *sc)
+u_int8_t
+MR_ValidateMapInfo(struct mrsas_softc *sc)
{
if (!sc) {
return 1;
}
- uint32_t total_map_sz;
- MR_FW_RAID_MAP_ALL *map = sc->raidmap_mem[(sc->map_id & 1)];
- MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap;
- PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) &sc->log_to_span;
-
- total_map_sz = (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP) +
- (sizeof(MR_LD_SPAN_MAP) * pFwRaidMap->ldCount));
-
- if (pFwRaidMap->totalSize != total_map_sz) {
- device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", total_map_sz);
- device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP));
- device_printf(sc->mrsas_dev, "pFwRaidMap->totalSize=%x\n", pFwRaidMap->totalSize);
- return 1;
- }
-
- if (sc->UnevenSpanSupport) {
- mr_update_span_set(map, ldSpanInfo);
- }
+ MR_PopulateDrvRaidMap(sc);
+
+ MR_DRV_RAID_MAP_ALL *drv_map = sc->ld_drv_map[(sc->map_id & 1)];
+ MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap;
+
+ u_int32_t expected_map_size;
+
+ drv_map = sc->ld_drv_map[(sc->map_id & 1)];
+ pDrvRaidMap = &drv_map->raidMap;
+ PLD_SPAN_INFO ldSpanInfo = (PLD_SPAN_INFO) & sc->log_to_span;
+
+ if (sc->max256vdSupport)
+ expected_map_size = sizeof(MR_FW_RAID_MAP_EXT);
+ else
+ expected_map_size =
+ (sizeof(MR_FW_RAID_MAP) - sizeof(MR_LD_SPAN_MAP)) +
+ (sizeof(MR_LD_SPAN_MAP) * pDrvRaidMap->ldCount);
- mrsas_update_load_balance_params(map, sc->load_balance_info);
+ if (pDrvRaidMap->totalSize != expected_map_size) {
+ device_printf(sc->mrsas_dev, "map size %x not matching ld count\n", expected_map_size);
+ device_printf(sc->mrsas_dev, "span map= %x\n", (unsigned int)sizeof(MR_LD_SPAN_MAP));
+ device_printf(sc->mrsas_dev, "pDrvRaidMap->totalSize=%x\n", pDrvRaidMap->totalSize);
+ return 1;
+ }
+ if (sc->UnevenSpanSupport) {
+ printf("Updating span set\n\n");
+ mr_update_span_set(drv_map, ldSpanInfo);
+ }
+ mrsas_update_load_balance_params(drv_map, sc->load_balance_info);
- return 0;
+ return 0;
}
/*
- * ******************************************************************************
- *
- * Function to print info about span set created in driver from FW raid map
- *
- * Inputs :
- * map - LD map
- * ldSpanInfo - ldSpanInfo per HBA instance
- *
- *
- * */
+ *
+ * Function to print info about span set created in driver from FW raid map
+ *
+ * Inputs: map
+ * ldSpanInfo: ld map span info per HBA instance
+ *
+ *
+ */
#if SPAN_DEBUG
-static int getSpanInfo(MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo)
+static int
+getSpanInfo(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo)
{
- u_int8_t span;
- u_int32_t element;
- MR_LD_RAID *raid;
- LD_SPAN_SET *span_set;
- MR_QUAD_ELEMENT *quad;
- int ldCount;
- u_int16_t ld;
-
- for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++)
- {
- ld = MR_TargetIdToLdGet(ldCount, map);
- if (ld >= MAX_LOGICAL_DRIVES) {
- continue;
- }
- raid = MR_LdRaidGet(ld, map);
- printf("LD %x: span_depth=%x\n", ld, raid->spanDepth);
- for (span=0; span<raid->spanDepth; span++)
- printf("Span=%x, number of quads=%x\n", span,
- map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements);
- for (element=0; element < MAX_QUAD_DEPTH; element++) {
- span_set = &(ldSpanInfo[ld].span_set[element]);
- if (span_set->span_row_data_width == 0) break;
-
- printf(" Span Set %x: width=%x, diff=%x\n", element,
- (unsigned int)span_set->span_row_data_width,
- (unsigned int)span_set->diff);
- printf(" logical LBA start=0x%08lx, end=0x%08lx\n",
- (long unsigned int)span_set->log_start_lba,
- (long unsigned int)span_set->log_end_lba);
- printf(" span row start=0x%08lx, end=0x%08lx\n",
- (long unsigned int)span_set->span_row_start,
- (long unsigned int)span_set->span_row_end);
- printf(" data row start=0x%08lx, end=0x%08lx\n",
- (long unsigned int)span_set->data_row_start,
- (long unsigned int)span_set->data_row_end);
- printf(" data strip start=0x%08lx, end=0x%08lx\n",
- (long unsigned int)span_set->data_strip_start,
- (long unsigned int)span_set->data_strip_end);
-
- for (span=0; span<raid->spanDepth; span++) {
- if (map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements >=element+1){
- quad = &map->raidMap.ldSpanMap[ld].
- spanBlock[span].block_span_info.
- quad[element];
- printf(" Span=%x, Quad=%x, diff=%x\n", span,
- element, quad->diff);
- printf(" offset_in_span=0x%08lx\n",
- (long unsigned int)quad->offsetInSpan);
- printf(" logical start=0x%08lx, end=0x%08lx\n",
- (long unsigned int)quad->logStart,
- (long unsigned int)quad->logEnd);
- }
- }
- }
- }
- return 0;
+ u_int8_t span;
+ u_int32_t element;
+ MR_LD_RAID *raid;
+ LD_SPAN_SET *span_set;
+ MR_QUAD_ELEMENT *quad;
+ int ldCount;
+ u_int16_t ld;
+
+ for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
+ ld = MR_TargetIdToLdGet(ldCount, map);
+ if (ld >= MAX_LOGICAL_DRIVES) {
+ continue;
+ }
+ raid = MR_LdRaidGet(ld, map);
+ printf("LD %x: span_depth=%x\n", ld, raid->spanDepth);
+ for (span = 0; span < raid->spanDepth; span++)
+ printf("Span=%x, number of quads=%x\n", span,
+ map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements);
+ for (element = 0; element < MAX_QUAD_DEPTH; element++) {
+ span_set = &(ldSpanInfo[ld].span_set[element]);
+ if (span_set->span_row_data_width == 0)
+ break;
+
+ printf("Span Set %x: width=%x, diff=%x\n", element,
+ (unsigned int)span_set->span_row_data_width,
+ (unsigned int)span_set->diff);
+ printf("logical LBA start=0x%08lx, end=0x%08lx\n",
+ (long unsigned int)span_set->log_start_lba,
+ (long unsigned int)span_set->log_end_lba);
+ printf("span row start=0x%08lx, end=0x%08lx\n",
+ (long unsigned int)span_set->span_row_start,
+ (long unsigned int)span_set->span_row_end);
+ printf("data row start=0x%08lx, end=0x%08lx\n",
+ (long unsigned int)span_set->data_row_start,
+ (long unsigned int)span_set->data_row_end);
+ printf("data strip start=0x%08lx, end=0x%08lx\n",
+ (long unsigned int)span_set->data_strip_start,
+ (long unsigned int)span_set->data_strip_end);
+
+ for (span = 0; span < raid->spanDepth; span++) {
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= element + 1) {
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].block_span_info.
+ quad[element];
+ printf("Span=%x, Quad=%x, diff=%x\n", span,
+ element, quad->diff);
+ printf("offset_in_span=0x%08lx\n",
+ (long unsigned int)quad->offsetInSpan);
+ printf("logical start=0x%08lx, end=0x%08lx\n",
+ (long unsigned int)quad->logStart,
+ (long unsigned int)quad->logEnd);
+ }
+ }
+ }
+ }
+ return 0;
}
+
#endif
/*
-******************************************************************************
-*
-* This routine calculates the Span block for given row using spanset.
-*
-* Inputs :
-* instance - HBA instance
-* ld - Logical drive number
-* row - Row number
-* map - LD map
-*
-* Outputs :
-*
-* span - Span number
-* block - Absolute Block number in the physical disk
-* div_error - Devide error code.
-*/
-
-u_int32_t mr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row,
- u_int64_t *span_blk, MR_FW_RAID_MAP_ALL *map, int *div_error)
+ *
+ * This routine calculates the Span block for given row using spanset.
+ *
+ * Inputs : HBA instance
+ * ld: Logical drive number
+ * row: Row number
+ * map: LD map
+ *
+ * Outputs : span - Span number block
+ * - Absolute Block number in the physical disk
+ * div_error - Devide error code.
+ */
+
+u_int32_t
+mr_spanset_get_span_block(struct mrsas_softc *sc, u_int32_t ld, u_int64_t row,
+ u_int64_t *span_blk, MR_DRV_RAID_MAP_ALL * map, int *div_error)
{
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- LD_SPAN_SET *span_set;
- MR_QUAD_ELEMENT *quad;
- u_int32_t span, info;
- PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
-
- for (info=0; info < MAX_QUAD_DEPTH; info++) {
- span_set = &(ldSpanInfo[ld].span_set[info]);
-
- if (span_set->span_row_data_width == 0) break;
- if (row > span_set->data_row_end) continue;
-
- for (span=0; span<raid->spanDepth; span++)
- if (map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements >= info+1) {
- quad = &map->raidMap.ldSpanMap[ld].
- spanBlock[span].
- block_span_info.quad[info];
- if (quad->diff == 0) {
- *div_error = 1;
- return span;
- }
- if ( quad->logStart <= row &&
- row <= quad->logEnd &&
- (mega_mod64(row - quad->logStart,
- quad->diff)) == 0 ) {
- if (span_blk != NULL) {
- u_int64_t blk;
- blk = mega_div64_32
- ((row - quad->logStart),
- quad->diff);
- blk = (blk + quad->offsetInSpan)
- << raid->stripeShift;
- *span_blk = blk;
- }
- return span;
- }
- }
- }
- return SPAN_INVALID;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ MR_QUAD_ELEMENT *quad;
+ u_int32_t span, info;
+ PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
+
+ for (info = 0; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+ if (row > span_set->data_row_end)
+ continue;
+
+ for (span = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info + 1) {
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].
+ block_span_info.quad[info];
+ if (quad->diff == 0) {
+ *div_error = 1;
+ return span;
+ }
+ if (quad->logStart <= row &&
+ row <= quad->logEnd &&
+ (mega_mod64(row - quad->logStart,
+ quad->diff)) == 0) {
+ if (span_blk != NULL) {
+ u_int64_t blk;
+
+ blk = mega_div64_32
+ ((row - quad->logStart),
+ quad->diff);
+ blk = (blk + quad->offsetInSpan)
+ << raid->stripeShift;
+ *span_blk = blk;
+ }
+ return span;
+ }
+ }
+ }
+ return SPAN_INVALID;
}
/*
-******************************************************************************
-*
-* This routine calculates the row for given strip using spanset.
-*
-* Inputs :
-* instance - HBA instance
-* ld - Logical drive number
-* Strip - Strip
-* map - LD map
-*
-* Outputs :
-*
-* row - row associated with strip
-*/
-
-static u_int64_t get_row_from_strip(struct mrsas_softc *sc,
- u_int32_t ld, u_int64_t strip, MR_FW_RAID_MAP_ALL *map)
+ *
+ * This routine calculates the row for given strip using spanset.
+ *
+ * Inputs : HBA instance
+ * ld: Logical drive number
+ * Strip: Strip
+ * map: LD map
+ *
+ * Outputs : row - row associated with strip
+ */
+
+static u_int64_t
+get_row_from_strip(struct mrsas_softc *sc,
+ u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- LD_SPAN_SET *span_set;
- PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
- u_int32_t info, strip_offset, span, span_offset;
- u_int64_t span_set_Strip, span_set_Row;
-
- for (info=0; info < MAX_QUAD_DEPTH; info++) {
- span_set = &(ldSpanInfo[ld].span_set[info]);
-
- if (span_set->span_row_data_width == 0) break;
- if (strip > span_set->data_strip_end) continue;
-
- span_set_Strip = strip - span_set->data_strip_start;
- strip_offset = mega_mod64(span_set_Strip,
- span_set->span_row_data_width);
- span_set_Row = mega_div64_32(span_set_Strip,
- span_set->span_row_data_width) * span_set->diff;
- for (span=0,span_offset=0; span<raid->spanDepth; span++)
- if (map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements >=info+1) {
- if (strip_offset >=
- span_set->strip_offset[span])
- span_offset++;
- else
- break;
- }
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx "
- "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip,
- (unsigned long long)span_set_Strip,
- (unsigned long long)span_set_Row,
- (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset);
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip,
- (unsigned long long) span_set->data_row_start +
- (unsigned long long) span_set_Row + (span_offset - 1));
- return (span_set->data_row_start + span_set_Row + (span_offset - 1));
- }
- return -1LLU;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
+ u_int32_t info, strip_offset, span, span_offset;
+ u_int64_t span_set_Strip, span_set_Row;
+
+ for (info = 0; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+ if (strip > span_set->data_strip_end)
+ continue;
+
+ span_set_Strip = strip - span_set->data_strip_start;
+ strip_offset = mega_mod64(span_set_Strip,
+ span_set->span_row_data_width);
+ span_set_Row = mega_div64_32(span_set_Strip,
+ span_set->span_row_data_width) * span_set->diff;
+ for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info + 1) {
+ if (strip_offset >=
+ span_set->strip_offset[span])
+ span_offset++;
+ else
+ break;
+ }
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx "
+ "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip,
+ (unsigned long long)span_set_Strip,
+ (unsigned long long)span_set_Row,
+ (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset);
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip,
+ (unsigned long long)span_set->data_row_start +
+ (unsigned long long)span_set_Row + (span_offset - 1));
+ return (span_set->data_row_start + span_set_Row + (span_offset - 1));
+ }
+ return -1LLU;
}
/*
-******************************************************************************
-*
-* This routine calculates the Start Strip for given row using spanset.
-*
-* Inputs :
-* instance - HBA instance
-* ld - Logical drive number
-* row - Row number
-* map - LD map
-*
-* Outputs :
-*
-* Strip - Start strip associated with row
-*/
-
-static u_int64_t get_strip_from_row(struct mrsas_softc *sc,
- u_int32_t ld, u_int64_t row, MR_FW_RAID_MAP_ALL *map)
+ *
+ * This routine calculates the Start Strip for given row using spanset.
+ *
+ * Inputs: HBA instance
+ * ld: Logical drive number
+ * row: Row number
+ * map: LD map
+ *
+ * Outputs : Strip - Start strip associated with row
+ */
+
+static u_int64_t
+get_strip_from_row(struct mrsas_softc *sc,
+ u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- LD_SPAN_SET *span_set;
- MR_QUAD_ELEMENT *quad;
- PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
- u_int32_t span, info;
- u_int64_t strip;
-
- for (info=0; info<MAX_QUAD_DEPTH; info++) {
- span_set = &(ldSpanInfo[ld].span_set[info]);
-
- if (span_set->span_row_data_width == 0) break;
- if (row > span_set->data_row_end) continue;
-
- for (span=0; span<raid->spanDepth; span++)
- if (map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements >=info+1) {
- quad = &map->raidMap.ldSpanMap[ld].
- spanBlock[span].block_span_info.quad[info];
- if ( quad->logStart <= row &&
- row <= quad->logEnd &&
- mega_mod64((row - quad->logStart),
- quad->diff) == 0 ) {
- strip = mega_div64_32
- (((row - span_set->data_row_start)
- - quad->logStart),
- quad->diff);
- strip *= span_set->span_row_data_width;
- strip += span_set->data_strip_start;
- strip += span_set->strip_offset[span];
- return strip;
- }
- }
- }
- mrsas_dprint(sc, MRSAS_PRL11,"LSI Debug - get_strip_from_row: returns invalid "
- "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row);
- return -1;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ MR_QUAD_ELEMENT *quad;
+ PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
+ u_int32_t span, info;
+ u_int64_t strip;
+
+ for (info = 0; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+ if (row > span_set->data_row_end)
+ continue;
+
+ for (span = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info + 1) {
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].block_span_info.quad[info];
+ if (quad->logStart <= row &&
+ row <= quad->logEnd &&
+ mega_mod64((row - quad->logStart),
+ quad->diff) == 0) {
+ strip = mega_div64_32
+ (((row - span_set->data_row_start)
+ - quad->logStart),
+ quad->diff);
+ strip *= span_set->span_row_data_width;
+ strip += span_set->data_strip_start;
+ strip += span_set->strip_offset[span];
+ return strip;
+ }
+ }
+ }
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug - get_strip_from_row: returns invalid "
+ "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row);
+ return -1;
}
/*
-******************************************************************************
-*
-* This routine calculates the Physical Arm for given strip using spanset.
-*
-* Inputs :
-* instance - HBA instance
-* ld - Logical drive number
-* strip - Strip
-* map - LD map
-*
-* Outputs :
-*
-* Phys Arm - Phys Arm associated with strip
-*/
-
-static u_int32_t get_arm_from_strip(struct mrsas_softc *sc,
- u_int32_t ld, u_int64_t strip, MR_FW_RAID_MAP_ALL *map)
+ * *****************************************************************************
+ *
+ *
+ * This routine calculates the Physical Arm for given strip using spanset.
+ *
+ * Inputs : HBA instance
+ * Logical drive number
+ * Strip
+ * LD map
+ *
+ * Outputs : Phys Arm - Phys Arm associated with strip
+ */
+
+static u_int32_t
+get_arm_from_strip(struct mrsas_softc *sc,
+ u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- LD_SPAN_SET *span_set;
- PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
- u_int32_t info, strip_offset, span, span_offset;
-
- for (info=0; info<MAX_QUAD_DEPTH; info++) {
- span_set = &(ldSpanInfo[ld].span_set[info]);
-
- if (span_set->span_row_data_width == 0) break;
- if (strip > span_set->data_strip_end) continue;
-
- strip_offset = (u_int32_t)mega_mod64
- ((strip - span_set->data_strip_start),
- span_set->span_row_data_width);
-
- for (span=0,span_offset=0; span<raid->spanDepth; span++)
- if (map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements >=info+1) {
- if (strip_offset >=
- span_set->strip_offset[span])
- span_offset =
- span_set->strip_offset[span];
- else
- break;
- }
- mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: "
- " for ld=0x%x strip=0x%lx arm is 0x%x\n", ld,
- (long unsigned int)strip, (strip_offset - span_offset));
- return (strip_offset - span_offset);
- }
-
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm"
- " for ld=%x strip=%lx\n", ld, (long unsigned int)strip);
-
- return -1;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ LD_SPAN_SET *span_set;
+ PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
+ u_int32_t info, strip_offset, span, span_offset;
+
+ for (info = 0; info < MAX_QUAD_DEPTH; info++) {
+ span_set = &(ldSpanInfo[ld].span_set[info]);
+
+ if (span_set->span_row_data_width == 0)
+ break;
+ if (strip > span_set->data_strip_end)
+ continue;
+
+ strip_offset = (u_int32_t)mega_mod64
+ ((strip - span_set->data_strip_start),
+ span_set->span_row_data_width);
+
+ for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements >= info + 1) {
+ if (strip_offset >= span_set->strip_offset[span])
+ span_offset = span_set->strip_offset[span];
+ else
+ break;
+ }
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: "
+ "for ld=0x%x strip=0x%lx arm is 0x%x\n", ld,
+ (long unsigned int)strip, (strip_offset - span_offset));
+ return (strip_offset - span_offset);
+ }
+
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm"
+ " for ld=%x strip=%lx\n", ld, (long unsigned int)strip);
+
+ return -1;
}
/* This Function will return Phys arm */
-u_int8_t get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe,
- MR_FW_RAID_MAP_ALL *map)
+u_int8_t
+get_arm(struct mrsas_softc *sc, u_int32_t ld, u_int8_t span, u_int64_t stripe,
+ MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- /* Need to check correct default value */
- u_int32_t arm = 0;
-
- switch (raid->level) {
- case 0:
- case 5:
- case 6:
- arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span));
- break;
- case 1:
- // start with logical arm
- arm = get_arm_from_strip(sc, ld, stripe, map);
- arm *= 2;
- break;
-
- }
-
- return arm;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+
+ /* Need to check correct default value */
+ u_int32_t arm = 0;
+
+ switch (raid->level) {
+ case 0:
+ case 5:
+ case 6:
+ arm = mega_mod64(stripe, SPAN_ROW_SIZE(map, ld, span));
+ break;
+ case 1:
+ /* start with logical arm */
+ arm = get_arm_from_strip(sc, ld, stripe, map);
+ arm *= 2;
+ break;
+ }
+
+ return arm;
}
/*
-******************************************************************************
-*
-* This routine calculates the arm, span and block for the specified stripe and
-* reference in stripe using spanset
-*
-* Inputs :
-*
-* ld - Logical drive number
-* stripRow - Stripe number
-* stripRef - Reference in stripe
-*
-* Outputs :
-*
-* span - Span number
-* block - Absolute Block number in the physical disk
-*/
-static u_int8_t mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow,
- u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
- RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map)
+ *
+ * This routine calculates the arm, span and block for the specified stripe and
+ * reference in stripe using spanset
+ *
+ * Inputs : Logical drive number
+ * stripRow: Stripe number
+ * stripRef: Reference in stripe
+ *
+ * Outputs : span - Span number block - Absolute Block
+ * number in the physical disk
+ */
+static u_int8_t
+mr_spanset_get_phy_params(struct mrsas_softc *sc, u_int32_t ld, u_int64_t stripRow,
+ u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
+ RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- u_int32_t pd, arRef;
- u_int8_t physArm, span;
- u_int64_t row;
- u_int8_t retval = TRUE;
- u_int64_t *pdBlock = &io_info->pdBlock;
- u_int16_t *pDevHandle = &io_info->devHandle;
- u_int32_t logArm, rowMod, armQ, arm;
- u_int8_t do_invader = 0;
-
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
- do_invader = 1;
-
- // Get row and span from io_info for Uneven Span IO.
- row = io_info->start_row;
- span = io_info->start_span;
-
-
- if (raid->level == 6) {
- logArm = get_arm_from_strip(sc, ld, stripRow, map);
- rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span));
- armQ = SPAN_ROW_SIZE(map,ld,span) - 1 - rowMod;
- arm = armQ + 1 + logArm;
- if (arm >= SPAN_ROW_SIZE(map, ld, span))
- arm -= SPAN_ROW_SIZE(map ,ld ,span);
- physArm = (u_int8_t)arm;
- } else
- // Calculate the arm
- physArm = get_arm(sc, ld, span, stripRow, map);
-
-
- arRef = MR_LdSpanArrayGet(ld, span, map);
- pd = MR_ArPdGet(arRef, physArm, map);
-
- if (pd != MR_PD_INVALID)
- *pDevHandle = MR_PdDevHandleGet(pd, map);
- else {
- *pDevHandle = MR_PD_INVALID;
- if ((raid->level >= 5) && ((!do_invader) || (do_invader &&
- raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
- pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
- else if (raid->level == 1) {
- pd = MR_ArPdGet(arRef, physArm + 1, map);
- if (pd != MR_PD_INVALID)
- *pDevHandle = MR_PdDevHandleGet(pd, map);
- }
- }
-
- *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
- pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
- return retval;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ u_int32_t pd, arRef;
+ u_int8_t physArm, span;
+ u_int64_t row;
+ u_int8_t retval = TRUE;
+ u_int64_t *pdBlock = &io_info->pdBlock;
+ u_int16_t *pDevHandle = &io_info->devHandle;
+ u_int32_t logArm, rowMod, armQ, arm;
+ u_int8_t do_invader = 0;
+
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
+ do_invader = 1;
+
+ /* Get row and span from io_info for Uneven Span IO. */
+ row = io_info->start_row;
+ span = io_info->start_span;
+
+
+ if (raid->level == 6) {
+ logArm = get_arm_from_strip(sc, ld, stripRow, map);
+ rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span));
+ armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod;
+ arm = armQ + 1 + logArm;
+ if (arm >= SPAN_ROW_SIZE(map, ld, span))
+ arm -= SPAN_ROW_SIZE(map, ld, span);
+ physArm = (u_int8_t)arm;
+ } else
+ /* Calculate the arm */
+ physArm = get_arm(sc, ld, span, stripRow, map);
+
+
+ arRef = MR_LdSpanArrayGet(ld, span, map);
+ pd = MR_ArPdGet(arRef, physArm, map);
+
+ if (pd != MR_PD_INVALID)
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ else {
+ *pDevHandle = MR_PD_INVALID;
+ if ((raid->level >= 5) && ((!do_invader) || (do_invader &&
+ raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
+ pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
+ else if (raid->level == 1) {
+ pd = MR_ArPdGet(arRef, physArm + 1, map);
+ if (pd != MR_PD_INVALID)
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ }
+ }
+
+ *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
+ pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
+ return retval;
}
-/**
-* MR_BuildRaidContext: Set up Fast path RAID context
-*
-* This function will initiate command processing. The start/end row
-* and strip information is calculated then the lock is acquired.
-* This function will return 0 if region lock was acquired OR return
-* num strips.
-*/
-u_int8_t
+/*
+ * MR_BuildRaidContext: Set up Fast path RAID context
+ *
+ * This function will initiate command processing. The start/end row and strip
+ * information is calculated then the lock is acquired. This function will
+ * return 0 if region lock was acquired OR return num strips.
+ */
+u_int8_t
MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info,
- RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map)
+ RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid;
- u_int32_t ld, stripSize, stripe_mask;
- u_int64_t endLba, endStrip, endRow, start_row, start_strip;
- REGION_KEY regStart;
- REGION_LEN regSize;
- u_int8_t num_strips, numRows;
- u_int16_t ref_in_start_stripe, ref_in_end_stripe;
- u_int64_t ldStartBlock;
- u_int32_t numBlocks, ldTgtId;
- u_int8_t isRead, stripIdx;
- u_int8_t retval = 0;
+ MR_LD_RAID *raid;
+ u_int32_t ld, stripSize, stripe_mask;
+ u_int64_t endLba, endStrip, endRow, start_row, start_strip;
+ REGION_KEY regStart;
+ REGION_LEN regSize;
+ u_int8_t num_strips, numRows;
+ u_int16_t ref_in_start_stripe, ref_in_end_stripe;
+ u_int64_t ldStartBlock;
+ u_int32_t numBlocks, ldTgtId;
+ u_int8_t isRead, stripIdx;
+ u_int8_t retval = 0;
u_int8_t startlba_span = SPAN_INVALID;
- u_int64_t *pdBlock = &io_info->pdBlock;
- int error_code = 0;
-
- ldStartBlock = io_info->ldStartBlock;
- numBlocks = io_info->numBlocks;
- ldTgtId = io_info->ldTgtId;
- isRead = io_info->isRead;
-
+ u_int64_t *pdBlock = &io_info->pdBlock;
+ int error_code = 0;
+
+ ldStartBlock = io_info->ldStartBlock;
+ numBlocks = io_info->numBlocks;
+ ldTgtId = io_info->ldTgtId;
+ isRead = io_info->isRead;
+
io_info->IoforUnevenSpan = 0;
- io_info->start_span = SPAN_INVALID;
-
- ld = MR_TargetIdToLdGet(ldTgtId, map);
- raid = MR_LdRaidGet(ld, map);
-
- /*
- * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero
- * return FALSE
- */
- if (raid->rowDataSize == 0) {
- if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0)
- return FALSE;
- else if (sc->UnevenSpanSupport) {
- io_info->IoforUnevenSpan = 1;
- }
- else {
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x,"
- " but there is _NO_ UnevenSpanSupport\n",
- MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize);
- return FALSE;
- }
+ io_info->start_span = SPAN_INVALID;
+
+ ld = MR_TargetIdToLdGet(ldTgtId, map);
+ raid = MR_LdRaidGet(ld, map);
+
+ if (raid->rowDataSize == 0) {
+ if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0)
+ return FALSE;
+ else if (sc->UnevenSpanSupport) {
+ io_info->IoforUnevenSpan = 1;
+ } else {
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x,"
+ " but there is _NO_ UnevenSpanSupport\n",
+ MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize);
+ return FALSE;
+ }
+ }
+ stripSize = 1 << raid->stripeShift;
+ stripe_mask = stripSize - 1;
+ /*
+ * calculate starting row and stripe, and number of strips and rows
+ */
+ start_strip = ldStartBlock >> raid->stripeShift;
+ ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask);
+ endLba = ldStartBlock + numBlocks - 1;
+ ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask);
+ endStrip = endLba >> raid->stripeShift;
+ num_strips = (u_int8_t)(endStrip - start_strip + 1); /* End strip */
+ if (io_info->IoforUnevenSpan) {
+ start_row = get_row_from_strip(sc, ld, start_strip, map);
+ endRow = get_row_from_strip(sc, ld, endStrip, map);
+ if (raid->spanDepth == 1) {
+ startlba_span = 0;
+ *pdBlock = start_row << raid->stripeShift;
+ } else {
+ startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row,
+ pdBlock, map, &error_code);
+ if (error_code == 1) {
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n",
+ __func__, __LINE__);
+ return FALSE;
+ }
+ }
+ if (startlba_span == SPAN_INVALID) {
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx,"
+ "start strip %llx endSrip %llx\n", __func__,
+ __LINE__, (unsigned long long)start_row,
+ (unsigned long long)start_strip,
+ (unsigned long long)endStrip);
+ return FALSE;
+ }
+ io_info->start_span = startlba_span;
+ io_info->start_row = start_row;
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, "
+ " start strip 0x%llx endSrip 0x%llx span 0x%x\n",
+ __func__, __LINE__, (unsigned long long)start_row,
+ (unsigned long long)start_strip,
+ (unsigned long long)endStrip, startlba_span);
+ mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n",
+ (unsigned long long)start_row, (unsigned long long)endRow, startlba_span);
+ } else {
+ start_row = mega_div64_32(start_strip, raid->rowDataSize);
+ endRow = mega_div64_32(endStrip, raid->rowDataSize);
}
- stripSize = 1 << raid->stripeShift;
- stripe_mask = stripSize-1;
- /*
- * calculate starting row and stripe, and number of strips and rows
- */
- start_strip = ldStartBlock >> raid->stripeShift;
- ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask);
- endLba = ldStartBlock + numBlocks - 1;
- ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask);
- endStrip = endLba >> raid->stripeShift;
- num_strips = (u_int8_t)(endStrip - start_strip + 1); // End strip
- if (io_info->IoforUnevenSpan) {
- start_row = get_row_from_strip(sc, ld, start_strip, map);
- endRow = get_row_from_strip(sc, ld, endStrip, map);
- if (raid->spanDepth == 1) {
- startlba_span = 0;
- *pdBlock = start_row << raid->stripeShift;
- } else {
- startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row,
- pdBlock, map, &error_code);
- if (error_code == 1) {
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n",
- __func__, __LINE__);
- return FALSE;
- }
- }
- if (startlba_span == SPAN_INVALID) {
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx,"
- "start strip %llx endSrip %llx\n", __func__,
- __LINE__, (unsigned long long)start_row,
- (unsigned long long)start_strip,
- (unsigned long long)endStrip);
- return FALSE;
- }
- io_info->start_span = startlba_span;
- io_info->start_row = start_row;
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, "
- " start strip 0x%llx endSrip 0x%llx span 0x%x\n",
- __func__, __LINE__, (unsigned long long)start_row,
- (unsigned long long)start_strip,
- (unsigned long long)endStrip, startlba_span);
- mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n",
- (unsigned long long)start_row, (unsigned long long)endRow, startlba_span);
- } else {
- start_row = mega_div64_32(start_strip, raid->rowDataSize); // Start Row
- endRow = mega_div64_32(endStrip, raid->rowDataSize);
- }
-
- numRows = (u_int8_t)(endRow - start_row + 1); // get the row count
-
- /*
- * Calculate region info. (Assume region at start of first row, and
- * assume this IO needs the full row - will adjust if not true.)
- */
- regStart = start_row << raid->stripeShift;
- regSize = stripSize;
-
- /* Check if we can send this I/O via FastPath */
- if (raid->capability.fpCapable) {
- if (isRead)
- io_info->fpOkForIo = (raid->capability.fpReadCapable &&
- ((num_strips == 1) ||
- raid->capability.
- fpReadAcrossStripe));
- else
- io_info->fpOkForIo = (raid->capability.fpWriteCapable &&
- ((num_strips == 1) ||
- raid->capability.
- fpWriteAcrossStripe));
- }
- else
- io_info->fpOkForIo = FALSE;
-
- if (numRows == 1) {
- if (num_strips == 1) {
- /* single-strip IOs can always lock only the data needed,
- multi-strip IOs always need to full stripe locked */
- regStart += ref_in_start_stripe;
- regSize = numBlocks;
- }
- }
- else if (io_info->IoforUnevenSpan == 0){
- // For Even span region lock optimization.
- // If the start strip is the last in the start row
- if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
- regStart += ref_in_start_stripe;
- // initialize count to sectors from startRef to end of strip
- regSize = stripSize - ref_in_start_stripe;
- }
- // add complete rows in the middle of the transfer
+
+ numRows = (u_int8_t)(endRow - start_row + 1); /* get the row count */
+
+ /*
+ * Calculate region info. (Assume region at start of first row, and
+ * assume this IO needs the full row - will adjust if not true.)
+ */
+ regStart = start_row << raid->stripeShift;
+ regSize = stripSize;
+
+ /* Check if we can send this I/O via FastPath */
+ if (raid->capability.fpCapable) {
+ if (isRead)
+ io_info->fpOkForIo = (raid->capability.fpReadCapable &&
+ ((num_strips == 1) ||
+ raid->capability.fpReadAcrossStripe));
+ else
+ io_info->fpOkForIo = (raid->capability.fpWriteCapable &&
+ ((num_strips == 1) ||
+ raid->capability.fpWriteAcrossStripe));
+ } else
+ io_info->fpOkForIo = FALSE;
+
+ if (numRows == 1) {
+ if (num_strips == 1) {
+ regStart += ref_in_start_stripe;
+ regSize = numBlocks;
+ }
+ } else if (io_info->IoforUnevenSpan == 0) {
+ /*
+ * For Even span region lock optimization. If the start strip
+ * is the last in the start row
+ */
+ if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
+ regStart += ref_in_start_stripe;
+ /*
+ * initialize count to sectors from startRef to end
+ * of strip
+ */
+ regSize = stripSize - ref_in_start_stripe;
+ }
+ /* add complete rows in the middle of the transfer */
if (numRows > 2)
- regSize += (numRows-2) << raid->stripeShift;
-
- // if IO ends within first strip of last row
- if (endStrip == endRow*raid->rowDataSize)
- regSize += ref_in_end_stripe+1;
- else
- regSize += stripSize;
- } else {
- //For Uneven span region lock optimization.
- // If the start strip is the last in the start row
- if (start_strip == (get_strip_from_row(sc, ld, start_row, map) +
- SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) {
- regStart += ref_in_start_stripe;
- // initialize count to sectors from startRef to end of strip
+ regSize += (numRows - 2) << raid->stripeShift;
+
+ /* if IO ends within first strip of last row */
+ if (endStrip == endRow * raid->rowDataSize)
+ regSize += ref_in_end_stripe + 1;
+ else
+ regSize += stripSize;
+ } else {
+ if (start_strip == (get_strip_from_row(sc, ld, start_row, map) +
+ SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) {
+ regStart += ref_in_start_stripe;
+ /*
+ * initialize count to sectors from startRef to end
+ * of strip
+ */
regSize = stripSize - ref_in_start_stripe;
- }
- // add complete rows in the middle of the transfer
- if (numRows > 2)
- regSize += (numRows-2) << raid->stripeShift;
-
- // if IO ends within first strip of last row
- if (endStrip == get_strip_from_row(sc, ld, endRow, map))
- regSize += ref_in_end_stripe+1;
- else
- regSize += stripSize;
- }
- pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
- if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
- pRAID_Context->regLockFlags = (isRead)? raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
- else
- pRAID_Context->regLockFlags = (isRead)? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
- pRAID_Context->VirtualDiskTgtId = raid->targetId;
- pRAID_Context->regLockRowLBA = regStart;
- pRAID_Context->regLockLength = regSize;
- pRAID_Context->configSeqNum = raid->seqNum;
-
- /*
- * Get Phy Params only if FP capable, or else leave it to MR firmware
- * to do the calculation.
- */
- if (io_info->fpOkForIo) {
- retval = io_info->IoforUnevenSpan ?
- mr_spanset_get_phy_params(sc, ld,
- start_strip, ref_in_start_stripe, io_info,
- pRAID_Context, map) :
- MR_GetPhyParams(sc, ld, start_strip,
- ref_in_start_stripe, io_info, pRAID_Context, map);
- /* If IO on an invalid Pd, then FP is not possible */
- if (io_info->devHandle == MR_PD_INVALID)
- io_info->fpOkForIo = FALSE;
- return retval;
- }
- else if (isRead) {
- for (stripIdx=0; stripIdx<num_strips; stripIdx++) {
- retval = io_info->IoforUnevenSpan ?
- mr_spanset_get_phy_params(sc, ld,
- start_strip + stripIdx,
- ref_in_start_stripe, io_info,
- pRAID_Context, map) :
- MR_GetPhyParams(sc, ld,
- start_strip + stripIdx, ref_in_start_stripe,
- io_info, pRAID_Context, map);
- if (!retval)
- return TRUE;
- }
- }
+ }
+ /* add complete rows in the middle of the transfer */
+ if (numRows > 2)
+ regSize += (numRows - 2) << raid->stripeShift;
+
+ /* if IO ends within first strip of last row */
+ if (endStrip == get_strip_from_row(sc, ld, endRow, map))
+ regSize += ref_in_end_stripe + 1;
+ else
+ regSize += stripSize;
+ }
+ pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
+ if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
+ pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
+ else
+ pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
+ pRAID_Context->VirtualDiskTgtId = raid->targetId;
+ pRAID_Context->regLockRowLBA = regStart;
+ pRAID_Context->regLockLength = regSize;
+ pRAID_Context->configSeqNum = raid->seqNum;
+
+ /*
+ * Get Phy Params only if FP capable, or else leave it to MR firmware
+ * to do the calculation.
+ */
+ if (io_info->fpOkForIo) {
+ retval = io_info->IoforUnevenSpan ?
+ mr_spanset_get_phy_params(sc, ld, start_strip,
+ ref_in_start_stripe, io_info, pRAID_Context, map) :
+ MR_GetPhyParams(sc, ld, start_strip,
+ ref_in_start_stripe, io_info, pRAID_Context, map);
+ /* If IO on an invalid Pd, then FP is not possible */
+ if (io_info->devHandle == MR_PD_INVALID)
+ io_info->fpOkForIo = FALSE;
+ return retval;
+ } else if (isRead) {
+ for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
+ retval = io_info->IoforUnevenSpan ?
+ mr_spanset_get_phy_params(sc, ld, start_strip + stripIdx,
+ ref_in_start_stripe, io_info, pRAID_Context, map) :
+ MR_GetPhyParams(sc, ld, start_strip + stripIdx,
+ ref_in_start_stripe, io_info, pRAID_Context, map);
+ if (!retval)
+ return TRUE;
+ }
+ }
#if SPAN_DEBUG
- // Just for testing what arm we get for strip.
- get_arm_from_strip(sc, ld, start_strip, map);
+ /* Just for testing what arm we get for strip. */
+ get_arm_from_strip(sc, ld, start_strip, map);
#endif
- return TRUE;
+ return TRUE;
}
/*
-******************************************************************************
-*
-* This routine pepare spanset info from Valid Raid map and store it into
-* local copy of ldSpanInfo per instance data structure.
-*
-* Inputs :
-* map - LD map
-* ldSpanInfo - ldSpanInfo per HBA instance
-*
-*/
-void mr_update_span_set(MR_FW_RAID_MAP_ALL *map, PLD_SPAN_INFO ldSpanInfo)
+ *
+ * This routine pepare spanset info from Valid Raid map and store it into local
+ * copy of ldSpanInfo per instance data structure.
+ *
+ * Inputs : LD map
+ * ldSpanInfo per HBA instance
+ *
+ */
+void
+mr_update_span_set(MR_DRV_RAID_MAP_ALL * map, PLD_SPAN_INFO ldSpanInfo)
{
- u_int8_t span,count;
- u_int32_t element,span_row_width;
- u_int64_t span_row;
- MR_LD_RAID *raid;
- LD_SPAN_SET *span_set, *span_set_prev;
- MR_QUAD_ELEMENT *quad;
- int ldCount;
- u_int16_t ld;
-
- if (!ldSpanInfo)
- return;
-
- for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++)
- {
- ld = MR_TargetIdToLdGet(ldCount, map);
- if (ld >= MAX_LOGICAL_DRIVES)
- continue;
- raid = MR_LdRaidGet(ld, map);
- for (element=0; element < MAX_QUAD_DEPTH; element++) {
- for (span=0; span < raid->spanDepth; span++) {
- if (map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements < element+1)
- continue;
- // TO-DO
- span_set = &(ldSpanInfo[ld].span_set[element]);
- quad = &map->raidMap.ldSpanMap[ld].
- spanBlock[span].block_span_info.
- quad[element];
-
- span_set->diff = quad->diff;
-
- for (count=0,span_row_width=0;
- count<raid->spanDepth; count++) {
- if (map->raidMap.ldSpanMap[ld].
- spanBlock[count].
- block_span_info.
- noElements >=element+1) {
- span_set->strip_offset[count] =
- span_row_width;
- span_row_width +=
- MR_LdSpanPtrGet
- (ld, count, map)->spanRowDataSize;
+ u_int8_t span, count;
+ u_int32_t element, span_row_width;
+ u_int64_t span_row;
+ MR_LD_RAID *raid;
+ LD_SPAN_SET *span_set, *span_set_prev;
+ MR_QUAD_ELEMENT *quad;
+ int ldCount;
+ u_int16_t ld;
+
+ for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
+ ld = MR_TargetIdToLdGet(ldCount, map);
+ if (ld >= MAX_LOGICAL_DRIVES)
+ continue;
+ raid = MR_LdRaidGet(ld, map);
+ for (element = 0; element < MAX_QUAD_DEPTH; element++) {
+ for (span = 0; span < raid->spanDepth; span++) {
+ if (map->raidMap.ldSpanMap[ld].spanBlock[span].
+ block_span_info.noElements < element + 1)
+ continue;
+ /* TO-DO */
+ span_set = &(ldSpanInfo[ld].span_set[element]);
+ quad = &map->raidMap.ldSpanMap[ld].
+ spanBlock[span].block_span_info.quad[element];
+
+ span_set->diff = quad->diff;
+
+ for (count = 0, span_row_width = 0;
+ count < raid->spanDepth; count++) {
+ if (map->raidMap.ldSpanMap[ld].spanBlock[count].
+ block_span_info.noElements >= element + 1) {
+ span_set->strip_offset[count] = span_row_width;
+ span_row_width +=
+ MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize;
#if SPAN_DEBUG
- printf("LSI Debug span %x rowDataSize %x\n",
- count, MR_LdSpanPtrGet
- (ld, count, map)->spanRowDataSize);
+ printf("LSI Debug span %x rowDataSize %x\n", count,
+ MR_LdSpanPtrGet(ld, count, map)->spanRowDataSize);
#endif
- }
- }
-
- span_set->span_row_data_width = span_row_width;
- span_row = mega_div64_32(((quad->logEnd -
- quad->logStart) + quad->diff), quad->diff);
-
- if (element == 0) {
- span_set->log_start_lba = 0;
- span_set->log_end_lba =
- ((span_row << raid->stripeShift) * span_row_width) - 1;
-
- span_set->span_row_start = 0;
- span_set->span_row_end = span_row - 1;
-
- span_set->data_strip_start = 0;
- span_set->data_strip_end =
- (span_row * span_row_width) - 1;
-
- span_set->data_row_start = 0;
- span_set->data_row_end =
- (span_row * quad->diff) - 1;
- } else {
- span_set_prev = &(ldSpanInfo[ld].
- span_set[element - 1]);
- span_set->log_start_lba =
- span_set_prev->log_end_lba + 1;
- span_set->log_end_lba =
- span_set->log_start_lba +
- ((span_row << raid->stripeShift) * span_row_width) - 1;
-
- span_set->span_row_start =
- span_set_prev->span_row_end + 1;
- span_set->span_row_end =
- span_set->span_row_start + span_row - 1;
-
- span_set->data_strip_start =
- span_set_prev->data_strip_end + 1;
- span_set->data_strip_end =
- span_set->data_strip_start +
- (span_row * span_row_width) - 1;
-
- span_set->data_row_start =
- span_set_prev->data_row_end + 1;
- span_set->data_row_end =
- span_set->data_row_start +
- (span_row * quad->diff) - 1;
- }
- break;
- }
- if (span == raid->spanDepth) break; // no quads remain
- }
- }
+ }
+ }
+
+ span_set->span_row_data_width = span_row_width;
+ span_row = mega_div64_32(((quad->logEnd -
+ quad->logStart) + quad->diff), quad->diff);
+
+ if (element == 0) {
+ span_set->log_start_lba = 0;
+ span_set->log_end_lba =
+ ((span_row << raid->stripeShift) * span_row_width) - 1;
+
+ span_set->span_row_start = 0;
+ span_set->span_row_end = span_row - 1;
+
+ span_set->data_strip_start = 0;
+ span_set->data_strip_end = (span_row * span_row_width) - 1;
+
+ span_set->data_row_start = 0;
+ span_set->data_row_end = (span_row * quad->diff) - 1;
+ } else {
+ span_set_prev = &(ldSpanInfo[ld].span_set[element - 1]);
+ span_set->log_start_lba = span_set_prev->log_end_lba + 1;
+ span_set->log_end_lba = span_set->log_start_lba +
+ ((span_row << raid->stripeShift) * span_row_width) - 1;
+
+ span_set->span_row_start = span_set_prev->span_row_end + 1;
+ span_set->span_row_end =
+ span_set->span_row_start + span_row - 1;
+
+ span_set->data_strip_start =
+ span_set_prev->data_strip_end + 1;
+ span_set->data_strip_end = span_set->data_strip_start +
+ (span_row * span_row_width) - 1;
+
+ span_set->data_row_start = span_set_prev->data_row_end + 1;
+ span_set->data_row_end = span_set->data_row_start +
+ (span_row * quad->diff) - 1;
+ }
+ break;
+ }
+ if (span == raid->spanDepth)
+ break; /* no quads remain */
+ }
+ }
#if SPAN_DEBUG
- getSpanInfo(map, ldSpanInfo); //to get span set info
+ getSpanInfo(map, ldSpanInfo); /* to get span set info */
#endif
}
-/**
- * mrsas_update_load_balance_params: Update load balance parmas
- * Inputs: map pointer
- * Load balance info
- * io_info pointer
+/*
+ * mrsas_update_load_balance_params: Update load balance parmas
+ * Inputs: map pointer
+ * Load balance info
*
- * This function updates the load balance parameters for the LD config
- * of a two drive optimal RAID-1.
+ * This function updates the load balance parameters for the LD config of a two
+ * drive optimal RAID-1.
*/
-void mrsas_update_load_balance_params(MR_FW_RAID_MAP_ALL *map,
- PLD_LOAD_BALANCE_INFO lbInfo)
+void
+mrsas_update_load_balance_params(MR_DRV_RAID_MAP_ALL * map,
+ PLD_LOAD_BALANCE_INFO lbInfo)
{
- int ldCount;
- u_int16_t ld;
- u_int32_t pd, arRef;
- MR_LD_RAID *raid;
-
- for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++)
- {
- ld = MR_TargetIdToLdGet(ldCount, map);
- if (ld >= MAX_LOGICAL_DRIVES) {
- lbInfo[ldCount].loadBalanceFlag = 0;
- continue;
- }
-
- raid = MR_LdRaidGet(ld, map);
-
- /* Two drive Optimal RAID 1 */
- if ((raid->level == 1) && (raid->rowSize == 2) &&
- (raid->spanDepth == 1)
- && raid->ldState == MR_LD_STATE_OPTIMAL) {
- lbInfo[ldCount].loadBalanceFlag = 1;
-
- /* Get the array on which this span is present */
- arRef = MR_LdSpanArrayGet(ld, 0, map);
-
- /* Get the PD */
- pd = MR_ArPdGet(arRef, 0, map);
- /* Get dev handle from PD */
- lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map);
- pd = MR_ArPdGet(arRef, 1, map);
- lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map);
- }
- else
- lbInfo[ldCount].loadBalanceFlag = 0;
- }
+ int ldCount;
+ u_int16_t ld;
+ u_int32_t pd, arRef;
+ MR_LD_RAID *raid;
+
+ for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) {
+ ld = MR_TargetIdToLdGet(ldCount, map);
+ if (ld >= MAX_LOGICAL_DRIVES) {
+ lbInfo[ldCount].loadBalanceFlag = 0;
+ continue;
+ }
+ raid = MR_LdRaidGet(ld, map);
+
+ /* Two drive Optimal RAID 1 */
+ if ((raid->level == 1) && (raid->rowSize == 2) &&
+ (raid->spanDepth == 1)
+ && raid->ldState == MR_LD_STATE_OPTIMAL) {
+ lbInfo[ldCount].loadBalanceFlag = 1;
+
+ /* Get the array on which this span is present */
+ arRef = MR_LdSpanArrayGet(ld, 0, map);
+
+ /* Get the PD */
+ pd = MR_ArPdGet(arRef, 0, map);
+ /* Get dev handle from PD */
+ lbInfo[ldCount].raid1DevHandle[0] = MR_PdDevHandleGet(pd, map);
+ pd = MR_ArPdGet(arRef, 1, map);
+ lbInfo[ldCount].raid1DevHandle[1] = MR_PdDevHandleGet(pd, map);
+ } else
+ lbInfo[ldCount].loadBalanceFlag = 0;
+ }
}
-/**
- * mrsas_set_pd_lba: Sets PD LBA
- * input: io_request pointer
- * CDB length
- * io_info pointer
- * Pointer to CCB
- * Local RAID map pointer
- * Start block of IO
- * Block Size
+/*
+ * mrsas_set_pd_lba: Sets PD LBA
+ * input: io_request pointer
+ * CDB length
+ * io_info pointer
+ * Pointer to CCB
+ * Local RAID map pointer
+ * Start block of IO Block Size
*
* Used to set the PD logical block address in CDB for FP IOs.
*/
-void mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST *io_request, u_int8_t cdb_len,
+void
+mrsas_set_pd_lba(MRSAS_RAID_SCSI_IO_REQUEST * io_request, u_int8_t cdb_len,
struct IO_REQUEST_INFO *io_info, union ccb *ccb,
- MR_FW_RAID_MAP_ALL *local_map_ptr, u_int32_t ref_tag,
+ MR_DRV_RAID_MAP_ALL * local_map_ptr, u_int32_t ref_tag,
u_int32_t ld_block_size)
{
- MR_LD_RAID *raid;
- u_int32_t ld;
- u_int64_t start_blk = io_info->pdBlock;
- u_int8_t *cdb = io_request->CDB.CDB32;
- u_int32_t num_blocks = io_info->numBlocks;
- u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0;
- struct ccb_hdr *ccb_h = &(ccb->ccb_h);
-
- /* Check if T10 PI (DIF) is enabled for this LD */
- ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
- raid = MR_LdRaidGet(ld, local_map_ptr);
- if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
- memset(cdb, 0, sizeof(io_request->CDB.CDB32));
- cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD;
- cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN;
-
- if (ccb_h->flags == CAM_DIR_OUT)
- cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32;
- else
- cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32;
- cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL;
-
- /* LBA */
- cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff);
- cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff);
- cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff);
- cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff);
- cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff);
- cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff);
- cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff);
- cdb[19] = (u_int8_t)(start_blk & 0xff);
-
- /* Logical block reference tag */
- io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag);
- io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
- io_request->IoFlags = 32; /* Specify 32-byte cdb */
-
- /* Transfer length */
- cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff);
- cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff);
- cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff);
- cdb[31] = (u_int8_t)(num_blocks & 0xff);
-
- /* set SCSI IO EEDP Flags */
- if (ccb_h->flags == CAM_DIR_OUT) {
- io_request->EEDPFlags =
- MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
- MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
- }
- else {
- io_request->EEDPFlags =
- MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
- MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
- }
- io_request->Control |= (0x4 << 26);
- io_request->EEDPBlockSize = ld_block_size;
- }
- else {
- /* Some drives don't support 16/12 byte CDB's, convert to 10 */
- if (((cdb_len == 12) || (cdb_len == 16)) &&
- (start_blk <= 0xffffffff)) {
- if (cdb_len == 16) {
- opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
- flagvals = cdb[1];
- groupnum = cdb[14];
- control = cdb[15];
- }
- else {
- opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
- flagvals = cdb[1];
- groupnum = cdb[10];
- control = cdb[11];
- }
-
- memset(cdb, 0, sizeof(io_request->CDB.CDB32));
-
- cdb[0] = opcode;
- cdb[1] = flagvals;
- cdb[6] = groupnum;
- cdb[9] = control;
-
- /* Transfer length */
- cdb[8] = (u_int8_t)(num_blocks & 0xff);
- cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff);
-
- io_request->IoFlags = 10; /* Specify 10-byte cdb */
- cdb_len = 10;
- } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
- /* Convert to 16 byte CDB for large LBA's */
- switch (cdb_len) {
- case 6:
- opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
- control = cdb[5];
- break;
- case 10:
- opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16;
- flagvals = cdb[1];
- groupnum = cdb[6];
- control = cdb[9];
- break;
- case 12:
- opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16;
- flagvals = cdb[1];
- groupnum = cdb[10];
- control = cdb[11];
- break;
- }
-
- memset(cdb, 0, sizeof(io_request->CDB.CDB32));
-
- cdb[0] = opcode;
- cdb[1] = flagvals;
- cdb[14] = groupnum;
- cdb[15] = control;
-
- /* Transfer length */
- cdb[13] = (u_int8_t)(num_blocks & 0xff);
- cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff);
- cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff);
- cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff);
-
- io_request->IoFlags = 16; /* Specify 16-byte cdb */
- cdb_len = 16;
- } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) {
- /* convert to 10 byte CDB */
- opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10;
- control = cdb[5];
-
- memset(cdb, 0, sizeof(io_request->CDB.CDB32));
- cdb[0] = opcode;
- cdb[9] = control;
-
- /* Set transfer length */
- cdb[8] = (u_int8_t)(num_blocks & 0xff);
- cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff);
-
- /* Specify 10-byte cdb */
- cdb_len = 10;
+ MR_LD_RAID *raid;
+ u_int32_t ld;
+ u_int64_t start_blk = io_info->pdBlock;
+ u_int8_t *cdb = io_request->CDB.CDB32;
+ u_int32_t num_blocks = io_info->numBlocks;
+ u_int8_t opcode = 0, flagvals = 0, groupnum = 0, control = 0;
+ struct ccb_hdr *ccb_h = &(ccb->ccb_h);
+
+ /* Check if T10 PI (DIF) is enabled for this LD */
+ ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr);
+ raid = MR_LdRaidGet(ld, local_map_ptr);
+ if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) {
+ memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+ cdb[0] = MRSAS_SCSI_VARIABLE_LENGTH_CMD;
+ cdb[7] = MRSAS_SCSI_ADDL_CDB_LEN;
+
+ if (ccb_h->flags == CAM_DIR_OUT)
+ cdb[9] = MRSAS_SCSI_SERVICE_ACTION_READ32;
+ else
+ cdb[9] = MRSAS_SCSI_SERVICE_ACTION_WRITE32;
+ cdb[10] = MRSAS_RD_WR_PROTECT_CHECK_ALL;
+
+ /* LBA */
+ cdb[12] = (u_int8_t)((start_blk >> 56) & 0xff);
+ cdb[13] = (u_int8_t)((start_blk >> 48) & 0xff);
+ cdb[14] = (u_int8_t)((start_blk >> 40) & 0xff);
+ cdb[15] = (u_int8_t)((start_blk >> 32) & 0xff);
+ cdb[16] = (u_int8_t)((start_blk >> 24) & 0xff);
+ cdb[17] = (u_int8_t)((start_blk >> 16) & 0xff);
+ cdb[18] = (u_int8_t)((start_blk >> 8) & 0xff);
+ cdb[19] = (u_int8_t)(start_blk & 0xff);
+
+ /* Logical block reference tag */
+ io_request->CDB.EEDP32.PrimaryReferenceTag = swap32(ref_tag);
+ io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
+ io_request->IoFlags = 32; /* Specify 32-byte cdb */
+
+ /* Transfer length */
+ cdb[28] = (u_int8_t)((num_blocks >> 24) & 0xff);
+ cdb[29] = (u_int8_t)((num_blocks >> 16) & 0xff);
+ cdb[30] = (u_int8_t)((num_blocks >> 8) & 0xff);
+ cdb[31] = (u_int8_t)(num_blocks & 0xff);
+
+ /* set SCSI IO EEDP Flags */
+ if (ccb_h->flags == CAM_DIR_OUT) {
+ io_request->EEDPFlags =
+ MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG |
+ MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
+ } else {
+ io_request->EEDPFlags =
+ MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
+ MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
+ }
+ io_request->Control |= (0x4 << 26);
+ io_request->EEDPBlockSize = ld_block_size;
+ } else {
+ /* Some drives don't support 16/12 byte CDB's, convert to 10 */
+ if (((cdb_len == 12) || (cdb_len == 16)) &&
+ (start_blk <= 0xffffffff)) {
+ if (cdb_len == 16) {
+ opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10;
+ flagvals = cdb[1];
+ groupnum = cdb[14];
+ control = cdb[15];
+ } else {
+ opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10;
+ flagvals = cdb[1];
+ groupnum = cdb[10];
+ control = cdb[11];
+ }
+
+ memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+
+ cdb[0] = opcode;
+ cdb[1] = flagvals;
+ cdb[6] = groupnum;
+ cdb[9] = control;
+
+ /* Transfer length */
+ cdb[8] = (u_int8_t)(num_blocks & 0xff);
+ cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff);
+
+ io_request->IoFlags = 10; /* Specify 10-byte cdb */
+ cdb_len = 10;
+ } else if ((cdb_len < 16) && (start_blk > 0xffffffff)) {
+ /* Convert to 16 byte CDB for large LBA's */
+ switch (cdb_len) {
+ case 6:
+ opcode = cdb[0] == READ_6 ? READ_16 : WRITE_16;
+ control = cdb[5];
+ break;
+ case 10:
+ opcode = cdb[0] == READ_10 ? READ_16 : WRITE_16;
+ flagvals = cdb[1];
+ groupnum = cdb[6];
+ control = cdb[9];
+ break;
+ case 12:
+ opcode = cdb[0] == READ_12 ? READ_16 : WRITE_16;
+ flagvals = cdb[1];
+ groupnum = cdb[10];
+ control = cdb[11];
+ break;
+ }
+
+ memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+
+ cdb[0] = opcode;
+ cdb[1] = flagvals;
+ cdb[14] = groupnum;
+ cdb[15] = control;
+
+ /* Transfer length */
+ cdb[13] = (u_int8_t)(num_blocks & 0xff);
+ cdb[12] = (u_int8_t)((num_blocks >> 8) & 0xff);
+ cdb[11] = (u_int8_t)((num_blocks >> 16) & 0xff);
+ cdb[10] = (u_int8_t)((num_blocks >> 24) & 0xff);
+
+ io_request->IoFlags = 16; /* Specify 16-byte cdb */
+ cdb_len = 16;
+ } else if ((cdb_len == 6) && (start_blk > 0x1fffff)) {
+ /* convert to 10 byte CDB */
+ opcode = cdb[0] == READ_6 ? READ_10 : WRITE_10;
+ control = cdb[5];
+
+ memset(cdb, 0, sizeof(io_request->CDB.CDB32));
+ cdb[0] = opcode;
+ cdb[9] = control;
+
+ /* Set transfer length */
+ cdb[8] = (u_int8_t)(num_blocks & 0xff);
+ cdb[7] = (u_int8_t)((num_blocks >> 8) & 0xff);
+
+ /* Specify 10-byte cdb */
+ cdb_len = 10;
+ }
+ /* Fall through normal case, just load LBA here */
+ u_int8_t val = cdb[1] & 0xE0;
+ switch (cdb_len) {
+ case 6:
+ cdb[3] = (u_int8_t)(start_blk & 0xff);
+ cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff);
+ cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f);
+ break;
+ case 10:
+ cdb[5] = (u_int8_t)(start_blk & 0xff);
+ cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff);
+ cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff);
+ cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff);
+ break;
+ case 12:
+ cdb[5] = (u_int8_t)(start_blk & 0xff);
+ cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff);
+ cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff);
+ cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff);
+ break;
+ case 16:
+ cdb[9] = (u_int8_t)(start_blk & 0xff);
+ cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff);
+ cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff);
+ cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff);
+ cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff);
+ cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff);
+ cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff);
+ cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff);
+ break;
+ }
}
-
- /* Fall through normal case, just load LBA here */
- switch (cdb_len)
- {
- case 6:
- {
- u_int8_t val = cdb[1] & 0xE0;
- cdb[3] = (u_int8_t)(start_blk & 0xff);
- cdb[2] = (u_int8_t)((start_blk >> 8) & 0xff);
- cdb[1] = val | ((u_int8_t)(start_blk >> 16) & 0x1f);
- break;
- }
- case 10:
- cdb[5] = (u_int8_t)(start_blk & 0xff);
- cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff);
- cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff);
- cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff);
- break;
- case 12:
- cdb[5] = (u_int8_t)(start_blk & 0xff);
- cdb[4] = (u_int8_t)((start_blk >> 8) & 0xff);
- cdb[3] = (u_int8_t)((start_blk >> 16) & 0xff);
- cdb[2] = (u_int8_t)((start_blk >> 24) & 0xff);
- break;
- case 16:
- cdb[9] = (u_int8_t)(start_blk & 0xff);
- cdb[8] = (u_int8_t)((start_blk >> 8) & 0xff);
- cdb[7] = (u_int8_t)((start_blk >> 16) & 0xff);
- cdb[6] = (u_int8_t)((start_blk >> 24) & 0xff);
- cdb[5] = (u_int8_t)((start_blk >> 32) & 0xff);
- cdb[4] = (u_int8_t)((start_blk >> 40) & 0xff);
- cdb[3] = (u_int8_t)((start_blk >> 48) & 0xff);
- cdb[2] = (u_int8_t)((start_blk >> 56) & 0xff);
- break;
- }
- }
}
-/**
- * mrsas_get_best_arm Determine the best spindle arm
- * Inputs: Load balance info
+/*
+ * mrsas_get_best_arm: Determine the best spindle arm
+ * Inputs: Load balance info
*
* This function determines and returns the best arm by looking at the
* parameters of the last PD access.
*/
-u_int8_t mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm,
- u_int64_t block, u_int32_t count)
+u_int8_t
+mrsas_get_best_arm(PLD_LOAD_BALANCE_INFO lbInfo, u_int8_t arm,
+ u_int64_t block, u_int32_t count)
{
- u_int16_t pend0, pend1;
- u_int64_t diff0, diff1;
- u_int8_t bestArm;
+ u_int16_t pend0, pend1;
+ u_int64_t diff0, diff1;
+ u_int8_t bestArm;
- /* get the pending cmds for the data and mirror arms */
- pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]);
- pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]);
+ /* get the pending cmds for the data and mirror arms */
+ pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]);
+ pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]);
- /* Determine the disk whose head is nearer to the req. block */
- diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]);
- diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]);
- bestArm = (diff0 <= diff1 ? 0 : 1);
+ /* Determine the disk whose head is nearer to the req. block */
+ diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]);
+ diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]);
+ bestArm = (diff0 <= diff1 ? 0 : 1);
- if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16))
- bestArm ^= 1;
+ if ((bestArm == arm && pend0 > pend1 + 16) || (bestArm != arm && pend1 > pend0 + 16))
+ bestArm ^= 1;
- /* Update the last accessed block on the correct pd */
- lbInfo->last_accessed_block[bestArm] = block + count - 1;
+ /* Update the last accessed block on the correct pd */
+ lbInfo->last_accessed_block[bestArm] = block + count - 1;
- return bestArm;
+ return bestArm;
}
-/**
- * mrsas_get_updated_dev_handle Get the update dev handle
- * Inputs: Load balance info
- * io_info pointer
+/*
+ * mrsas_get_updated_dev_handle: Get the update dev handle
+ * Inputs: Load balance info io_info pointer
*
* This function determines and returns the updated dev handle.
*/
-u_int16_t mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo,
- struct IO_REQUEST_INFO *io_info)
+u_int16_t
+mrsas_get_updated_dev_handle(PLD_LOAD_BALANCE_INFO lbInfo,
+ struct IO_REQUEST_INFO *io_info)
{
- u_int8_t arm, old_arm;
- u_int16_t devHandle;
+ u_int8_t arm, old_arm;
+ u_int16_t devHandle;
- old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1;
+ old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1;
- /* get best new arm */
- arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks);
- devHandle = lbInfo->raid1DevHandle[arm];
- atomic_inc(&lbInfo->scsi_pending_cmds[arm]);
+ /* get best new arm */
+ arm = mrsas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, io_info->numBlocks);
+ devHandle = lbInfo->raid1DevHandle[arm];
+ atomic_inc(&lbInfo->scsi_pending_cmds[arm]);
- return devHandle;
+ return devHandle;
}
-/**
- * MR_GetPhyParams Calculates arm, span, and block
- * Inputs: Adapter instance soft state
- * Logical drive number (LD)
- * Stripe number (stripRow)
- * Reference in stripe (stripRef)
- * Outputs: Span number
- * Absolute Block number in the physical disk
+/*
+ * MR_GetPhyParams: Calculates arm, span, and block
+ * Inputs: Adapter soft state
+ * Logical drive number (LD)
+ * Stripe number(stripRow)
+ * Reference in stripe (stripRef)
*
- * This routine calculates the arm, span and block for the specified stripe
- * and reference in stripe.
+ * Outputs: Absolute Block number in the physical disk
+ *
+ * This routine calculates the arm, span and block for the specified stripe and
+ * reference in stripe.
*/
-u_int8_t MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld,
- u_int64_t stripRow,
- u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
- RAID_CONTEXT *pRAID_Context, MR_FW_RAID_MAP_ALL *map)
+u_int8_t
+MR_GetPhyParams(struct mrsas_softc *sc, u_int32_t ld,
+ u_int64_t stripRow,
+ u_int16_t stripRef, struct IO_REQUEST_INFO *io_info,
+ RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map)
{
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- u_int32_t pd, arRef;
- u_int8_t physArm, span;
- u_int64_t row;
- u_int8_t retval = TRUE;
- int error_code = 0;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ u_int32_t pd, arRef;
+ u_int8_t physArm, span;
+ u_int64_t row;
+ u_int8_t retval = TRUE;
+ int error_code = 0;
u_int64_t *pdBlock = &io_info->pdBlock;
- u_int16_t *pDevHandle = &io_info->devHandle;
- u_int32_t rowMod, armQ, arm, logArm;
+ u_int16_t *pDevHandle = &io_info->devHandle;
+ u_int32_t rowMod, armQ, arm, logArm;
u_int8_t do_invader = 0;
if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
do_invader = 1;
- row = mega_div64_32(stripRow, raid->rowDataSize);
-
- if (raid->level == 6) {
- logArm = mega_mod64(stripRow, raid->rowDataSize); // logical arm within row
- if (raid->rowSize == 0)
- return FALSE;
- rowMod = mega_mod64(row, raid->rowSize); // get logical row mod
- armQ = raid->rowSize-1-rowMod; // index of Q drive
- arm = armQ+1+logArm; // data always logically follows Q
- if (arm >= raid->rowSize) // handle wrap condition
- arm -= raid->rowSize;
- physArm = (u_int8_t)arm;
- }
- else {
- if (raid->modFactor == 0)
- return FALSE;
- physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map);
- }
-
- if (raid->spanDepth == 1) {
- span = 0;
- *pdBlock = row << raid->stripeShift;
- }
- else {
- span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code);
- if (error_code == 1)
- return FALSE;
- }
-
- /* Get the array on which this span is present */
- arRef = MR_LdSpanArrayGet(ld, span, map);
-
- pd = MR_ArPdGet(arRef, physArm, map); // Get the Pd.
-
- if (pd != MR_PD_INVALID)
- *pDevHandle = MR_PdDevHandleGet(pd, map); // Get dev handle from Pd.
- else {
- *pDevHandle = MR_PD_INVALID; // set dev handle as invalid.
- if ((raid->level >= 5) && ((!do_invader) || (do_invader &&
- raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
- pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
- else if (raid->level == 1) {
- pd = MR_ArPdGet(arRef, physArm + 1, map); // Get Alternate Pd.
- if (pd != MR_PD_INVALID)
- *pDevHandle = MR_PdDevHandleGet(pd, map);//Get dev handle from Pd.
- }
- }
-
- *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
- pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
- return retval;
+ row = mega_div64_32(stripRow, raid->rowDataSize);
+
+ if (raid->level == 6) {
+ /* logical arm within row */
+ logArm = mega_mod64(stripRow, raid->rowDataSize);
+ if (raid->rowSize == 0)
+ return FALSE;
+ rowMod = mega_mod64(row, raid->rowSize); /* get logical row mod */
+ armQ = raid->rowSize - 1 - rowMod; /* index of Q drive */
+ arm = armQ + 1 + logArm;/* data always logically follows Q */
+ if (arm >= raid->rowSize) /* handle wrap condition */
+ arm -= raid->rowSize;
+ physArm = (u_int8_t)arm;
+ } else {
+ if (raid->modFactor == 0)
+ return FALSE;
+ physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, raid->modFactor), map);
+ }
+
+ if (raid->spanDepth == 1) {
+ span = 0;
+ *pdBlock = row << raid->stripeShift;
+ } else {
+ span = (u_int8_t)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code);
+ if (error_code == 1)
+ return FALSE;
+ }
+
+ /* Get the array on which this span is present */
+ arRef = MR_LdSpanArrayGet(ld, span, map);
+
+ pd = MR_ArPdGet(arRef, physArm, map); /* Get the Pd. */
+
+ if (pd != MR_PD_INVALID)
+ /* Get dev handle from Pd */
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ else {
+ *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
+ if ((raid->level >= 5) && ((!do_invader) || (do_invader &&
+ raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
+ pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
+ else if (raid->level == 1) {
+ /* Get Alternate Pd. */
+ pd = MR_ArPdGet(arRef, physArm + 1, map);
+ if (pd != MR_PD_INVALID)
+ /* Get dev handle from Pd. */
+ *pDevHandle = MR_PdDevHandleGet(pd, map);
+ }
+ }
+
+ *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;
+ pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
+ return retval;
}
-/**
- * MR_GetSpanBlock Calculates span block
- * Inputs: LD
- * row
- * PD span block
- * RAID map pointer
- * Outputs: Span number
- * Error code
+/*
+ * MR_GetSpanBlock: Calculates span block
+ * Inputs: LD
+ * row PD
+ * span block
+ * RAID map pointer
*
- * This routine calculates the span from the span block info.
+ * Outputs: Span number Error code
+ *
+ * This routine calculates the span from the span block info.
*/
-u_int32_t MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk,
- MR_FW_RAID_MAP_ALL *map, int *div_error)
+u_int32_t
+MR_GetSpanBlock(u_int32_t ld, u_int64_t row, u_int64_t *span_blk,
+ MR_DRV_RAID_MAP_ALL * map, int *div_error)
{
- MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
- MR_QUAD_ELEMENT *quad;
- MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
- u_int32_t span, j;
- u_int64_t blk, debugBlk;
-
- for (span=0; span < raid->spanDepth; span++, pSpanBlock++) {
- for (j=0; j < pSpanBlock->block_span_info.noElements; j++) {
- quad = &pSpanBlock->block_span_info.quad[j];
- if (quad->diff == 0) {
- *div_error = 1;
- return span;
- }
- if (quad->logStart <= row && row <= quad->logEnd &&
- (mega_mod64(row-quad->logStart, quad->diff)) == 0) {
- if (span_blk != NULL) {
- blk = mega_div64_32((row-quad->logStart), quad->diff);
- debugBlk = blk;
- blk = (blk + quad->offsetInSpan) << raid->stripeShift;
- *span_blk = blk;
- }
- return span;
- }
- }
- }
- return span;
+ MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
+ MR_QUAD_ELEMENT *quad;
+ MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
+ u_int32_t span, j;
+ u_int64_t blk, debugBlk;
+
+ for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) {
+ for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) {
+ quad = &pSpanBlock->block_span_info.quad[j];
+ if (quad->diff == 0) {
+ *div_error = 1;
+ return span;
+ }
+ if (quad->logStart <= row && row <= quad->logEnd &&
+ (mega_mod64(row - quad->logStart, quad->diff)) == 0) {
+ if (span_blk != NULL) {
+ blk = mega_div64_32((row - quad->logStart), quad->diff);
+ debugBlk = blk;
+ blk = (blk + quad->offsetInSpan) << raid->stripeShift;
+ *span_blk = blk;
+ }
+ return span;
+ }
+ }
+ }
+ return span;
}
-
diff --git a/sys/dev/mrsas/mrsas_ioctl.c b/sys/dev/mrsas/mrsas_ioctl.c
index 6343aa5..8e2aead 100644
--- a/sys/dev/mrsas/mrsas_ioctl.c
+++ b/sys/dev/mrsas/mrsas_ioctl.c
@@ -1,43 +1,38 @@
/*
- * Copyright (c) 2014, LSI Corp.
- * All rights reserved.
- * Author: Marian Choy
+ * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
* Support: freebsdraid@lsi.com
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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 <ORGANIZATION> nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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
+ * <ORGANIZATION> 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 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 HOLDER 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
+ * 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 HOLDER 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.
*
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing
* official policies,either expressed or implied, of the FreeBSD Project.
*
- * Send feedback to: <megaraidfbsd@lsi.com>
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: MegaRaid FreeBSD
+ * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621
+ * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
*
*/
@@ -47,500 +42,464 @@ __FBSDID("$FreeBSD$");
#include <dev/mrsas/mrsas.h>
#include <dev/mrsas/mrsas_ioctl.h>
-/*
- * Function prototypes
+/*
+ * Function prototypes
*/
-int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
-int mrsas_passthru(struct mrsas_softc *sc, void *arg);
-void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
-void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
-void mrsas_dump_dcmd(struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd);
-void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc);
-void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
+int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
+int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
+void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
+void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
+void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
static int mrsas_create_frame_pool(struct mrsas_softc *sc);
-static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
- int nsegs, int error);
+static void
+mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
+ int nsegs, int error);
-extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc);
+extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc);
extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
-extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
+extern int
+mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
struct mrsas_mfi_cmd *cmd);
-
-/**
- * mrsas_dump_ioctl: Print debug output for DCMDs
- * input: Adapter instance soft state
- * DCMD frame structure
- *
- * This function is called from mrsas_passthru() to print out debug information
- * in the handling and routing of DCMD commands.
- */
-void mrsas_dump_dcmd( struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd )
-{
- int i;
-
- device_printf(sc->mrsas_dev, "dcmd->cmd: 0x%02hhx\n", dcmd->cmd);
- device_printf(sc->mrsas_dev, "dcmd->cmd_status: 0x%02hhx\n", dcmd->cmd_status);
- device_printf(sc->mrsas_dev, "dcmd->sge_count: 0x%02hhx\n", dcmd->sge_count);
- device_printf(sc->mrsas_dev, "dcmd->context: 0x%08x\n", dcmd->context);
- device_printf(sc->mrsas_dev, "dcmd->flags: 0x%04hx\n", dcmd->flags);
- device_printf(sc->mrsas_dev, "dcmd->timeout: 0x%04hx\n", dcmd->timeout);
- device_printf(sc->mrsas_dev, "dcmd->data_xfer_len: 0x%08x\n", dcmd->data_xfer_len);
- device_printf(sc->mrsas_dev, "dcmd->opcode: 0x%08x\n", dcmd->opcode);
- device_printf(sc->mrsas_dev, "dcmd->mbox.w[0]: 0x%08x\n", dcmd->mbox.w[0]);
- device_printf(sc->mrsas_dev, "dcmd->mbox.w[1]: 0x%08x\n", dcmd->mbox.w[1]);
- device_printf(sc->mrsas_dev, "dcmd->mbox.w[2]: 0x%08x\n", dcmd->mbox.w[2]);
- for (i=0; i< MIN(MAX_IOCTL_SGE, dcmd->sge_count); i++) {
- device_printf(sc->mrsas_dev, "sgl[%02d]\n", i);
- device_printf(sc->mrsas_dev, " sge32[%02d].phys_addr: 0x%08x\n",
- i, dcmd->sgl.sge32[i].phys_addr);
- device_printf(sc->mrsas_dev, " sge32[%02d].length: 0x%08x\n",
- i, dcmd->sgl.sge32[i].length);
- device_printf(sc->mrsas_dev, " sge64[%02d].phys_addr: 0x%08llx\n",
- i, (long long unsigned int) dcmd->sgl.sge64[i].phys_addr);
- device_printf(sc->mrsas_dev, " sge64[%02d].length: 0x%08x\n",
- i, dcmd->sgl.sge64[i].length);
- }
-}
-
-/**
- * mrsas_dump_ioctl: Print debug output for ioctl
- * input: Adapter instance soft state
- * iocpacket structure
- *
- * This function is called from mrsas_passthru() to print out debug information
- * in the handling and routing of ioctl commands.
- */
-void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc)
-{
- union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
- struct mrsas_dcmd_frame* dcmd = (struct mrsas_dcmd_frame *) &(in_cmd->dcmd);
- int i;
-
- device_printf(sc->mrsas_dev,
- "====== In %s() ======================================\n", __func__);
- device_printf(sc->mrsas_dev, "host_no: 0x%04hx\n", user_ioc->host_no);
- device_printf(sc->mrsas_dev, " __pad1: 0x%04hx\n", user_ioc->__pad1);
- device_printf(sc->mrsas_dev, "sgl_off: 0x%08x\n", user_ioc->sgl_off);
- device_printf(sc->mrsas_dev, "sge_count: 0x%08x\n", user_ioc->sge_count);
- device_printf(sc->mrsas_dev, "sense_off: 0x%08x\n", user_ioc->sense_off);
- device_printf(sc->mrsas_dev, "sense_len: 0x%08x\n", user_ioc->sense_len);
-
- mrsas_dump_dcmd(sc, dcmd);
-
- for (i=0; i< MIN(MAX_IOCTL_SGE, user_ioc->sge_count); i++) {
- device_printf(sc->mrsas_dev, "sge[%02d]\n", i);
- device_printf(sc->mrsas_dev,
- " iov_base: %p\n", user_ioc->sgl[i].iov_base);
- device_printf(sc->mrsas_dev, " iov_len: %p\n",
- (void*)user_ioc->sgl[i].iov_len);
- }
- device_printf(sc->mrsas_dev,
- "==================================================================\n");
-}
-
-/**
- * mrsas_passthru: Handle pass-through commands
- * input: Adapter instance soft state
- * argument pointer
+/*
+ * mrsas_passthru: Handle pass-through commands
+ * input: Adapter instance soft state argument pointer
*
- * This function is called from mrsas_ioctl() to handle pass-through and
- * ioctl commands to Firmware.
+ * This function is called from mrsas_ioctl() to handle pass-through and ioctl
+ * commands to Firmware.
*/
-int mrsas_passthru( struct mrsas_softc *sc, void *arg )
+int
+mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd)
{
- struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
- union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
- struct mrsas_mfi_cmd *cmd = NULL;
- bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
- bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
- void *ioctl_data_mem[MAX_IOCTL_SGE]; // ioctl data virtual addr
- bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; // ioctl data phys addr
- bus_dma_tag_t ioctl_sense_tag = 0;
- bus_dmamap_t ioctl_sense_dmamap = 0;
- void *ioctl_sense_mem = 0;
- bus_addr_t ioctl_sense_phys_addr = 0;
- int i, adapter, ioctl_data_size, ioctl_sense_size, ret=0;
- struct mrsas_sge32 *kern_sge32;
- unsigned long *sense_ptr;
-
- /* For debug - uncomment the following line for debug output */
- //mrsas_dump_ioctl(sc, user_ioc);
-
- /*
- * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In this
- * case do nothing and return 0 to it as status.
- */
- if (in_cmd->dcmd.opcode == 0) {
- device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
- user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
- return (0);
- }
-
- /* Validate host_no */
- adapter = user_ioc->host_no;
- if (adapter != device_get_unit(sc->mrsas_dev)) {
- device_printf(sc->mrsas_dev, "In %s() IOCTL not for me!\n", __func__);
- return(ENOENT);
- }
-
- /* Validate SGL length */
- if (user_ioc->sge_count > MAX_IOCTL_SGE) {
- device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
- __func__, user_ioc->sge_count);
- return(ENOENT);
- }
-
- /* Get a command */
- cmd = mrsas_get_mfi_cmd(sc);
- if (!cmd) {
- device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
- return(ENOMEM);
- }
-
- /*
- * User's IOCTL packet has 2 frames (maximum). Copy those two
- * frames into our cmd's frames. cmd->frame's context will get
- * overwritten when we copy from user's frames. So set that value
- * alone separately
- */
- memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
- cmd->frame->hdr.context = cmd->index;
- cmd->frame->hdr.pad_0 = 0;
- cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
- MFI_FRAME_SENSE64);
-
- /*
- * The management interface between applications and the fw uses
- * MFI frames. E.g, RAID configuration changes, LD property changes
- * etc are accomplishes through different kinds of MFI frames. The
- * driver needs to care only about substituting user buffers with
- * kernel buffers in SGLs. The location of SGL is embedded in the
- * struct iocpacket itself.
- */
- kern_sge32 = (struct mrsas_sge32 *)
- ((unsigned long)cmd->frame + user_ioc->sgl_off);
-
- /*
- * For each user buffer, create a mirror buffer and copy in
- */
- for (i=0; i < user_ioc->sge_count; i++) {
- if (!user_ioc->sgl[i].iov_len)
- continue;
- ioctl_data_size = user_ioc->sgl[i].iov_len;
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- ioctl_data_size, // maxsize
- 1, // msegments
- ioctl_data_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &ioctl_data_tag[i])) {
- device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
- (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
- device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
- ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
- &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
- return (ENOMEM);
- }
-
- /* Save the physical address and length */
- kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
- kern_sge32[i].length = user_ioc->sgl[i].iov_len;
-
- /* Copy in data from user space */
- ret = copyin(user_ioc->sgl[i].iov_base, ioctl_data_mem[i],
- user_ioc->sgl[i].iov_len);
- if (ret) {
- device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
- goto out;
- }
- }
-
- ioctl_sense_size = user_ioc->sense_len;
- if (user_ioc->sense_len) {
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- ioctl_sense_size, // maxsize
- 1, // msegments
- ioctl_sense_size, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &ioctl_sense_tag)) {
- device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
- return (ENOMEM);
- }
- if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
- (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
- return (ENOMEM);
- }
- if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
- ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
- &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
- return (ENOMEM);
- }
- sense_ptr =
- (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
- sense_ptr = ioctl_sense_mem;
- }
-
- /*
- * Set the sync_cmd flag so that the ISR knows not to complete this
- * cmd to the SCSI mid-layer
- */
- cmd->sync_cmd = 1;
- mrsas_issue_blocked_cmd(sc, cmd);
- cmd->sync_cmd = 0;
-
- /*
- * copy out the kernel buffers to user buffers
- */
- for (i = 0; i < user_ioc->sge_count; i++) {
- ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base,
- user_ioc->sgl[i].iov_len);
- if (ret) {
- device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
- goto out;
- }
- }
-
- /*
- * copy out the sense
- */
- if (user_ioc->sense_len) {
- /*
- * sense_buff points to the location that has the user
- * sense buffer address
- */
- sense_ptr = (unsigned long *) ((unsigned long)user_ioc->frame.raw +
- user_ioc->sense_off);
- ret = copyout(ioctl_sense_mem, (unsigned long*)*sense_ptr,
- user_ioc->sense_len);
- if (ret) {
- device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
- goto out;
- }
- }
-
- /*
- * Return command status to user space
- */
- memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
- sizeof(u_int8_t));
+ struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
+
+#ifdef COMPAT_FREEBSD32
+ struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg;
+
+#endif
+ union mrsas_frame *in_cmd = (union mrsas_frame *)&(user_ioc->frame.raw);
+ struct mrsas_mfi_cmd *cmd = NULL;
+ bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
+ bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
+ void *ioctl_data_mem[MAX_IOCTL_SGE];
+ bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE];
+ bus_dma_tag_t ioctl_sense_tag = 0;
+ bus_dmamap_t ioctl_sense_dmamap = 0;
+ void *ioctl_sense_mem = 0;
+ bus_addr_t ioctl_sense_phys_addr = 0;
+ int i, ioctl_data_size = 0, ioctl_sense_size, ret = 0;
+ struct mrsas_sge32 *kern_sge32;
+ unsigned long *sense_ptr;
+ uint8_t *iov_base_ptrin = NULL;
+ size_t iov_len = 0;
+
+ /*
+ * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In
+ * this case do nothing and return 0 to it as status.
+ */
+ if (in_cmd->dcmd.opcode == 0) {
+ device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
+ user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
+ return (0);
+ }
+ /* Validate SGL length */
+ if (user_ioc->sge_count > MAX_IOCTL_SGE) {
+ device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
+ __func__, user_ioc->sge_count);
+ return (ENOENT);
+ }
+ /* Get a command */
+ cmd = mrsas_get_mfi_cmd(sc);
+ if (!cmd) {
+ device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
+ return (ENOMEM);
+ }
+ /*
+ * User's IOCTL packet has 2 frames (maximum). Copy those two frames
+ * into our cmd's frames. cmd->frame's context will get overwritten
+ * when we copy from user's frames. So set that value alone
+ * separately
+ */
+ memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
+ cmd->frame->hdr.context = cmd->index;
+ cmd->frame->hdr.pad_0 = 0;
+ cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
+ MFI_FRAME_SENSE64);
+
+ /*
+ * The management interface between applications and the fw uses MFI
+ * frames. E.g, RAID configuration changes, LD property changes etc
+ * are accomplishes through different kinds of MFI frames. The driver
+ * needs to care only about substituting user buffers with kernel
+ * buffers in SGLs. The location of SGL is embedded in the struct
+ * iocpacket itself.
+ */
+ kern_sge32 = (struct mrsas_sge32 *)
+ ((unsigned long)cmd->frame + user_ioc->sgl_off);
+
+ /*
+ * For each user buffer, create a mirror buffer and copy in
+ */
+ for (i = 0; i < user_ioc->sge_count; i++) {
+ if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
+ if (!user_ioc->sgl[i].iov_len)
+ continue;
+ ioctl_data_size = user_ioc->sgl[i].iov_len;
+#ifdef COMPAT_FREEBSD32
+ } else {
+ if (!user_ioc32->sgl[i].iov_len)
+ continue;
+ ioctl_data_size = user_ioc32->sgl[i].iov_len;
+#endif
+ }
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ ioctl_data_size,
+ 1,
+ ioctl_data_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &ioctl_data_tag[i])) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
+ ret = ENOMEM;
+ goto out;
+ }
+ if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
+ (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
+ ret = ENOMEM;
+ goto out;
+ }
+ if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
+ ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
+ &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
+ ret = ENOMEM;
+ goto out;
+ }
+ /* Save the physical address and length */
+ kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
+
+ if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
+ kern_sge32[i].length = user_ioc->sgl[i].iov_len;
+
+ iov_base_ptrin = user_ioc->sgl[i].iov_base;
+ iov_len = user_ioc->sgl[i].iov_len;
+#ifdef COMPAT_FREEBSD32
+ } else {
+ kern_sge32[i].length = user_ioc32->sgl[i].iov_len;
+
+ iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
+ iov_len = user_ioc32->sgl[i].iov_len;
+#endif
+ }
+
+ /* Copy in data from user space */
+ ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len);
+ if (ret) {
+ device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
+ goto out;
+ }
+ }
+
+ ioctl_sense_size = user_ioc->sense_len;
+
+ if (user_ioc->sense_len) {
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ ioctl_sense_size,
+ 1,
+ ioctl_sense_size,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &ioctl_sense_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
+ ret = ENOMEM;
+ goto out;
+ }
+ if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
+ (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense mem\n");
+ ret = ENOMEM;
+ goto out;
+ }
+ if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
+ ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
+ &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
+ ret = ENOMEM;
+ goto out;
+ }
+ sense_ptr =
+ (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
+ sense_ptr = ioctl_sense_mem;
+ }
+ /*
+ * Set the sync_cmd flag so that the ISR knows not to complete this
+ * cmd to the SCSI mid-layer
+ */
+ cmd->sync_cmd = 1;
+ mrsas_issue_blocked_cmd(sc, cmd);
+ cmd->sync_cmd = 0;
+
+ /*
+ * copy out the kernel buffers to user buffers
+ */
+ for (i = 0; i < user_ioc->sge_count; i++) {
+ if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
+ iov_base_ptrin = user_ioc->sgl[i].iov_base;
+ iov_len = user_ioc->sgl[i].iov_len;
+#ifdef COMPAT_FREEBSD32
+ } else {
+ iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
+ iov_len = user_ioc32->sgl[i].iov_len;
+#endif
+ }
+
+ ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len);
+ if (ret) {
+ device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
+ goto out;
+ }
+ }
+
+ /*
+ * copy out the sense
+ */
+ if (user_ioc->sense_len) {
+ /*
+ * sense_buff points to the location that has the user sense
+ * buffer address
+ */
+ sense_ptr = (unsigned long *)((unsigned long)user_ioc->frame.raw +
+ user_ioc->sense_off);
+ ret = copyout(ioctl_sense_mem, (unsigned long *)*sense_ptr,
+ user_ioc->sense_len);
+ if (ret) {
+ device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
+ goto out;
+ }
+ }
+ /*
+ * Return command status to user space
+ */
+ memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
+ sizeof(u_int8_t));
out:
- /*
- * Release sense buffer
- */
- if (ioctl_sense_phys_addr)
- bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
- if (ioctl_sense_mem)
- bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
- if (ioctl_sense_tag)
- bus_dma_tag_destroy(ioctl_sense_tag);
-
- /*
- * Release data buffers
- */
- for (i = 0; i < user_ioc->sge_count; i++) {
- if (!user_ioc->sgl[i].iov_len)
- continue;
- if (ioctl_data_phys_addr[i])
- bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
- if (ioctl_data_mem[i] != NULL)
- bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
- ioctl_data_dmamap[i]);
- if (ioctl_data_tag[i] != NULL)
- bus_dma_tag_destroy(ioctl_data_tag[i]);
- }
-
- /* Free command */
- mrsas_release_mfi_cmd(cmd);
-
- return(ret);
+ /*
+ * Release sense buffer
+ */
+ if (ioctl_sense_phys_addr)
+ bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
+ if (ioctl_sense_mem != NULL)
+ bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
+ if (ioctl_sense_tag != NULL)
+ bus_dma_tag_destroy(ioctl_sense_tag);
+
+ /*
+ * Release data buffers
+ */
+ for (i = 0; i < user_ioc->sge_count; i++) {
+ if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
+ if (!user_ioc->sgl[i].iov_len)
+ continue;
+#ifdef COMPAT_FREEBSD32
+ } else {
+ if (!user_ioc32->sgl[i].iov_len)
+ continue;
+#endif
+ }
+ if (ioctl_data_phys_addr[i])
+ bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
+ if (ioctl_data_mem[i] != NULL)
+ bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
+ ioctl_data_dmamap[i]);
+ if (ioctl_data_tag[i] != NULL)
+ bus_dma_tag_destroy(ioctl_data_tag[i]);
+ }
+ /* Free command */
+ mrsas_release_mfi_cmd(cmd);
+
+ return (ret);
}
-/**
- * mrsas_alloc_mfi_cmds: Allocates the command packets
- * input: Adapter instance soft state
+/*
+ * mrsas_alloc_mfi_cmds: Allocates the command packets
+ * input: Adapter instance soft state
*
* Each IOCTL or passthru command that is issued to the FW are wrapped in a
- * local data structure called mrsas_mfi_cmd. The frame embedded in this
- * mrsas_mfi is issued to FW. The array is used only to look up the
+ * local data structure called mrsas_mfi_cmd. The frame embedded in this
+ * mrsas_mfi is issued to FW. The array is used only to look up the
* mrsas_mfi_cmd given the context. The free commands are maintained in a
* linked list.
*/
-int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
+int
+mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
{
- int i, j;
- u_int32_t max_cmd;
- struct mrsas_mfi_cmd *cmd;
-
- max_cmd = MRSAS_MAX_MFI_CMDS;
-
- /*
- * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. Allocate the
- * dynamic array first and then allocate individual commands.
- */
- sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd*)*max_cmd, M_MRSAS, M_NOWAIT);
- if (!sc->mfi_cmd_list) {
- device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
- return(ENOMEM);
- }
- memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *)*max_cmd);
- for (i = 0; i < max_cmd; i++) {
- sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd),
- M_MRSAS, M_NOWAIT);
- if (!sc->mfi_cmd_list[i]) {
- for (j = 0; j < i; j++)
- free(sc->mfi_cmd_list[j],M_MRSAS);
- free(sc->mfi_cmd_list, M_MRSAS);
- sc->mfi_cmd_list = NULL;
- return(ENOMEM);
- }
- }
-
- for (i = 0; i < max_cmd; i++) {
- cmd = sc->mfi_cmd_list[i];
- memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
- cmd->index = i;
- cmd->ccb_ptr = NULL;
- cmd->sc = sc;
- TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
- }
-
- /* create a frame pool and assign one frame to each command */
- if (mrsas_create_frame_pool(sc)) {
- device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
- for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { // Free the frames
- cmd = sc->mfi_cmd_list[i];
- mrsas_free_frame(sc, cmd);
- }
- if (sc->mficmd_frame_tag != NULL)
- bus_dma_tag_destroy(sc->mficmd_frame_tag);
- return(ENOMEM);
- }
-
- return(0);
+ int i, j;
+ u_int32_t max_cmd;
+ struct mrsas_mfi_cmd *cmd;
+
+ max_cmd = MRSAS_MAX_MFI_CMDS;
+
+ /*
+ * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers.
+ * Allocate the dynamic array first and then allocate individual
+ * commands.
+ */
+ sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd *) * max_cmd, M_MRSAS, M_NOWAIT);
+ if (!sc->mfi_cmd_list) {
+ device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
+ return (ENOMEM);
+ }
+ memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *) * max_cmd);
+ for (i = 0; i < max_cmd; i++) {
+ sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd),
+ M_MRSAS, M_NOWAIT);
+ if (!sc->mfi_cmd_list[i]) {
+ for (j = 0; j < i; j++)
+ free(sc->mfi_cmd_list[j], M_MRSAS);
+ free(sc->mfi_cmd_list, M_MRSAS);
+ sc->mfi_cmd_list = NULL;
+ return (ENOMEM);
+ }
+ }
+
+ for (i = 0; i < max_cmd; i++) {
+ cmd = sc->mfi_cmd_list[i];
+ memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
+ cmd->index = i;
+ cmd->ccb_ptr = NULL;
+ cmd->sc = sc;
+ TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
+ }
+
+ /* create a frame pool and assign one frame to each command */
+ if (mrsas_create_frame_pool(sc)) {
+ device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
+ /* Free the frames */
+ for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
+ cmd = sc->mfi_cmd_list[i];
+ mrsas_free_frame(sc, cmd);
+ }
+ if (sc->mficmd_frame_tag != NULL)
+ bus_dma_tag_destroy(sc->mficmd_frame_tag);
+ return (ENOMEM);
+ }
+ return (0);
}
-/**
- * mrsas_create_frame_pool - Creates DMA pool for cmd frames
- * input: Adapter soft state
+/*
+ * mrsas_create_frame_pool: Creates DMA pool for cmd frames
+ * input: Adapter soft state
*
* Each command packet has an embedded DMA memory buffer that is used for
* filling MFI frame and the SG list that immediately follows the frame. This
* function creates those DMA memory buffers for each command packet by using
- * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
+ * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
* of context and could cause FW crash.
*/
-static int mrsas_create_frame_pool(struct mrsas_softc *sc)
+static int
+mrsas_create_frame_pool(struct mrsas_softc *sc)
{
- int i;
- struct mrsas_mfi_cmd *cmd;
-
- if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
- 1, 0, // algnmnt, boundary
- BUS_SPACE_MAXADDR_32BIT,// lowaddr
- BUS_SPACE_MAXADDR, // highaddr
- NULL, NULL, // filter, filterarg
- MRSAS_MFI_FRAME_SIZE, // maxsize
- 1, // msegments
- MRSAS_MFI_FRAME_SIZE, // maxsegsize
- BUS_DMA_ALLOCNOW, // flags
- NULL, NULL, // lockfunc, lockarg
- &sc->mficmd_frame_tag)) {
- device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
- return (ENOMEM);
- }
-
- for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
- cmd = sc->mfi_cmd_list[i];
- cmd->frame = mrsas_alloc_frame(sc, cmd);
- if (cmd->frame == NULL) {
- device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
- return (ENOMEM);
- }
- memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
- cmd->frame->io.context = cmd->index;
- cmd->frame->io.pad_0 = 0;
- }
-
- return(0);
+ int i;
+ struct mrsas_mfi_cmd *cmd;
+
+ if (bus_dma_tag_create(sc->mrsas_parent_tag,
+ 1, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ MRSAS_MFI_FRAME_SIZE,
+ 1,
+ MRSAS_MFI_FRAME_SIZE,
+ BUS_DMA_ALLOCNOW,
+ NULL, NULL,
+ &sc->mficmd_frame_tag)) {
+ device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
+ return (ENOMEM);
+ }
+ for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
+ cmd = sc->mfi_cmd_list[i];
+ cmd->frame = mrsas_alloc_frame(sc, cmd);
+ if (cmd->frame == NULL) {
+ device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
+ return (ENOMEM);
+ }
+ memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
+ cmd->frame->io.context = cmd->index;
+ cmd->frame->io.pad_0 = 0;
+ }
+
+ return (0);
}
-/**
- * mrsas_alloc_frame - Allocates MFI Frames
- * input: Adapter soft state
+/*
+ * mrsas_alloc_frame: Allocates MFI Frames
+ * input: Adapter soft state
*
- * Create bus DMA memory tag and dmamap and load memory for MFI frames.
- * Returns virtual memory pointer to allocated region.
+ * Create bus DMA memory tag and dmamap and load memory for MFI frames. Returns
+ * virtual memory pointer to allocated region.
*/
-void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
+void *
+mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
- u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
-
- if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
- BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
- device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
- return (NULL);
- }
- if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
- cmd->frame_mem, frame_size, mrsas_alloc_cb,
- &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
- device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
- return (NULL);
- }
-
- return(cmd->frame_mem);
+ u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
+
+ if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
+ BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
+ device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
+ return (NULL);
+ }
+ if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
+ cmd->frame_mem, frame_size, mrsas_alloc_cb,
+ &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
+ device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
+ return (NULL);
+ }
+ return (cmd->frame_mem);
}
/*
- * mrsas_alloc_cb: Callback function of bus_dmamap_load()
- * input: callback argument,
- * machine dependent type that describes DMA segments,
- * number of segments,
- * error code.
+ * mrsas_alloc_cb: Callback function of bus_dmamap_load()
+ * input: callback argument,
+ * machine dependent type that describes DMA segments,
+ * number of segments,
+ * error code.
*
- * This function is for the driver to receive mapping information resultant
- * of the bus_dmamap_load(). The information is actually not being used,
- * but the address is saved anyway.
+ * This function is for the driver to receive mapping information resultant of
+ * the bus_dmamap_load(). The information is actually not being used, but the
+ * address is saved anyway.
*/
-static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
- int nsegs, int error)
+static void
+mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
+ int nsegs, int error)
{
- bus_addr_t *addr;
+ bus_addr_t *addr;
- addr = arg;
- *addr = segs[0].ds_addr;
+ addr = arg;
+ *addr = segs[0].ds_addr;
}
-/**
- * mrsas_free_frames: Frees memory for MFI frames
- * input: Adapter soft state
+/*
+ * mrsas_free_frames: Frees memory for MFI frames
+ * input: Adapter soft state
*
- * Deallocates MFI frames memory. Called from mrsas_free_mem() during
- * detach and error case during creation of frame pool.
+ * Deallocates MFI frames memory. Called from mrsas_free_mem() during detach
+ * and error case during creation of frame pool.
*/
-void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
+void
+mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
{
- if (cmd->frame_phys_addr)
- bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
- if (cmd->frame_mem != NULL)
- bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);
+ if (cmd->frame_phys_addr)
+ bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
+ if (cmd->frame_mem != NULL)
+ bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);
}
diff --git a/sys/dev/mrsas/mrsas_ioctl.h b/sys/dev/mrsas/mrsas_ioctl.h
index 3604842..bf05a7d 100644
--- a/sys/dev/mrsas/mrsas_ioctl.h
+++ b/sys/dev/mrsas/mrsas_ioctl.h
@@ -1,43 +1,38 @@
/*
- * Copyright (c) 2014, LSI Corp.
- * All rights reserved.
- * Author: Marian Choy
+ * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
* Support: freebsdraid@lsi.com
*
* Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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 <ORGANIZATION> nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
+ * 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
+ * <ORGANIZATION> 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 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 HOLDER 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
+ * 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 HOLDER 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.
*
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing
* official policies,either expressed or implied, of the FreeBSD Project.
*
- * Send feedback to: <megaraidfbsd@lsi.com>
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: MegaRaid FreeBSD
+ * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621
+ * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
*
*/
@@ -45,53 +40,87 @@
__FBSDID("$FreeBSD$");
#ifndef MRSAS_IOCTL_H
-#define MRSAS_IOCTL_H
+#define MRSAS_IOCTL_H
#ifndef _IOWR
#include <sys/ioccom.h>
-#endif /* !_IOWR */
+#endif /* !_IOWR */
+
+#ifdef COMPAT_FREEBSD32
+/* Compilation error FIX */
+#if (__FreeBSD_version <= 900000)
+#include <sys/socket.h>
+#endif
+#include <sys/mount.h>
+#include <compat/freebsd32/freebsd32.h>
+#endif
/*
- * We need to use the same values as the mfi driver until MegaCli adds
- * support for this (mrsas) driver:
- * M is for MegaRAID. (This is typically the vendor or product initial)
- * 1 arbitrary. (This may be used to segment kinds of commands.
- * (1-9 status, 10-20 policy, etc.)
- * struct mrsas_iocpacket (sizeof() this parameter will be used.)
- * These three values are encoded into a somewhat unique, 32-bit value.
+ * We need to use the same values as the mfi driver until MegaCli adds
+ * support for this (mrsas) driver: M is for MegaRAID. (This is typically the
+ * vendor or product initial) 1 arbitrary. (This may be used to segment kinds
+ * of commands. (1-9 status, 10-20 policy, etc.) struct mrsas_iocpacket
+ * (sizeof() this parameter will be used.) These three values are encoded
+ * into a somewhat unique, 32-bit value.
*/
-#define MRSAS_IOC_FIRMWARE_PASS_THROUGH _IOWR('M', 1, struct mrsas_iocpacket)
+#define MRSAS_IOC_FIRMWARE_PASS_THROUGH64 _IOWR('M', 1, struct mrsas_iocpacket)
+#ifdef COMPAT_FREEBSD32
+#define MRSAS_IOC_FIRMWARE_PASS_THROUGH32 _IOWR('M', 1, struct mrsas_iocpacket32)
+#endif
+
+#define MRSAS_IOC_SCAN_BUS _IO('M', 10)
-#define MRSAS_IOC_SCAN_BUS _IO('M', 10)
+#define MRSAS_LINUX_CMD32 0xc1144d01
-#define MAX_IOCTL_SGE 16
-#define MFI_FRAME_DIR_READ 0x0010
-#define MFI_CMD_LD_SCSI_IO 0x03
+#define MAX_IOCTL_SGE 16
+#define MFI_FRAME_DIR_READ 0x0010
+#define MFI_CMD_LD_SCSI_IO 0x03
-#define INQUIRY_CMD 0x12
-#define INQUIRY_CMDLEN 6
-#define INQUIRY_REPLY_LEN 96
-#define INQUIRY_VENDOR 8 /* Offset in reply data to vendor name */
-#define SCSI_SENSE_BUFFERSIZE 96
+#define INQUIRY_CMD 0x12
+#define INQUIRY_CMDLEN 6
+#define INQUIRY_REPLY_LEN 96
+#define INQUIRY_VENDOR 8 /* Offset in reply data to
+ * vendor name */
+#define SCSI_SENSE_BUFFERSIZE 96
-#define MEGAMFI_RAW_FRAME_SIZE 128
+#define MEGAMFI_RAW_FRAME_SIZE 128
#pragma pack(1)
struct mrsas_iocpacket {
- u_int16_t host_no;
- u_int16_t __pad1;
- u_int32_t sgl_off;
- u_int32_t sge_count;
- u_int32_t sense_off;
- u_int32_t sense_len;
- union {
- u_int8_t raw[MEGAMFI_RAW_FRAME_SIZE];
- struct mrsas_header hdr;
- } frame;
- struct iovec sgl[MAX_IOCTL_SGE];
+ u_int16_t host_no;
+ u_int16_t __pad1;
+ u_int32_t sgl_off;
+ u_int32_t sge_count;
+ u_int32_t sense_off;
+ u_int32_t sense_len;
+ union {
+ u_int8_t raw[MEGAMFI_RAW_FRAME_SIZE];
+ struct mrsas_header hdr;
+ } frame;
+ struct iovec sgl[MAX_IOCTL_SGE];
+};
+
+#pragma pack()
+
+#ifdef COMPAT_FREEBSD32
+#pragma pack(1)
+struct mrsas_iocpacket32 {
+ u_int16_t host_no;
+ u_int16_t __pad1;
+ u_int32_t sgl_off;
+ u_int32_t sge_count;
+ u_int32_t sense_off;
+ u_int32_t sense_len;
+ union {
+ u_int8_t raw[MEGAMFI_RAW_FRAME_SIZE];
+ struct mrsas_header hdr;
+ } frame;
+ struct iovec32 sgl[MAX_IOCTL_SGE];
};
+
#pragma pack()
+#endif /* COMPAT_FREEBSD32 */
-#endif /* MRSAS_IOCTL_H */
+#endif /* MRSAS_IOCTL_H */
diff --git a/sys/dev/mrsas/mrsas_linux.c b/sys/dev/mrsas/mrsas_linux.c
new file mode 100644
index 0000000..8a3db0b
--- /dev/null
+++ b/sys/dev/mrsas/mrsas_linux.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Kashyap Desai,
+ * Sibananda Sahu Support: freebsdraid@lsi.com
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions
+ * in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of the
+ * <ORGANIZATION> 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 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 HOLDER 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.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing
+ * official policies,either expressed or implied, of the FreeBSD Project.
+ *
+ * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621
+ * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#if (__FreeBSD_version > 900000)
+#include <sys/capability.h>
+#endif
+
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include <machine/bus.h>
+
+#if defined(__amd64__) /* Assume amd64 wants 32 bit Linux */
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_util.h>
+
+#include <dev/mrsas/mrsas.h>
+#include <dev/mrsas/mrsas_ioctl.h>
+
+/* There are multiple ioctl number ranges that need to be handled */
+#define MRSAS_LINUX_IOCTL_MIN 0x4d00
+#define MRSAS_LINUX_IOCTL_MAX 0x4d01
+
+static linux_ioctl_function_t mrsas_linux_ioctl;
+static struct linux_ioctl_handler mrsas_linux_handler = {mrsas_linux_ioctl,
+ MRSAS_LINUX_IOCTL_MIN,
+MRSAS_LINUX_IOCTL_MAX};
+
+SYSINIT(mrsas_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ linux_ioctl_register_handler, &mrsas_linux_handler);
+SYSUNINIT(mrsas_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ linux_ioctl_unregister_handler, &mrsas_linux_handler);
+
+static struct linux_device_handler mrsas_device_handler =
+{"mrsas", "megaraid_sas", "mrsas0", "megaraid_sas_ioctl_node", -1, 0, 1};
+
+SYSINIT(mrsas_register2, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ linux_device_register_handler, &mrsas_device_handler);
+SYSUNINIT(mrsas_unregister2, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ linux_device_unregister_handler, &mrsas_device_handler);
+
+static int
+mrsas_linux_modevent(module_t mod __unused, int cmd __unused, void *data __unused)
+{
+ return (0);
+}
+
+/*
+ * mrsas_linux_ioctl: linux emulator IOCtl commands entry point.
+ *
+ * This function is the entry point for IOCtls from linux binaries.
+ * It calls the mrsas_ioctl function for processing
+ * depending on the IOCTL command received.
+ */
+static int
+mrsas_linux_ioctl(struct thread *p, struct linux_ioctl_args *args)
+{
+#if (__FreeBSD_version >= 1000000)
+ cap_rights_t rights;
+
+#endif
+ struct file *fp;
+ int error;
+ u_long cmd = args->cmd;
+
+ if (cmd != MRSAS_LINUX_CMD32) {
+ error = ENOTSUP;
+ goto END;
+ }
+#if (__FreeBSD_version >= 1000000)
+ error = fget(p, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+#elif (__FreeBSD_version <= 900000)
+ error = fget(p, args->fd, &fp);
+#else /* For FreeBSD version greater than
+ * 9.0.0 but less than 10.0.0 */
+ error = fget(p, args->fd, CAP_IOCTL, &fp);
+#endif
+ if (error != 0)
+ goto END;
+
+ error = fo_ioctl(fp, cmd, (caddr_t)args->arg, p->td_ucred, p);
+ fdrop(fp, p);
+END:
+ return (error);
+}
+
+DEV_MODULE(mrsas_linux, mrsas_linux_modevent, NULL);
+MODULE_DEPEND(mrsas, linux, 1, 1, 1);
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 1bb3172..2666d7f 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -207,6 +207,7 @@ struct pci_quirk {
#define PCI_QUIRK_ENABLE_MSI_VM 3 /* Older chipset in VM where MSI works */
#define PCI_QUIRK_UNMAP_REG 4 /* Ignore PCI map register */
#define PCI_QUIRK_DISABLE_MSIX 5 /* MSI-X doesn't work */
+#define PCI_QUIRK_MSI_INTX_BUG 6 /* PCIM_CMD_INTxDIS disables MSI */
int arg1;
int arg2;
};
@@ -266,6 +267,15 @@ static const struct pci_quirk pci_quirks[] = {
*/
{ 0x43851002, PCI_QUIRK_UNMAP_REG, 0x14, 0 },
+ /*
+ * Atheros AR8161/AR8162/E2200 ethernet controller has a bug that
+ * MSI interrupt does not assert if PCIM_CMD_INTxDIS bit of the
+ * command register is set.
+ */
+ { 0x10911969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+ { 0xE0911969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+ { 0x10901969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+
{ 0 }
};
@@ -3856,8 +3866,14 @@ pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
mte->mte_handlers++;
}
- /* Make sure that INTx is disabled if we are using MSI/MSIX */
- pci_set_command_bit(dev, child, PCIM_CMD_INTxDIS);
+ if (!pci_has_quirk(pci_get_devid(dev),
+ PCI_QUIRK_MSI_INTX_BUG)) {
+ /*
+ * Make sure that INTx is disabled if we are
+ * using MSI/MSIX
+ */
+ pci_set_command_bit(dev, child, PCIM_CMD_INTxDIS);
+ }
bad:
if (error) {
(void)bus_generic_teardown_intr(dev, child, irq,
@@ -3949,6 +3965,7 @@ pci_print_child(device_t dev, device_t child)
retval += printf(" at device %d.%d", pci_get_slot(child),
pci_get_function(child));
+ retval += bus_print_child_domain(dev, child);
retval += bus_print_child_footer(dev, child);
return (retval);
diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c
index f52fec1..65ecf76 100644
--- a/sys/dev/uart/uart_bus_fdt.c
+++ b/sys/dev/uart/uart_bus_fdt.c
@@ -84,7 +84,7 @@ static struct ofw_compat_data compat_data[] = {
{"fsl,imx21-uart", (uintptr_t)&uart_imx_class},
{"fsl,mvf600-uart", (uintptr_t)&uart_vybrid_class},
{"lpc,uart", (uintptr_t)&uart_lpc_class},
- {"qcom,uart-dm", (uintptr_t)&uart_msm_class},
+ {"qcom,msm-uartdm", (uintptr_t)&uart_msm_class},
{"ti,ns16550", (uintptr_t)&uart_ti8250_class},
{"ns16550", (uintptr_t)&uart_ns8250_class},
{NULL, (uintptr_t)NULL},
diff --git a/sys/dev/usb/usb_freebsd.h b/sys/dev/usb/usb_freebsd.h
index cda4e69..5c10923 100644
--- a/sys/dev/usb/usb_freebsd.h
+++ b/sys/dev/usb/usb_freebsd.h
@@ -50,6 +50,7 @@
#define USB_HAVE_FIXED_IFACE 0
#define USB_HAVE_FIXED_CONFIG 0
#define USB_HAVE_FIXED_PORT 0
+#define USB_HAVE_DISABLE_ENUM 1
/* define zero ticks callout value */
#define USB_CALLOUT_ZERO_TICKS 1
diff --git a/sys/dev/usb/usb_freebsd_loader.h b/sys/dev/usb/usb_freebsd_loader.h
index bd08218..4f82dd0 100644
--- a/sys/dev/usb/usb_freebsd_loader.h
+++ b/sys/dev/usb/usb_freebsd_loader.h
@@ -50,6 +50,7 @@
#define USB_HAVE_FIXED_IFACE 0
#define USB_HAVE_FIXED_CONFIG 0
#define USB_HAVE_FIXED_PORT 0
+#define USB_HAVE_DISABLE_ENUM 0
#define USB_CALLOUT_ZERO_TICKS 1
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index 8e0d557..6d79327 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -97,6 +97,16 @@ SYSCTL_INT(_hw_usb, OID_AUTO, power_timeout, CTLFLAG_RW,
&usb_power_timeout, 0, "USB power timeout");
#endif
+#if USB_HAVE_DISABLE_ENUM
+static int usb_disable_enumeration = 0;
+SYSCTL_INT(_hw_usb, OID_AUTO, disable_enumeration, CTLFLAG_RWTUN,
+ &usb_disable_enumeration, 0, "Set to disable all USB device enumeration.");
+
+static int usb_disable_port_power = 0;
+SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN,
+ &usb_disable_port_power, 0, "Set to disable all USB port power.");
+#endif
+
struct uhub_current_state {
uint16_t port_change;
uint16_t port_status;
@@ -111,6 +121,10 @@ struct uhub_softc {
struct mtx sc_mtx; /* our mutex */
struct usb_device *sc_udev; /* USB device */
struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
+#if USB_HAVE_DISABLE_ENUM
+ int sc_disable_enumeration;
+ int sc_disable_port_power;
+#endif
uint8_t sc_flags;
#define UHUB_FLAG_DID_EXPLORE 0x01
};
@@ -618,9 +632,9 @@ repeat:
err = usbd_req_clear_port_feature(udev, NULL,
portno, UHF_C_PORT_CONNECTION);
- if (err) {
+ if (err)
goto error;
- }
+
/* check if there is a child */
if (child != NULL) {
@@ -633,14 +647,22 @@ repeat:
/* get fresh status */
err = uhub_read_port_status(sc, portno);
- if (err) {
+ if (err)
+ goto error;
+
+#if USB_HAVE_DISABLE_ENUM
+ /* check if we should skip enumeration from this USB HUB */
+ if (usb_disable_enumeration != 0 ||
+ sc->sc_disable_enumeration != 0) {
+ DPRINTF("Enumeration is disabled!\n");
goto error;
}
+#endif
/* check if nothing is connected to the port */
- if (!(sc->sc_st.port_status & UPS_CURRENT_CONNECT_STATUS)) {
+ if (!(sc->sc_st.port_status & UPS_CURRENT_CONNECT_STATUS))
goto error;
- }
+
/* check if there is no power on the port and print a warning */
switch (udev->speed) {
@@ -1188,6 +1210,10 @@ uhub_attach(device_t dev)
struct usb_hub *hub;
struct usb_hub_descriptor hubdesc20;
struct usb_hub_ss_descriptor hubdesc30;
+#if USB_HAVE_DISABLE_ENUM
+ struct sysctl_ctx_list *sysctl_ctx;
+ struct sysctl_oid *sysctl_tree;
+#endif
uint16_t pwrdly;
uint16_t nports;
uint8_t x;
@@ -1385,6 +1411,24 @@ uhub_attach(device_t dev)
/* wait with power off for a while */
usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME));
+#if USB_HAVE_DISABLE_ENUM
+ /* Add device sysctls */
+
+ sysctl_ctx = device_get_sysctl_ctx(dev);
+ sysctl_tree = device_get_sysctl_tree(dev);
+
+ if (sysctl_ctx != NULL && sysctl_tree != NULL) {
+ (void) SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "disable_enumeration", CTLFLAG_RWTUN,
+ &sc->sc_disable_enumeration, 0,
+ "Set to disable enumeration on this USB HUB.");
+
+ (void) SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "disable_port_power", CTLFLAG_RWTUN,
+ &sc->sc_disable_port_power, 0,
+ "Set to disable USB port power on this USB HUB.");
+ }
+#endif
/*
* To have the best chance of success we do things in the exact same
* order as Windoze98. This should not be necessary, but some
@@ -1439,13 +1483,27 @@ uhub_attach(device_t dev)
removable++;
break;
}
- if (!err) {
- /* turn the power on */
- err = usbd_req_set_port_feature(udev, NULL,
- portno, UHF_PORT_POWER);
+ if (err == 0) {
+#if USB_HAVE_DISABLE_ENUM
+ /* check if we should disable USB port power or not */
+ if (usb_disable_port_power != 0 ||
+ sc->sc_disable_port_power != 0) {
+ /* turn the power off */
+ DPRINTFN(0, "Turning port %d power off\n", portno);
+ err = usbd_req_clear_port_feature(udev, NULL,
+ portno, UHF_PORT_POWER);
+ } else {
+#endif
+ /* turn the power on */
+ DPRINTFN(0, "Turning port %d power on\n", portno);
+ err = usbd_req_set_port_feature(udev, NULL,
+ portno, UHF_PORT_POWER);
+#if USB_HAVE_DISABLE_ENUM
+ }
+#endif
}
- if (err) {
- DPRINTFN(0, "port %d power on failed, %s\n",
+ if (err != 0) {
+ DPRINTFN(0, "port %d power on or off failed, %s\n",
portno, usbd_errstr(err));
}
DPRINTF("turn on port %d power\n",
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 17a8806..a5273ac 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -2353,6 +2353,8 @@ product HUAWEI E3131 0x1506 3G modem
product HUAWEI K3765_INIT 0x1520 K3765 Initial
product HUAWEI K4505_INIT 0x1521 K4505 Initial
product HUAWEI E3272_INIT 0x155b LTE modem initial
+product HUAWEI R215_INIT 0x1582 LTE modem initial
+product HUAWEI R215 0x1588 LTE modem
product HUAWEI ETS2055 0x1803 CDMA modem
product HUAWEI E173 0x1c05 3G modem
product HUAWEI E173_INIT 0x1c0b 3G modem initial
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index 2dd7e3f..487a7ce 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -120,6 +120,7 @@ const struct terminal_class vt_termclass = {
static SYSCTL_NODE(_kern, OID_AUTO, vt, CTLFLAG_RD, 0, "vt(9) parameters");
VT_SYSCTL_INT(enable_altgr, 1, "Enable AltGr key (Do not assume R.Alt as Alt)");
+VT_SYSCTL_INT(enable_bell, 1, "Enable bell");
VT_SYSCTL_INT(debug, 0, "vt(9) debug level");
VT_SYSCTL_INT(deadtimer, 15, "Time to wait busy process in VT_PROCESS mode");
VT_SYSCTL_INT(suspendswitch, 1, "Switch to VT0 before suspend");
@@ -904,6 +905,9 @@ vtterm_bell(struct terminal *tm)
struct vt_window *vw = tm->tm_softc;
struct vt_device *vd = vw->vw_device;
+ if (!vt_enable_bell)
+ return;
+
if (vd->vd_flags & VDF_QUIET_BELL)
return;
@@ -915,6 +919,9 @@ vtterm_beep(struct terminal *tm, u_int param)
{
u_int freq, period;
+ if (!vt_enable_bell)
+ return;
+
if ((param == 0) || ((param & 0xffff) == 0)) {
vtterm_bell(tm);
return;
@@ -1269,7 +1276,8 @@ vtterm_cnprobe(struct terminal *tm, struct consdev *cp)
* that we have the real viewable size, fix it in the static
* buffer.
*/
- vt_termsize(vd, vw->vw_font, &vw->vw_buf.vb_scr_size);
+ if (vd->vd_width != 0 && vd->vd_height != 0)
+ vt_termsize(vd, vw->vw_font, &vw->vw_buf.vb_scr_size);
vtbuf_init_early(&vw->vw_buf);
vt_winsize(vd, vw->vw_font, &wsz);
diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c
index 719a2c5..a2aa6c1 100644
--- a/sys/fs/autofs/autofs.c
+++ b/sys/fs/autofs/autofs.c
@@ -367,7 +367,7 @@ autofs_trigger_one(struct autofs_node *anp,
char *key, *path;
int error = 0, request_error, last;
- amp = VFSTOAUTOFS(anp->an_vnode->v_mount);
+ amp = anp->an_mount;
sx_assert(&autofs_softc->sc_lock, SA_XLOCKED);
diff --git a/sys/fs/autofs/autofs.h b/sys/fs/autofs/autofs.h
index 0713307..dc33eef 100644
--- a/sys/fs/autofs/autofs.h
+++ b/sys/fs/autofs/autofs.h
@@ -138,6 +138,6 @@ int autofs_node_find(struct autofs_node *parent,
const char *name, int namelen, struct autofs_node **anpp);
void autofs_node_delete(struct autofs_node *anp);
int autofs_node_vn(struct autofs_node *anp, struct mount *mp,
- struct vnode **vpp);
+ int flags, struct vnode **vpp);
#endif /* !AUTOFS_H */
diff --git a/sys/fs/autofs/autofs_vfsops.c b/sys/fs/autofs/autofs_vfsops.c
index 21a49d9..13a5a89 100644
--- a/sys/fs/autofs/autofs_vfsops.c
+++ b/sys/fs/autofs/autofs_vfsops.c
@@ -88,6 +88,10 @@ autofs_mount(struct mount *mp)
vfs_getnewfsid(mp);
+ MNT_ILOCK(mp);
+ mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED;
+ MNT_IUNLOCK(mp);
+
AUTOFS_XLOCK(amp);
error = autofs_node_new(NULL, amp, ".", -1, &amp->am_root);
if (error != 0) {
@@ -177,7 +181,7 @@ autofs_root(struct mount *mp, int flags, struct vnode **vpp)
amp = VFSTOAUTOFS(mp);
- error = autofs_node_vn(amp->am_root, mp, vpp);
+ error = autofs_node_vn(amp->am_root, mp, flags, vpp);
return (error);
}
diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c
index 53490b3..a3ae3a9 100644
--- a/sys/fs/autofs/autofs_vnops.c
+++ b/sys/fs/autofs/autofs_vnops.c
@@ -198,12 +198,12 @@ mounted:
}
static int
-autofs_vget_callback(struct mount *mp, void *arg, int lkflags __unused,
+autofs_vget_callback(struct mount *mp, void *arg, int flags,
struct vnode **vpp)
{
- return (autofs_node_vn(arg, mp, vpp));
+ return (autofs_node_vn(arg, mp, flags, vpp));
}
static int
@@ -233,7 +233,7 @@ autofs_lookup(struct vop_lookup_args *ap)
* use vn_vget_ino_gen() which takes care of all that.
*/
error = vn_vget_ino_gen(dvp, autofs_vget_callback,
- anp->an_parent, 0, vpp);
+ anp->an_parent, cnp->cn_lkflags, vpp);
if (error != 0) {
AUTOFS_WARN("vn_vget_ino_gen() failed with error %d",
error);
@@ -294,7 +294,7 @@ autofs_lookup(struct vop_lookup_args *ap)
*/
AUTOFS_SUNLOCK(amp);
- error = autofs_node_vn(child, mp, vpp);
+ error = autofs_node_vn(child, mp, cnp->cn_lkflags, vpp);
if (error != 0) {
if ((cnp->cn_flags & ISLASTCN) && cnp->cn_nameiop == CREATE)
return (EJUSTRETURN);
@@ -334,7 +334,7 @@ autofs_mkdir(struct vop_mkdir_args *ap)
}
AUTOFS_XUNLOCK(amp);
- error = autofs_node_vn(child, vp->v_mount, ap->a_vpp);
+ error = autofs_node_vn(child, vp->v_mount, LK_EXCLUSIVE, ap->a_vpp);
return (error);
}
@@ -459,8 +459,8 @@ autofs_readdir(struct vop_readdir_args *ap)
static int
autofs_reclaim(struct vop_reclaim_args *ap)
{
- struct vnode *vp = ap->a_vp;
- struct autofs_node *anp = vp->v_data;
+ struct vnode *vp;
+ struct autofs_node *anp;
vp = ap->a_vp;
anp = vp->v_data;
@@ -581,7 +581,8 @@ autofs_node_delete(struct autofs_node *anp)
}
int
-autofs_node_vn(struct autofs_node *anp, struct mount *mp, struct vnode **vpp)
+autofs_node_vn(struct autofs_node *anp, struct mount *mp, int flags,
+ struct vnode **vpp)
{
struct vnode *vp;
int error;
@@ -592,7 +593,7 @@ autofs_node_vn(struct autofs_node *anp, struct mount *mp, struct vnode **vpp)
vp = anp->an_vnode;
if (vp != NULL) {
- error = vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+ error = vget(vp, flags | LK_RETRY, curthread);
if (error != 0) {
AUTOFS_WARN("vget failed with error %d", error);
sx_xunlock(&anp->an_vnode_lock);
@@ -632,6 +633,8 @@ autofs_node_vn(struct autofs_node *anp, struct mount *mp, struct vnode **vpp)
vp->v_vflag |= VV_ROOT;
vp->v_data = anp;
+ VN_LOCK_ASHARE(vp);
+
error = insmntque(vp, mp);
if (error != 0) {
AUTOFS_WARN("insmntque() failed with error %d", error);
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index d0aabef..d7009a4 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -545,22 +545,25 @@ devfs_close(struct vop_close_args *ap)
* if the reference count is 2 (this last descriptor
* plus the session), release the reference from the session.
*/
- oldvp = NULL;
- sx_xlock(&proctree_lock);
if (td && vp == td->td_proc->p_session->s_ttyvp) {
- SESS_LOCK(td->td_proc->p_session);
- VI_LOCK(vp);
- if (count_dev(dev) == 2 && (vp->v_iflag & VI_DOOMED) == 0) {
- td->td_proc->p_session->s_ttyvp = NULL;
- td->td_proc->p_session->s_ttydp = NULL;
- oldvp = vp;
+ oldvp = NULL;
+ sx_xlock(&proctree_lock);
+ if (vp == td->td_proc->p_session->s_ttyvp) {
+ SESS_LOCK(td->td_proc->p_session);
+ VI_LOCK(vp);
+ if (count_dev(dev) == 2 &&
+ (vp->v_iflag & VI_DOOMED) == 0) {
+ td->td_proc->p_session->s_ttyvp = NULL;
+ td->td_proc->p_session->s_ttydp = NULL;
+ oldvp = vp;
+ }
+ VI_UNLOCK(vp);
+ SESS_UNLOCK(td->td_proc->p_session);
}
- VI_UNLOCK(vp);
- SESS_UNLOCK(td->td_proc->p_session);
+ sx_xunlock(&proctree_lock);
+ if (oldvp != NULL)
+ vrele(oldvp);
}
- sx_xunlock(&proctree_lock);
- if (oldvp != NULL)
- vrele(oldvp);
/*
* We do not want to really close the device if it
* is still in use unless we are trying to close it
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index c7104d8..e6213ee 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -82,6 +82,8 @@ static struct cdevsw g_dev_cdevsw = {
.d_flags = D_DISK | D_TRACKCLOSE,
};
+static g_init_t g_dev_init;
+static g_fini_t g_dev_fini;
static g_taste_t g_dev_taste;
static g_orphan_t g_dev_orphan;
static g_attrchanged_t g_dev_attrchanged;
@@ -89,6 +91,8 @@ static g_attrchanged_t g_dev_attrchanged;
static struct g_class g_dev_class = {
.name = "DEV",
.version = G_VERSION,
+ .init = g_dev_init,
+ .fini = g_dev_fini,
.taste = g_dev_taste,
.orphan = g_dev_orphan,
.attrchanged = g_dev_attrchanged
@@ -107,6 +111,58 @@ SYSCTL_QUAD(_kern_geom_dev, OID_AUTO, delete_max_sectors, CTLFLAG_RW,
"delete request sent to the provider. Larger requests are chunked "
"so they can be interrupted. (0 = disable chunking)");
+static char *dumpdev = NULL;
+static void
+g_dev_init(struct g_class *mp)
+{
+
+ dumpdev = getenv("dumpdev");
+}
+
+static void
+g_dev_fini(struct g_class *mp)
+{
+
+ freeenv(dumpdev);
+}
+
+static int
+g_dev_setdumpdev(struct cdev *dev)
+{
+ struct g_kerneldump kd;
+ struct g_consumer *cp;
+ int error, len;
+
+ if (dev == NULL)
+ return (set_dumper(NULL, NULL));
+
+ cp = dev->si_drv2;
+ len = sizeof(kd);
+ kd.offset = 0;
+ kd.length = OFF_MAX;
+ error = g_io_getattr("GEOM::kerneldump", cp, &len, &kd);
+ if (error == 0) {
+ error = set_dumper(&kd.di, devtoname(dev));
+ if (error == 0)
+ dev->si_flags |= SI_DUMPDEV;
+ }
+ return (error);
+}
+
+static void
+init_dumpdev(struct cdev *dev)
+{
+
+ if (dumpdev == NULL)
+ return;
+ if (strcmp(devtoname(dev), dumpdev) != 0)
+ return;
+ if (g_dev_setdumpdev(dev) == 0) {
+ freeenv(dumpdev);
+ dumpdev = NULL;
+ }
+}
+
static void
g_dev_destroy(void *arg, int flags __unused)
{
@@ -261,10 +317,12 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
dev->si_iosize_max = MAXPHYS;
dev->si_drv2 = cp;
+ init_dumpdev(dev);
if (adev != NULL) {
adev->si_iosize_max = MAXPHYS;
adev->si_drv2 = cp;
adev->si_flags |= SI_UNMAPPED;
+ init_dumpdev(adev);
}
g_dev_attrchanged(cp, "GEOM::physpath");
@@ -358,7 +416,6 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread
{
struct g_consumer *cp;
struct g_provider *pp;
- struct g_kerneldump kd;
off_t offset, length, chunk;
int i, error;
@@ -395,19 +452,10 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread
error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
break;
case DIOCSKERNELDUMP:
- if (*(u_int *)data == 0) {
- error = set_dumper(NULL, NULL);
- break;
- }
- kd.offset = 0;
- kd.length = OFF_MAX;
- i = sizeof kd;
- error = g_io_getattr("GEOM::kerneldump", cp, &i, &kd);
- if (error == 0) {
- error = set_dumper(&kd.di, devtoname(dev));
- if (error == 0)
- dev->si_flags |= SI_DUMPDEV;
- }
+ if (*(u_int *)data == 0)
+ error = g_dev_setdumpdev(NULL);
+ else
+ error = g_dev_setdumpdev(dev);
break;
case DIOCGFLUSH:
error = g_io_flush(cp);
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 8892c56..9d98f0e 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -109,7 +109,11 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_sym.h>
#endif
+#ifdef PC98
+#include <pc98/pc98/pc98_machdep.h>
+#else
#include <isa/rtc.h>
+#endif
#include <net/netisr.h>
@@ -204,6 +208,14 @@ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
int _udatasel, _ucodesel;
u_int basemem;
+#ifdef PC98
+int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */
+int need_post_dma_flush; /* If 1, use invd after DMA transfer. */
+
+static int ispc98 = 1;
+SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, "");
+#endif
+
int cold = 1;
#ifdef COMPAT_43
@@ -259,7 +271,8 @@ cpu_startup(dummy)
{
uintmax_t memsize;
char *sysenv;
-
+
+#ifndef PC98
/*
* On MacBooks, we need to disallow the legacy USB circuit to
* generate an SMI# because this can cause several problems,
@@ -285,6 +298,7 @@ cpu_startup(dummy)
}
freeenv(sysenv);
}
+#endif /* !PC98 */
/*
* Good {morning,afternoon,evening,night}.
@@ -1235,6 +1249,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RWTUN, &idle_mwait,
#define STATE_MWAIT 0x1
#define STATE_SLEEPING 0x2
+#ifndef PC98
static void
cpu_idle_acpi(sbintime_t sbt)
{
@@ -1253,6 +1268,7 @@ cpu_idle_acpi(sbintime_t sbt)
__asm __volatile("sti; hlt");
*state = STATE_RUNNING;
}
+#endif /* !PC98 */
#ifndef XEN
static void
@@ -1370,7 +1386,7 @@ cpu_probe_amdc1e(void)
}
}
-#ifdef XEN
+#if defined(PC98) || defined(XEN)
void (*cpu_idle_fn)(sbintime_t) = cpu_idle_hlt;
#else
void (*cpu_idle_fn)(sbintime_t) = cpu_idle_acpi;
@@ -1458,7 +1474,9 @@ struct {
{ cpu_idle_spin, "spin" },
{ cpu_idle_mwait, "mwait" },
{ cpu_idle_hlt, "hlt" },
+#ifndef PC98
{ cpu_idle_acpi, "acpi" },
+#endif
{ NULL, NULL }
};
@@ -1475,9 +1493,11 @@ idle_sysctl_available(SYSCTL_HANDLER_ARGS)
if (strstr(idle_tbl[i].id_name, "mwait") &&
(cpu_feature2 & CPUID2_MON) == 0)
continue;
+#ifndef PC98
if (strcmp(idle_tbl[i].id_name, "acpi") == 0 &&
cpu_idle_hook == NULL)
continue;
+#endif
p += sprintf(p, "%s%s", p != avail ? ", " : "",
idle_tbl[i].id_name);
}
@@ -1512,9 +1532,11 @@ idle_sysctl(SYSCTL_HANDLER_ARGS)
if (strstr(idle_tbl[i].id_name, "mwait") &&
(cpu_feature2 & CPUID2_MON) == 0)
continue;
+#ifndef PC98
if (strcmp(idle_tbl[i].id_name, "acpi") == 0 &&
cpu_idle_hook == NULL)
continue;
+#endif
if (strcmp(idle_tbl[i].id_name, buf))
continue;
cpu_idle_fn = idle_tbl[i].id_fn;
@@ -2000,7 +2022,7 @@ sdtossd(sd, ssd)
ssd->ssd_gran = sd->sd_gran;
}
-#ifndef XEN
+#if !defined(PC98) && !defined(XEN)
static int
add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
int *physmap_idxp)
@@ -2107,7 +2129,9 @@ add_smap_entries(struct bios_smap *smapbase, vm_paddr_t *physmap,
if (!add_smap_entry(smap, physmap, physmap_idxp))
break;
}
+#endif /* !PC98 && !XEN */
+#ifndef XEN
static void
basemem_setup(void)
{
@@ -2155,7 +2179,7 @@ basemem_setup(void)
for (i = basemem / 4; i < 160; i++)
pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
}
-#endif
+#endif /* !XEN */
/*
* Populate the (physmap) array with base/bound pairs describing the
@@ -2170,6 +2194,271 @@ basemem_setup(void)
*
* XXX first should be vm_paddr_t.
*/
+#ifdef PC98
+static void
+getmemsize(int first)
+{
+ int off, physmap_idx, pa_indx, da_indx;
+ u_long physmem_tunable, memtest;
+ vm_paddr_t physmap[PHYSMAP_SIZE];
+ pt_entry_t *pte;
+ quad_t dcons_addr, dcons_size;
+ int i;
+ int pg_n;
+ u_int extmem;
+ u_int under16;
+ vm_paddr_t pa;
+
+ bzero(physmap, sizeof(physmap));
+
+ /* XXX - some of EPSON machines can't use PG_N */
+ pg_n = PG_N;
+ if (pc98_machine_type & M_EPSON_PC98) {
+ switch (epson_machine_id) {
+#ifdef WB_CACHE
+ default:
+#endif
+ case EPSON_PC486_HX:
+ case EPSON_PC486_HG:
+ case EPSON_PC486_HA:
+ pg_n = 0;
+ break;
+ }
+ }
+
+ under16 = pc98_getmemsize(&basemem, &extmem);
+ basemem_setup();
+
+ physmap[0] = 0;
+ physmap[1] = basemem * 1024;
+ physmap_idx = 2;
+ physmap[physmap_idx] = 0x100000;
+ physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024;
+
+ /*
+ * Now, physmap contains a map of physical memory.
+ */
+
+#ifdef SMP
+ /* make hole for AP bootstrap code */
+ physmap[1] = mp_bootaddress(physmap[1]);
+#endif
+
+ /*
+ * Maxmem isn't the "maximum memory", it's one larger than the
+ * highest page of the physical address space. It should be
+ * called something like "Maxphyspage". We may adjust this
+ * based on ``hw.physmem'' and the results of the memory test.
+ */
+ Maxmem = atop(physmap[physmap_idx + 1]);
+
+#ifdef MAXMEM
+ Maxmem = MAXMEM / 4;
+#endif
+
+ if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
+ Maxmem = atop(physmem_tunable);
+
+ /*
+ * By default keep the memtest enabled. Use a general name so that
+ * one could eventually do more with the code than just disable it.
+ */
+ memtest = 1;
+ TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest);
+
+ if (atop(physmap[physmap_idx + 1]) != Maxmem &&
+ (boothowto & RB_VERBOSE))
+ printf("Physical memory use set to %ldK\n", Maxmem * 4);
+
+ /*
+ * If Maxmem has been increased beyond what the system has detected,
+ * extend the last memory segment to the new limit.
+ */
+ if (atop(physmap[physmap_idx + 1]) < Maxmem)
+ physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem);
+
+ /*
+ * We need to divide chunk if Maxmem is larger than 16MB and
+ * under 16MB area is not full of memory.
+ * (1) system area (15-16MB region) is cut off
+ * (2) extended memory is only over 16MB area (ex. Melco "HYPERMEMORY")
+ */
+ if ((under16 != 16 * 1024) && (extmem > 15 * 1024)) {
+ /* 15M - 16M region is cut off, so need to divide chunk */
+ physmap[physmap_idx + 1] = under16 * 1024;
+ physmap_idx += 2;
+ physmap[physmap_idx] = 0x1000000;
+ physmap[physmap_idx + 1] = physmap[2] + extmem * 1024;
+ }
+
+ /* call pmap initialization to make new kernel address space */
+ pmap_bootstrap(first);
+
+ /*
+ * Size up each available chunk of physical memory.
+ */
+ physmap[0] = PAGE_SIZE; /* mask off page 0 */
+ pa_indx = 0;
+ da_indx = 1;
+ phys_avail[pa_indx++] = physmap[0];
+ phys_avail[pa_indx] = physmap[0];
+ dump_avail[da_indx] = physmap[0];
+ pte = CMAP3;
+
+ /*
+ * Get dcons buffer address
+ */
+ if (getenv_quad("dcons.addr", &dcons_addr) == 0 ||
+ getenv_quad("dcons.size", &dcons_size) == 0)
+ dcons_addr = 0;
+
+ /*
+ * physmap is in bytes, so when converting to page boundaries,
+ * round up the start address and round down the end address.
+ */
+ for (i = 0; i <= physmap_idx; i += 2) {
+ vm_paddr_t end;
+
+ end = ptoa((vm_paddr_t)Maxmem);
+ if (physmap[i + 1] < end)
+ end = trunc_page(physmap[i + 1]);
+ for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) {
+ int tmp, page_bad, full;
+ int *ptr = (int *)CADDR3;
+
+ full = FALSE;
+ /*
+ * block out kernel memory as not available.
+ */
+ if (pa >= KERNLOAD && pa < first)
+ goto do_dump_avail;
+
+ /*
+ * block out dcons buffer
+ */
+ if (dcons_addr > 0
+ && pa >= trunc_page(dcons_addr)
+ && pa < dcons_addr + dcons_size)
+ goto do_dump_avail;
+
+ page_bad = FALSE;
+ if (memtest == 0)
+ goto skip_memtest;
+
+ /*
+ * map page into kernel: valid, read/write,non-cacheable
+ */
+ *pte = pa | PG_V | PG_RW | pg_n;
+ invltlb();
+
+ tmp = *(int *)ptr;
+ /*
+ * Test for alternating 1's and 0's
+ */
+ *(volatile int *)ptr = 0xaaaaaaaa;
+ if (*(volatile int *)ptr != 0xaaaaaaaa)
+ page_bad = TRUE;
+ /*
+ * Test for alternating 0's and 1's
+ */
+ *(volatile int *)ptr = 0x55555555;
+ if (*(volatile int *)ptr != 0x55555555)
+ page_bad = TRUE;
+ /*
+ * Test for all 1's
+ */
+ *(volatile int *)ptr = 0xffffffff;
+ if (*(volatile int *)ptr != 0xffffffff)
+ page_bad = TRUE;
+ /*
+ * Test for all 0's
+ */
+ *(volatile int *)ptr = 0x0;
+ if (*(volatile int *)ptr != 0x0)
+ page_bad = TRUE;
+ /*
+ * Restore original value.
+ */
+ *(int *)ptr = tmp;
+
+skip_memtest:
+ /*
+ * Adjust array of valid/good pages.
+ */
+ if (page_bad == TRUE)
+ continue;
+ /*
+ * If this good page is a continuation of the
+ * previous set of good pages, then just increase
+ * the end pointer. Otherwise start a new chunk.
+ * Note that "end" points one higher than end,
+ * making the range >= start and < end.
+ * If we're also doing a speculative memory
+ * test and we at or past the end, bump up Maxmem
+ * so that we keep going. The first bad page
+ * will terminate the loop.
+ */
+ if (phys_avail[pa_indx] == pa) {
+ phys_avail[pa_indx] += PAGE_SIZE;
+ } else {
+ pa_indx++;
+ if (pa_indx == PHYS_AVAIL_ARRAY_END) {
+ printf(
+ "Too many holes in the physical address space, giving up\n");
+ pa_indx--;
+ full = TRUE;
+ goto do_dump_avail;
+ }
+ phys_avail[pa_indx++] = pa; /* start */
+ phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */
+ }
+ physmem++;
+do_dump_avail:
+ if (dump_avail[da_indx] == pa) {
+ dump_avail[da_indx] += PAGE_SIZE;
+ } else {
+ da_indx++;
+ if (da_indx == DUMP_AVAIL_ARRAY_END) {
+ da_indx--;
+ goto do_next;
+ }
+ dump_avail[da_indx++] = pa; /* start */
+ dump_avail[da_indx] = pa + PAGE_SIZE; /* end */
+ }
+do_next:
+ if (full)
+ break;
+ }
+ }
+ *pte = 0;
+ invltlb();
+
+ /*
+ * XXX
+ * The last chunk must contain at least one page plus the message
+ * buffer to avoid complicating other code (message buffer address
+ * calculation, etc.).
+ */
+ while (phys_avail[pa_indx - 1] + PAGE_SIZE +
+ round_page(msgbufsize) >= phys_avail[pa_indx]) {
+ physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
+ phys_avail[pa_indx--] = 0;
+ phys_avail[pa_indx--] = 0;
+ }
+
+ Maxmem = atop(phys_avail[pa_indx]);
+
+ /* Trim off space for the message buffer. */
+ phys_avail[pa_indx] -= round_page(msgbufsize);
+
+ /* Map the message buffer. */
+ for (off = 0; off < round_page(msgbufsize); off += PAGE_SIZE)
+ pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] +
+ off);
+
+ PT_UPDATES_FLUSH();
+}
+#else /* PC98 */
static void
getmemsize(int first)
{
@@ -2567,6 +2856,7 @@ do_next:
PT_UPDATES_FLUSH();
}
+#endif /* PC98 */
#ifdef XEN
#define MTOPSIZE (1<<(14 + PAGE_SHIFT))
@@ -2830,6 +3120,13 @@ init386(first)
*/
proc_linkup0(&proc0, &thread0);
+#ifdef PC98
+ /*
+ * Initialize DMAC
+ */
+ pc98_init_dmac();
+#endif
+
metadata_missing = 0;
if (bootinfo.bi_modulep) {
preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE;
@@ -2993,7 +3290,9 @@ init386(first)
#ifdef DEV_ISA
#ifdef DEV_ATPIC
+#ifndef PC98
elcr_probe();
+#endif
atpic_startup();
#else
/* Reset and mask the atpics and leave them shut down. */
@@ -3027,6 +3326,7 @@ init386(first)
setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
+ initializecpucache();
/* make an initial tss so cpu can get interrupt stack on syscall! */
/* Note: -16 is so we can grow the trapframe if we came from vm86 */
@@ -3114,6 +3414,7 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
pcpu->pc_acpi_id = 0xffffffff;
}
+#ifndef PC98
static int
smap_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
@@ -3149,6 +3450,7 @@ smap_sysctl_handler(SYSCTL_HANDLER_ARGS)
}
SYSCTL_PROC(_machdep, OID_AUTO, smap, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0,
smap_sysctl_handler, "S,bios_smap_xattr", "Raw BIOS SMAP data");
+#endif /* !PC98 */
void
spinlock_enter(void)
diff --git a/sys/i386/i386/minidump_machdep.c b/sys/i386/i386/minidump_machdep.c
index e0cd1ff..dd3490b 100644
--- a/sys/i386/i386/minidump_machdep.c
+++ b/sys/i386/i386/minidump_machdep.c
@@ -178,7 +178,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
/* A fake page table page, to avoid having to handle both 4K and 2M pages */
static pt_entry_t fakept[NPTEPG];
-void
+int
minidumpsys(struct dumperinfo *di)
{
uint64_t dumpsize;
@@ -377,7 +377,7 @@ minidumpsys(struct dumperinfo *di)
/* Signal completion, signoff and exit stage left. */
dump_write(di, NULL, 0, 0, 0);
printf("\nDump complete\n");
- return;
+ return (0);
fail:
if (error < 0)
@@ -389,6 +389,7 @@ minidumpsys(struct dumperinfo *di)
printf("\nDump failed. Partition too small.\n");
else
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+ return (error);
}
void
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 37e14e9..90ea046 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -1172,16 +1172,20 @@ pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde)
#define PMAP_CLFLUSH_THRESHOLD (2 * 1024 * 1024)
void
-pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
+pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva, boolean_t force)
{
- KASSERT((sva & PAGE_MASK) == 0,
- ("pmap_invalidate_cache_range: sva not page-aligned"));
- KASSERT((eva & PAGE_MASK) == 0,
- ("pmap_invalidate_cache_range: eva not page-aligned"));
+ if (force) {
+ sva &= ~(vm_offset_t)cpu_clflush_line_size;
+ } else {
+ KASSERT((sva & PAGE_MASK) == 0,
+ ("pmap_invalidate_cache_range: sva not page-aligned"));
+ KASSERT((eva & PAGE_MASK) == 0,
+ ("pmap_invalidate_cache_range: eva not page-aligned"));
+ }
- if (cpu_feature & CPUID_SS)
- ; /* If "Self Snoop" is supported, do nothing. */
+ if ((cpu_feature & CPUID_SS) != 0 && !force)
+ ; /* If "Self Snoop" is supported and allowed, do nothing. */
else if ((cpu_feature & CPUID_CLFSH) != 0 &&
eva - sva < PMAP_CLFLUSH_THRESHOLD) {
@@ -5164,7 +5168,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode)
for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE)
pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode);
pmap_invalidate_range(kernel_pmap, va, va + tmpsize);
- pmap_invalidate_cache_range(va, va + size);
+ pmap_invalidate_cache_range(va, va + size, FALSE);
return ((void *)(va + offset));
}
@@ -5370,7 +5374,7 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode)
*/
if (changed) {
pmap_invalidate_range(kernel_pmap, base, tmpva);
- pmap_invalidate_cache_range(base, tmpva);
+ pmap_invalidate_cache_range(base, tmpva, FALSE);
}
return (0);
}
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 9c87548..e2ba874 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -813,7 +813,7 @@ sf_buf_invalidate(struct sf_buf *sf)
* settings are recalculated.
*/
pmap_qenter(sf->kva, &m, 1);
- pmap_invalidate_cache_range(sf->kva, sf->kva + PAGE_SIZE);
+ pmap_invalidate_cache_range(sf->kva, sf->kva + PAGE_SIZE, FALSE);
}
/*
diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h
index 950fa1f..2425fab 100644
--- a/sys/i386/include/md_var.h
+++ b/sys/i386/include/md_var.h
@@ -113,6 +113,6 @@ void ppro_reenable_apic(void);
void printcpuinfo(void);
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec);
int user_dbreg_trap(void);
-void minidumpsys(struct dumperinfo *);
+int minidumpsys(struct dumperinfo *);
#endif /* !_MACHINE_MD_VAR_H_ */
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index 100475c..05656cd 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -458,7 +458,8 @@ void pmap_invalidate_range(pmap_t, vm_offset_t, vm_offset_t);
void pmap_invalidate_all(pmap_t);
void pmap_invalidate_cache(void);
void pmap_invalidate_cache_pages(vm_page_t *pages, int count);
-void pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva);
+void pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva,
+ boolean_t force);
#endif /* _KERNEL */
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m
index ccc854c..cce997c 100644
--- a/sys/kern/bus_if.m
+++ b/sys/kern/bus_if.m
@@ -692,3 +692,16 @@ METHOD int resume_child {
device_t _dev;
device_t _child;
} DEFAULT bus_generic_resume_child;
+
+/**
+ * @brief Get the VM domain handle for the given bus and child.
+ *
+ * @param _dev the bus device
+ * @param _child the child device
+ * @param _domain a pointer to the bus's domain handle identifier
+ */
+METHOD int get_domain {
+ device_t _dev;
+ device_t _child;
+ int *_domain;
+} DEFAULT bus_generic_get_domain;
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 634a50c..e3494f6 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1112,8 +1112,8 @@ core_output(struct vnode *vp, void *base, size_t len, off_t offset,
#endif
} else {
error = vn_rdwr_inchunks(UIO_WRITE, vp, base, len, offset,
- UIO_USERSPACE, IO_UNIT | IO_DIRECT, active_cred, file_cred,
- NULL, td);
+ UIO_USERSPACE, IO_UNIT | IO_DIRECT | IO_RANGELOCKED,
+ active_cred, file_cred, NULL, td);
}
return (error);
}
@@ -1160,8 +1160,8 @@ sbuf_drain_core_output(void *arg, const char *data, int len)
#endif
error = vn_rdwr_inchunks(UIO_WRITE, p->vp,
__DECONST(void *, data), len, p->offset, UIO_SYSSPACE,
- IO_UNIT | IO_DIRECT, p->active_cred, p->file_cred, NULL,
- p->td);
+ IO_UNIT | IO_DIRECT | IO_RANGELOCKED, p->active_cred,
+ p->file_cred, NULL, p->td);
if (locked)
PROC_LOCK(p->td->td_proc);
if (error != 0)
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 0e6e0f1..3decfd41 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 263318 2014-03-18 21:32:03Z attilio
+ * created from FreeBSD: head/sys/kern/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
#include "opt_compat.h"
@@ -505,10 +505,10 @@ struct sysent sysent[] = {
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 468 = nosys */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 469 = __getpath_fromfd */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 470 = __getpath_fromaddr */
- { AS(sctp_peeloff_args), (sy_call_t *)sys_sctp_peeloff, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 471 = sctp_peeloff */
- { AS(sctp_generic_sendmsg_args), (sy_call_t *)sys_sctp_generic_sendmsg, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 472 = sctp_generic_sendmsg */
- { AS(sctp_generic_sendmsg_iov_args), (sy_call_t *)sys_sctp_generic_sendmsg_iov, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 473 = sctp_generic_sendmsg_iov */
- { AS(sctp_generic_recvmsg_args), (sy_call_t *)sys_sctp_generic_recvmsg, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 474 = sctp_generic_recvmsg */
+ { AS(sctp_peeloff_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 471 = sctp_peeloff */
+ { AS(sctp_generic_sendmsg_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 472 = sctp_generic_sendmsg */
+ { AS(sctp_generic_sendmsg_iov_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 473 = sctp_generic_sendmsg_iov */
+ { AS(sctp_generic_recvmsg_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_ABSENT }, /* 474 = sctp_generic_recvmsg */
{ AS(pread_args), (sy_call_t *)sys_pread, AUE_PREAD, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 475 = pread */
{ AS(pwrite_args), (sy_call_t *)sys_pwrite, AUE_PWRITE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 476 = pwrite */
{ AS(mmap_args), (sy_call_t *)sys_mmap, AUE_MMAP, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 477 = mmap */
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index c48378c..c51a876 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -288,11 +288,18 @@ _fdfree(struct filedesc *fdp, int fd, int last)
struct filedescent *fde;
fde = &fdp->fd_ofiles[fd];
+#ifdef CAPABILITIES
+ if (!last)
+ seq_write_begin(&fde->fde_seq);
+#endif
filecaps_free(&fde->fde_caps);
if (last)
return;
- bzero(fde, sizeof(*fde));
+ bzero(fde, fde_change_size);
fdunused(fdp, fd);
+#ifdef CAPABILITIES
+ seq_write_end(&fde->fde_seq);
+#endif
}
static inline void
@@ -883,13 +890,19 @@ do_dup(struct thread *td, int flags, int old, int new,
/*
* Duplicate the source descriptor.
*/
+#ifdef CAPABILITIES
+ seq_write_begin(&newfde->fde_seq);
+#endif
filecaps_free(&newfde->fde_caps);
- *newfde = *oldfde;
+ memcpy(newfde, oldfde, fde_change_size);
filecaps_copy(&oldfde->fde_caps, &newfde->fde_caps);
if ((flags & DUP_CLOEXEC) != 0)
newfde->fde_flags = oldfde->fde_flags | UF_EXCLOSE;
else
newfde->fde_flags = oldfde->fde_flags & ~UF_EXCLOSE;
+#ifdef CAPABILITIES
+ seq_write_end(&newfde->fde_seq);
+#endif
*retval = new;
if (delfp != NULL) {
@@ -1756,6 +1769,9 @@ finstall(struct thread *td, struct file *fp, int *fd, int flags,
}
fhold(fp);
fde = &fdp->fd_ofiles[*fd];
+#ifdef CAPABILITIES
+ seq_write_begin(&fde->fde_seq);
+#endif
fde->fde_file = fp;
if ((flags & O_CLOEXEC) != 0)
fde->fde_flags |= UF_EXCLOSE;
@@ -1763,6 +1779,9 @@ finstall(struct thread *td, struct file *fp, int *fd, int flags,
filecaps_move(fcaps, &fde->fde_caps);
else
filecaps_fill(&fde->fde_caps);
+#ifdef CAPABILITIES
+ seq_write_end(&fde->fde_seq);
+#endif
FILEDESC_XUNLOCK(fdp);
return (0);
}
@@ -2294,6 +2313,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file *fp;
u_int count;
#ifdef CAPABILITIES
+ seq_t seq;
cap_rights_t haverights;
int error;
#endif
@@ -2314,7 +2334,12 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
*/
for (;;) {
#ifdef CAPABILITIES
+ seq = seq_read(fd_seq(fdp, fd));
fde = fdp->fd_ofiles[fd];
+ if (!seq_consistent(fd_seq(fdp, fd), seq)) {
+ cpu_spinwait();
+ continue;
+ }
fp = fde.fde_file;
#else
fp = fdp->fd_ofiles[fd].fde_file;
@@ -2343,7 +2368,11 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
*/
if (atomic_cmpset_acq_int(&fp->f_count, count, count + 1) != 1)
continue;
+#ifdef CAPABILITIES
+ if (seq_consistent_nomb(fd_seq(fdp, fd), seq))
+#else
if (fp == fdp->fd_ofiles[fd].fde_file)
+#endif
break;
fdrop(fp, curthread);
}
@@ -2700,6 +2729,7 @@ int
dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
int openerror, int *indxp)
{
+ struct filedescent *newfde, *oldfde;
struct file *fp;
int error, indx;
@@ -2743,17 +2773,32 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
return (EACCES);
}
fhold(fp);
- fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
- filecaps_copy(&fdp->fd_ofiles[dfd].fde_caps,
- &fdp->fd_ofiles[indx].fde_caps);
+ newfde = &fdp->fd_ofiles[indx];
+ oldfde = &fdp->fd_ofiles[dfd];
+#ifdef CAPABILITIES
+ seq_write_begin(&newfde->fde_seq);
+#endif
+ memcpy(newfde, oldfde, fde_change_size);
+ filecaps_copy(&oldfde->fde_caps, &newfde->fde_caps);
+#ifdef CAPABILITIES
+ seq_write_end(&newfde->fde_seq);
+#endif
break;
case ENXIO:
/*
* Steal away the file pointer from dfd and stuff it into indx.
*/
- fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
- bzero(&fdp->fd_ofiles[dfd], sizeof(fdp->fd_ofiles[dfd]));
+ newfde = &fdp->fd_ofiles[indx];
+ oldfde = &fdp->fd_ofiles[dfd];
+#ifdef CAPABILITIES
+ seq_write_begin(&newfde->fde_seq);
+#endif
+ memcpy(newfde, oldfde, fde_change_size);
+ bzero(oldfde, fde_change_size);
fdunused(fdp, dfd);
+#ifdef CAPABILITIES
+ seq_write_end(&newfde->fde_seq);
+#endif
break;
}
FILEDESC_XUNLOCK(fdp);
@@ -3052,7 +3097,7 @@ export_kinfo_to_sb(struct export_fd_buf *efbuf)
}
efbuf->remainder -= kif->kf_structsize;
}
- return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize));
+ return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize) == 0 ? 0 : ENOMEM);
}
static int
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 7488652..55bffe7 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -569,9 +569,10 @@ filt_timerexpire(void *knx)
if ((kn->kn_flags & EV_ONESHOT) != EV_ONESHOT) {
calloutp = (struct callout *)kn->kn_hook;
- callout_reset_sbt_on(calloutp,
- timer2sbintime(kn->kn_sdata, kn->kn_sfflags), 0,
- filt_timerexpire, kn, PCPU_GET(cpuid), 0);
+ *kn->kn_ptr.p_nexttime += timer2sbintime(kn->kn_sdata,
+ kn->kn_sfflags);
+ callout_reset_sbt_on(calloutp, *kn->kn_ptr.p_nexttime, 0,
+ filt_timerexpire, kn, PCPU_GET(cpuid), C_ABSOLUTE);
}
}
@@ -607,11 +608,13 @@ filt_timerattach(struct knote *kn)
kn->kn_flags |= EV_CLEAR; /* automatically set */
kn->kn_status &= ~KN_DETACHED; /* knlist_add clears it */
+ kn->kn_ptr.p_nexttime = malloc(sizeof(sbintime_t), M_KQUEUE, M_WAITOK);
calloutp = malloc(sizeof(*calloutp), M_KQUEUE, M_WAITOK);
callout_init(calloutp, CALLOUT_MPSAFE);
kn->kn_hook = calloutp;
- callout_reset_sbt_on(calloutp, to, 0,
- filt_timerexpire, kn, PCPU_GET(cpuid), 0);
+ *kn->kn_ptr.p_nexttime = to + sbinuptime();
+ callout_reset_sbt_on(calloutp, *kn->kn_ptr.p_nexttime, 0,
+ filt_timerexpire, kn, PCPU_GET(cpuid), C_ABSOLUTE);
return (0);
}
@@ -625,6 +628,7 @@ filt_timerdetach(struct knote *kn)
calloutp = (struct callout *)kn->kn_hook;
callout_drain(calloutp);
free(calloutp, M_KQUEUE);
+ free(kn->kn_ptr.p_nexttime, M_KQUEUE);
old = atomic_fetch_sub_explicit(&kq_ncallouts, 1, memory_order_relaxed);
KASSERT(old > 0, ("Number of callouts cannot become negative"));
kn->kn_status |= KN_DETACHED; /* knlist_remove sets it */
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 1dbb997..1e4c095 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -265,8 +265,8 @@ exit1(struct thread *td, int rv)
AUDIT_SYSCALL_EXIT(0, td);
#endif
- /* Are we a task leader? */
- if (p == p->p_leader) {
+ /* Are we a task leader with peers? */
+ if (p->p_peers != NULL && p == p->p_leader) {
mtx_lock(&ppeers_lock);
q = p->p_peers;
while (q != NULL) {
@@ -337,15 +337,17 @@ exit1(struct thread *td, int rv)
/*
* Remove ourself from our leader's peer list and wake our leader.
*/
- mtx_lock(&ppeers_lock);
- if (p->p_leader->p_peers) {
- q = p->p_leader;
- while (q->p_peers != p)
- q = q->p_peers;
- q->p_peers = p->p_peers;
- wakeup(p->p_leader);
+ if (p->p_leader->p_peers != NULL) {
+ mtx_lock(&ppeers_lock);
+ if (p->p_leader->p_peers != NULL) {
+ q = p->p_leader;
+ while (q->p_peers != p)
+ q = q->p_peers;
+ q->p_peers = p->p_peers;
+ wakeup(p->p_leader);
+ }
+ mtx_unlock(&ppeers_lock);
}
- mtx_unlock(&ppeers_lock);
vmspace_exit(td);
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 6e9a4e8..d6de611 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
+#include "opt_kstack_usage_prof.h"
#include <sys/param.h>
#include <sys/bus.h>
@@ -1396,6 +1397,10 @@ intr_event_handle(struct intr_event *ie, struct trapframe *frame)
td = curthread;
+#ifdef KSTACK_USAGE_PROF
+ intr_prof_stack_use(td, frame);
+#endif
+
/* An interrupt with no event or handlers is a stray interrupt. */
if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers))
return (EINVAL);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 96510c9..41cd304 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -1208,21 +1208,25 @@ kern_proc_out(struct proc *p, struct sbuf *sb, int flags)
#ifdef COMPAT_FREEBSD32
if ((flags & KERN_PROC_MASK32) != 0) {
freebsd32_kinfo_proc_out(&ki, &ki32);
- error = sbuf_bcat(sb, &ki32, sizeof(ki32));
+ if (sbuf_bcat(sb, &ki32, sizeof(ki32)) != 0)
+ error = ENOMEM;
} else
#endif
- error = sbuf_bcat(sb, &ki, sizeof(ki));
+ if (sbuf_bcat(sb, &ki, sizeof(ki)) != 0)
+ error = ENOMEM;
} else {
FOREACH_THREAD_IN_PROC(p, td) {
fill_kinfo_thread(td, &ki, 1);
#ifdef COMPAT_FREEBSD32
if ((flags & KERN_PROC_MASK32) != 0) {
freebsd32_kinfo_proc_out(&ki, &ki32);
- error = sbuf_bcat(sb, &ki32, sizeof(ki32));
+ if (sbuf_bcat(sb, &ki32, sizeof(ki32)) != 0)
+ error = ENOMEM;
} else
#endif
- error = sbuf_bcat(sb, &ki, sizeof(ki));
- if (error)
+ if (sbuf_bcat(sb, &ki, sizeof(ki)) != 0)
+ error = ENOMEM;
+ if (error != 0)
break;
}
}
@@ -1777,7 +1781,8 @@ proc_getauxv(struct thread *td, struct proc *p, struct sbuf *sb)
else
#endif
size = vsize * sizeof(Elf_Auxinfo);
- error = sbuf_bcat(sb, auxv, size);
+ if (sbuf_bcat(sb, auxv, size) != 0)
+ error = ENOMEM;
free(auxv, M_TEMP);
}
return (error);
@@ -2363,9 +2368,10 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb)
strlen(kve->kve_path) + 1;
kve->kve_structsize = roundup(kve->kve_structsize,
sizeof(uint64_t));
- error = sbuf_bcat(sb, kve, kve->kve_structsize);
+ if (sbuf_bcat(sb, kve, kve->kve_structsize) != 0)
+ error = ENOMEM;
vm_map_lock_read(map);
- if (error)
+ if (error != 0)
break;
if (last_timestamp != map->timestamp) {
vm_map_lookup_entry(map, addr - 1, &tmp_entry);
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 7552363..fd2b7f4 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1884,23 +1884,13 @@ crfree(struct ucred *cr)
}
/*
- * Check to see if this ucred is shared.
- */
-int
-crshared(struct ucred *cr)
-{
-
- return (cr->cr_ref > 1);
-}
-
-/*
* Copy a ucred's contents from a template. Does not block.
*/
void
crcopy(struct ucred *dest, struct ucred *src)
{
- KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
+ KASSERT(dest->cr_ref == 1, ("crcopy of shared ucred"));
bcopy(&src->cr_startcopy, &dest->cr_startcopy,
(unsigned)((caddr_t)&src->cr_endcopy -
(caddr_t)&src->cr_startcopy));
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index 26ebc4e..84fa312 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -1203,88 +1203,4 @@ racct_init(void)
}
SYSINIT(racct, SI_SUB_RACCT, SI_ORDER_FIRST, racct_init, NULL);
-#else /* !RACCT */
-
-int
-racct_add(struct proc *p, int resource, uint64_t amount)
-{
-
- return (0);
-}
-
-void
-racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
-{
-}
-
-void
-racct_add_force(struct proc *p, int resource, uint64_t amount)
-{
-
- return;
-}
-
-int
-racct_set(struct proc *p, int resource, uint64_t amount)
-{
-
- return (0);
-}
-
-void
-racct_set_force(struct proc *p, int resource, uint64_t amount)
-{
-}
-
-void
-racct_sub(struct proc *p, int resource, uint64_t amount)
-{
-}
-
-void
-racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
-{
-}
-
-uint64_t
-racct_get_limit(struct proc *p, int resource)
-{
-
- return (UINT64_MAX);
-}
-
-uint64_t
-racct_get_available(struct proc *p, int resource)
-{
-
- return (UINT64_MAX);
-}
-
-void
-racct_create(struct racct **racctp)
-{
-}
-
-void
-racct_destroy(struct racct **racctp)
-{
-}
-
-int
-racct_proc_fork(struct proc *parent, struct proc *child)
-{
-
- return (0);
-}
-
-void
-racct_proc_fork_done(struct proc *child)
-{
-}
-
-void
-racct_proc_exit(struct proc *p)
-{
-}
-
#endif /* !RACCT */
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 1bb042f..5cdc2ce 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -3214,8 +3214,8 @@ coredump(struct thread *td)
struct flock lf;
struct vattr vattr;
int error, error1, locked;
- struct mount *mp;
char *name; /* name of corefile */
+ void *rl_cookie;
off_t limit;
int compress;
@@ -3248,39 +3248,33 @@ coredump(struct thread *td)
}
PROC_UNLOCK(p);
-restart:
error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td, compress,
&vp, &name);
if (error != 0)
return (error);
- /* Don't dump to non-regular files or files with links. */
+ /*
+ * Don't dump to non-regular files or files with links.
+ * Do not dump into system files.
+ */
if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 ||
- vattr.va_nlink != 1) {
+ vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0) {
VOP_UNLOCK(vp, 0);
error = EFAULT;
goto close;
}
VOP_UNLOCK(vp, 0);
+
+ /* Postpone other writers, including core dumps of other processes. */
+ rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX);
+
lf.l_whence = SEEK_SET;
lf.l_start = 0;
lf.l_len = 0;
lf.l_type = F_WRLCK;
locked = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK) == 0);
- if (vn_start_write(vp, &mp, V_NOWAIT) != 0) {
- lf.l_type = F_UNLCK;
- if (locked)
- VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK);
- if ((error = vn_close(vp, FWRITE, cred, td)) != 0)
- goto out;
- if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
- goto out;
- free(name, M_TEMP);
- goto restart;
- }
-
VATTR_NULL(&vattr);
vattr.va_size = 0;
if (set_core_nodump_flag)
@@ -3288,7 +3282,6 @@ restart:
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
VOP_SETATTR(vp, &vattr, cred);
VOP_UNLOCK(vp, 0);
- vn_finished_write(mp);
PROC_LOCK(p);
p->p_acflag |= ACORE;
PROC_UNLOCK(p);
@@ -3304,11 +3297,11 @@ restart:
lf.l_type = F_UNLCK;
VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK);
}
+ vn_rangelock_unlock(vp, rl_cookie);
close:
error1 = vn_close(vp, FWRITE, cred, td);
if (error == 0)
error = error1;
-out:
#ifdef AUDIT
audit_proc_coredump(td, name, error);
#endif
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index b503633..13822fd 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -163,6 +163,7 @@ struct callout_cpu {
sbintime_t cc_lastscan;
void *cc_cookie;
u_int cc_bucket;
+ char cc_ktr_event_name[20];
};
#define cc_exec_curr cc_exec_entity[0].cc_curr
@@ -201,7 +202,7 @@ struct callout_cpu cc_cpu;
static int timeout_cpu;
-static void callout_cpu_init(struct callout_cpu *cc);
+static void callout_cpu_init(struct callout_cpu *cc, int cpu);
static void softclock_call_cc(struct callout *c, struct callout_cpu *cc,
#ifdef CALLOUT_PROFILING
int *mpcalls, int *lockcalls, int *gcalls,
@@ -302,7 +303,7 @@ callout_callwheel_init(void *dummy)
cc = CC_CPU(timeout_cpu);
cc->cc_callout = malloc(ncallout * sizeof(struct callout),
M_CALLOUT, M_WAITOK);
- callout_cpu_init(cc);
+ callout_cpu_init(cc, timeout_cpu);
}
SYSINIT(callwheel_init, SI_SUB_CPU, SI_ORDER_ANY, callout_callwheel_init, NULL);
@@ -310,7 +311,7 @@ SYSINIT(callwheel_init, SI_SUB_CPU, SI_ORDER_ANY, callout_callwheel_init, NULL);
* Initialize the per-cpu callout structures.
*/
static void
-callout_cpu_init(struct callout_cpu *cc)
+callout_cpu_init(struct callout_cpu *cc, int cpu)
{
struct callout *c;
int i;
@@ -325,6 +326,8 @@ callout_cpu_init(struct callout_cpu *cc)
cc->cc_firstevent = SBT_MAX;
for (i = 0; i < 2; i++)
cc_cce_cleanup(cc, i);
+ snprintf(cc->cc_ktr_event_name, sizeof(cc->cc_ktr_event_name),
+ "callwheel cpu %d", cpu);
if (cc->cc_callout == NULL) /* Only cpu0 handles timeout(9) */
return;
for (i = 0; i < ncallout; i++) {
@@ -396,7 +399,7 @@ start_softclock(void *dummy)
continue;
cc = CC_CPU(cpu);
cc->cc_callout = NULL; /* Only cpu0 handles timeout(9). */
- callout_cpu_init(cc);
+ callout_cpu_init(cc, cpu);
snprintf(name, sizeof(name), "clock (%d)", cpu);
ie = NULL;
if (swi_add(&ie, name, softclock, cc, SWI_CLOCK,
@@ -711,6 +714,8 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc,
CTR3(KTR_CALLOUT, "callout %p func %p arg %p",
c, c_func, c_arg);
}
+ KTR_STATE3(KTR_SCHED, "callout", cc->cc_ktr_event_name, "running",
+ "func:%p", c_func, "arg:%p", c_arg, "direct:%d", direct);
#if defined(DIAGNOSTIC) || defined(CALLOUT_PROFILING)
sbt1 = sbinuptime();
#endif
@@ -733,6 +738,7 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc,
lastfunc = c_func;
}
#endif
+ KTR_STATE0(KTR_SCHED, "callout", cc->cc_ktr_event_name, "idle");
CTR1(KTR_CALLOUT, "callout %p finished", c);
if ((c_flags & CALLOUT_RETURNUNLOCKED) == 0)
class->lc_unlock(c_lock);
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 974c540..31ad45e 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
+#include <sys/cpuset.h>
#include <net/vnet.h>
@@ -3754,6 +3755,25 @@ bus_print_child_footer(device_t dev, device_t child)
/**
* @brief Helper function for implementing BUS_PRINT_CHILD().
*
+ * This function prints out the VM domain for the given device.
+ *
+ * @returns the number of characters printed
+ */
+int
+bus_print_child_domain(device_t dev, device_t child)
+{
+ int domain;
+
+ /* No domain? Don't print anything */
+ if (BUS_GET_DOMAIN(dev, child, &domain) != 0)
+ return (0);
+
+ return (printf(" numa-domain %d", domain));
+}
+
+/**
+ * @brief Helper function for implementing BUS_PRINT_CHILD().
+ *
* This function simply calls bus_print_child_header() followed by
* bus_print_child_footer().
*
@@ -3765,6 +3785,7 @@ bus_generic_print_child(device_t dev, device_t child)
int retval = 0;
retval += bus_print_child_header(dev, child);
+ retval += bus_print_child_domain(dev, child);
retval += bus_print_child_footer(dev, child);
return (retval);
@@ -4179,6 +4200,16 @@ bus_generic_child_present(device_t dev, device_t child)
return (BUS_CHILD_PRESENT(device_get_parent(dev), dev));
}
+int
+bus_generic_get_domain(device_t dev, device_t child, int *domain)
+{
+
+ if (dev->parent)
+ return (BUS_GET_DOMAIN(dev->parent, dev, domain));
+
+ return (ENOENT);
+}
+
/*
* Some convenience functions to make it easier for drivers to use the
* resource-management functions. All these really do is hide the
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index d9f8388..276c34a 100644
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 263318 2014-03-18 21:32:03Z attilio
+ * created from FreeBSD: head/sys/kern/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
const char *syscallnames[] = {
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 71e6273..35c05f0 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -837,14 +837,14 @@
468 AUE_NULL UNIMPL nosys
469 AUE_NULL UNIMPL __getpath_fromfd
470 AUE_NULL UNIMPL __getpath_fromaddr
-471 AUE_NULL STD { int sctp_peeloff(int sd, uint32_t name); }
-472 AUE_NULL STD { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
+471 AUE_NULL NOSTD { int sctp_peeloff(int sd, uint32_t name); }
+472 AUE_NULL NOSTD { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
caddr_t to, __socklen_t tolen, \
struct sctp_sndrcvinfo *sinfo, int flags); }
-473 AUE_NULL STD { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
+473 AUE_NULL NOSTD { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
caddr_t to, __socklen_t tolen, \
struct sctp_sndrcvinfo *sinfo, int flags); }
-474 AUE_NULL STD { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
+474 AUE_NULL NOSTD { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
struct sockaddr * from, __socklen_t *fromlenaddr, \
struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
475 AUE_PREAD STD { ssize_t pread(int fd, void *buf, \
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index e2a0fa3..373fcc3 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -123,9 +123,10 @@ tty_watermarks(struct tty *tp)
}
static int
-tty_drain(struct tty *tp)
+tty_drain(struct tty *tp, int leaving)
{
- int error;
+ size_t bytesused;
+ int error, revokecnt;
if (ttyhook_hashook(tp, getc_inject))
/* buffer is inaccessible */
@@ -134,11 +135,27 @@ tty_drain(struct tty *tp)
while (ttyoutq_bytesused(&tp->t_outq) > 0) {
ttydevsw_outwakeup(tp);
/* Could be handled synchronously. */
- if (ttyoutq_bytesused(&tp->t_outq) == 0)
+ bytesused = ttyoutq_bytesused(&tp->t_outq);
+ if (bytesused == 0)
return (0);
/* Wait for data to be drained. */
- error = tty_wait(tp, &tp->t_outwait);
+ if (leaving) {
+ revokecnt = tp->t_revokecnt;
+ error = tty_timedwait(tp, &tp->t_outwait, hz);
+ switch (error) {
+ case ERESTART:
+ if (revokecnt != tp->t_revokecnt)
+ error = 0;
+ break;
+ case EWOULDBLOCK:
+ if (ttyoutq_bytesused(&tp->t_outq) < bytesused)
+ error = 0;
+ break;
+ }
+ } else
+ error = tty_wait(tp, &tp->t_outwait);
+
if (error)
return (error);
}
@@ -191,10 +208,8 @@ ttydev_leave(struct tty *tp)
/* Drain any output. */
MPASS((tp->t_flags & TF_STOPPED) == 0);
- if (!tty_gone(tp)) {
- while (tty_drain(tp) == ERESTART)
- ;
- }
+ if (!tty_gone(tp))
+ tty_drain(tp, 1);
ttydisc_close(tp);
@@ -1392,14 +1407,14 @@ tty_timedwait(struct tty *tp, struct cv *cv, int hz)
error = cv_timedwait_sig(cv, tp->t_mtx, hz);
- /* Restart the system call when we may have been revoked. */
- if (tp->t_revokecnt != revokecnt)
- return (ERESTART);
-
/* Bail out when the device slipped away. */
if (tty_gone(tp))
return (ENXIO);
+ /* Restart the system call when we may have been revoked. */
+ if (tp->t_revokecnt != revokecnt)
+ return (ERESTART);
+
return (error);
}
@@ -1528,7 +1543,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
/* Set terminal flags through tcsetattr(). */
if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
- error = tty_drain(tp);
+ error = tty_drain(tp, 0);
if (error)
return (error);
if (cmd == TIOCSETAF)
@@ -1707,7 +1722,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
}
case TIOCDRAIN:
/* Drain TTY output. */
- return tty_drain(tp);
+ return tty_drain(tp, 0);
case TIOCCONS:
/* Set terminal as console TTY. */
if (*(int *)data) {
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 43dd56b..6d423ba 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
#include "opt_capsicum.h"
#include "opt_inet.h"
#include "opt_inet6.h"
-#include "opt_sctp.h"
#include "opt_compat.h"
#include "opt_ktrace.h"
@@ -95,13 +94,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <vm/uma.h>
-#if defined(INET) || defined(INET6)
-#ifdef SCTP
-#include <netinet/sctp.h>
-#include <netinet/sctp_peeloff.h>
-#endif /* SCTP */
-#endif /* INET || INET6 */
-
/*
* Flags for accept1() and kern_accept4(), in addition to SOCK_CLOEXEC
* and SOCK_NONBLOCK.
@@ -198,7 +190,7 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, sfstat, CTLTYPE_OPAQUE | CTLFLAG_RW,
* capability rights are present.
* A reference on the file entry is held upon returning.
*/
-static int
+int
getsock_cap(struct filedesc *fdp, int fd, cap_rights_t *rightsp,
struct file **fpp, u_int *fflagp)
{
@@ -3206,484 +3198,3 @@ out:
return (error);
}
-
-/*
- * SCTP syscalls.
- * Functionality only compiled in if SCTP is defined in the kernel Makefile,
- * otherwise all return EOPNOTSUPP.
- * XXX: We should make this loadable one day.
- */
-int
-sys_sctp_peeloff(td, uap)
- struct thread *td;
- struct sctp_peeloff_args /* {
- int sd;
- caddr_t name;
- } */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
- struct file *nfp = NULL;
- struct socket *head, *so;
- cap_rights_t rights;
- u_int fflag;
- int error, fd;
-
- AUDIT_ARG_FD(uap->sd);
- error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
- &head, &fflag);
- if (error != 0)
- goto done2;
- if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
- error = EOPNOTSUPP;
- goto done;
- }
- error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
- if (error != 0)
- goto done;
- /*
- * At this point we know we do have a assoc to pull
- * we proceed to get the fd setup. This may block
- * but that is ok.
- */
-
- error = falloc(td, &nfp, &fd, 0);
- if (error != 0)
- goto done;
- td->td_retval[0] = fd;
-
- CURVNET_SET(head->so_vnet);
- so = sonewconn(head, SS_ISCONNECTED);
- if (so == NULL) {
- error = ENOMEM;
- goto noconnection;
- }
- /*
- * Before changing the flags on the socket, we have to bump the
- * reference count. Otherwise, if the protocol calls sofree(),
- * the socket will be released due to a zero refcount.
- */
- SOCK_LOCK(so);
- soref(so); /* file descriptor reference */
- SOCK_UNLOCK(so);
-
- ACCEPT_LOCK();
-
- TAILQ_REMOVE(&head->so_comp, so, so_list);
- head->so_qlen--;
- so->so_state |= (head->so_state & SS_NBIO);
- so->so_state &= ~SS_NOFDREF;
- so->so_qstate &= ~SQ_COMP;
- so->so_head = NULL;
- ACCEPT_UNLOCK();
- finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
- error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name);
- if (error != 0)
- goto noconnection;
- if (head->so_sigio != NULL)
- fsetown(fgetown(&head->so_sigio), &so->so_sigio);
-
-noconnection:
- /*
- * close the new descriptor, assuming someone hasn't ripped it
- * out from under us.
- */
- if (error != 0)
- fdclose(td->td_proc->p_fd, nfp, fd, td);
-
- /*
- * Release explicitly held references before returning.
- */
- CURVNET_RESTORE();
-done:
- if (nfp != NULL)
- fdrop(nfp, td);
- fputsock(head);
-done2:
- return (error);
-#else /* SCTP */
- return (EOPNOTSUPP);
-#endif /* SCTP */
-}
-
-int
-sys_sctp_generic_sendmsg (td, uap)
- struct thread *td;
- struct sctp_generic_sendmsg_args /* {
- int sd,
- caddr_t msg,
- int mlen,
- caddr_t to,
- __socklen_t tolen,
- struct sctp_sndrcvinfo *sinfo,
- int flags
- } */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
- struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
- struct socket *so;
- struct file *fp = NULL;
- struct sockaddr *to = NULL;
-#ifdef KTRACE
- struct uio *ktruio = NULL;
-#endif
- struct uio auio;
- struct iovec iov[1];
- cap_rights_t rights;
- int error = 0, len;
-
- if (uap->sinfo != NULL) {
- error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
- if (error != 0)
- return (error);
- u_sinfo = &sinfo;
- }
-
- cap_rights_init(&rights, CAP_SEND);
- if (uap->tolen != 0) {
- error = getsockaddr(&to, uap->to, uap->tolen);
- if (error != 0) {
- to = NULL;
- goto sctp_bad2;
- }
- cap_rights_set(&rights, CAP_CONNECT);
- }
-
- AUDIT_ARG_FD(uap->sd);
- error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
- if (error != 0)
- goto sctp_bad;
-#ifdef KTRACE
- if (to && (KTRPOINT(td, KTR_STRUCT)))
- ktrsockaddr(to);
-#endif
-
- iov[0].iov_base = uap->msg;
- iov[0].iov_len = uap->mlen;
-
- so = (struct socket *)fp->f_data;
- if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
- error = EOPNOTSUPP;
- goto sctp_bad;
- }
-#ifdef MAC
- error = mac_socket_check_send(td->td_ucred, so);
- if (error != 0)
- goto sctp_bad;
-#endif /* MAC */
-
- auio.uio_iov = iov;
- auio.uio_iovcnt = 1;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_rw = UIO_WRITE;
- auio.uio_td = td;
- auio.uio_offset = 0; /* XXX */
- auio.uio_resid = 0;
- len = auio.uio_resid = uap->mlen;
- CURVNET_SET(so->so_vnet);
- error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL,
- (struct mbuf *)NULL, uap->flags, u_sinfo, td);
- CURVNET_RESTORE();
- if (error != 0) {
- if (auio.uio_resid != len && (error == ERESTART ||
- error == EINTR || error == EWOULDBLOCK))
- error = 0;
- /* Generation of SIGPIPE can be controlled per socket. */
- if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
- !(uap->flags & MSG_NOSIGNAL)) {
- PROC_LOCK(td->td_proc);
- tdsignal(td, SIGPIPE);
- PROC_UNLOCK(td->td_proc);
- }
- }
- if (error == 0)
- td->td_retval[0] = len - auio.uio_resid;
-#ifdef KTRACE
- if (ktruio != NULL) {
- ktruio->uio_resid = td->td_retval[0];
- ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
- }
-#endif /* KTRACE */
-sctp_bad:
- if (fp != NULL)
- fdrop(fp, td);
-sctp_bad2:
- free(to, M_SONAME);
- return (error);
-#else /* SCTP */
- return (EOPNOTSUPP);
-#endif /* SCTP */
-}
-
-int
-sys_sctp_generic_sendmsg_iov(td, uap)
- struct thread *td;
- struct sctp_generic_sendmsg_iov_args /* {
- int sd,
- struct iovec *iov,
- int iovlen,
- caddr_t to,
- __socklen_t tolen,
- struct sctp_sndrcvinfo *sinfo,
- int flags
- } */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
- struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
- struct socket *so;
- struct file *fp = NULL;
- struct sockaddr *to = NULL;
-#ifdef KTRACE
- struct uio *ktruio = NULL;
-#endif
- struct uio auio;
- struct iovec *iov, *tiov;
- cap_rights_t rights;
- ssize_t len;
- int error, i;
-
- if (uap->sinfo != NULL) {
- error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
- if (error != 0)
- return (error);
- u_sinfo = &sinfo;
- }
- cap_rights_init(&rights, CAP_SEND);
- if (uap->tolen != 0) {
- error = getsockaddr(&to, uap->to, uap->tolen);
- if (error != 0) {
- to = NULL;
- goto sctp_bad2;
- }
- cap_rights_set(&rights, CAP_CONNECT);
- }
-
- AUDIT_ARG_FD(uap->sd);
- error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
- if (error != 0)
- goto sctp_bad1;
-
-#ifdef COMPAT_FREEBSD32
- if (SV_CURPROC_FLAG(SV_ILP32))
- error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
- uap->iovlen, &iov, EMSGSIZE);
- else
-#endif
- error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
- if (error != 0)
- goto sctp_bad1;
-#ifdef KTRACE
- if (to && (KTRPOINT(td, KTR_STRUCT)))
- ktrsockaddr(to);
-#endif
-
- so = (struct socket *)fp->f_data;
- if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
- error = EOPNOTSUPP;
- goto sctp_bad;
- }
-#ifdef MAC
- error = mac_socket_check_send(td->td_ucred, so);
- if (error != 0)
- goto sctp_bad;
-#endif /* MAC */
-
- auio.uio_iov = iov;
- auio.uio_iovcnt = uap->iovlen;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_rw = UIO_WRITE;
- auio.uio_td = td;
- auio.uio_offset = 0; /* XXX */
- auio.uio_resid = 0;
- tiov = iov;
- for (i = 0; i <uap->iovlen; i++, tiov++) {
- if ((auio.uio_resid += tiov->iov_len) < 0) {
- error = EINVAL;
- goto sctp_bad;
- }
- }
- len = auio.uio_resid;
- CURVNET_SET(so->so_vnet);
- error = sctp_lower_sosend(so, to, &auio,
- (struct mbuf *)NULL, (struct mbuf *)NULL,
- uap->flags, u_sinfo, td);
- CURVNET_RESTORE();
- if (error != 0) {
- if (auio.uio_resid != len && (error == ERESTART ||
- error == EINTR || error == EWOULDBLOCK))
- error = 0;
- /* Generation of SIGPIPE can be controlled per socket */
- if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
- !(uap->flags & MSG_NOSIGNAL)) {
- PROC_LOCK(td->td_proc);
- tdsignal(td, SIGPIPE);
- PROC_UNLOCK(td->td_proc);
- }
- }
- if (error == 0)
- td->td_retval[0] = len - auio.uio_resid;
-#ifdef KTRACE
- if (ktruio != NULL) {
- ktruio->uio_resid = td->td_retval[0];
- ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
- }
-#endif /* KTRACE */
-sctp_bad:
- free(iov, M_IOV);
-sctp_bad1:
- if (fp != NULL)
- fdrop(fp, td);
-sctp_bad2:
- free(to, M_SONAME);
- return (error);
-#else /* SCTP */
- return (EOPNOTSUPP);
-#endif /* SCTP */
-}
-
-int
-sys_sctp_generic_recvmsg(td, uap)
- struct thread *td;
- struct sctp_generic_recvmsg_args /* {
- int sd,
- struct iovec *iov,
- int iovlen,
- struct sockaddr *from,
- __socklen_t *fromlenaddr,
- struct sctp_sndrcvinfo *sinfo,
- int *msg_flags
- } */ *uap;
-{
-#if (defined(INET) || defined(INET6)) && defined(SCTP)
- uint8_t sockbufstore[256];
- struct uio auio;
- struct iovec *iov, *tiov;
- struct sctp_sndrcvinfo sinfo;
- struct socket *so;
- struct file *fp = NULL;
- struct sockaddr *fromsa;
- cap_rights_t rights;
-#ifdef KTRACE
- struct uio *ktruio = NULL;
-#endif
- ssize_t len;
- int error, fromlen, i, msg_flags;
-
- AUDIT_ARG_FD(uap->sd);
- error = getsock_cap(td->td_proc->p_fd, uap->sd,
- cap_rights_init(&rights, CAP_RECV), &fp, NULL);
- if (error != 0)
- return (error);
-#ifdef COMPAT_FREEBSD32
- if (SV_CURPROC_FLAG(SV_ILP32))
- error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
- uap->iovlen, &iov, EMSGSIZE);
- else
-#endif
- error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
- if (error != 0)
- goto out1;
-
- so = fp->f_data;
- if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
- error = EOPNOTSUPP;
- goto out;
- }
-#ifdef MAC
- error = mac_socket_check_receive(td->td_ucred, so);
- if (error != 0)
- goto out;
-#endif /* MAC */
-
- if (uap->fromlenaddr != NULL) {
- error = copyin(uap->fromlenaddr, &fromlen, sizeof (fromlen));
- if (error != 0)
- goto out;
- } else {
- fromlen = 0;
- }
- if (uap->msg_flags) {
- error = copyin(uap->msg_flags, &msg_flags, sizeof (int));
- if (error != 0)
- goto out;
- } else {
- msg_flags = 0;
- }
- auio.uio_iov = iov;
- auio.uio_iovcnt = uap->iovlen;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_td = td;
- auio.uio_offset = 0; /* XXX */
- auio.uio_resid = 0;
- tiov = iov;
- for (i = 0; i <uap->iovlen; i++, tiov++) {
- if ((auio.uio_resid += tiov->iov_len) < 0) {
- error = EINVAL;
- goto out;
- }
- }
- len = auio.uio_resid;
- fromsa = (struct sockaddr *)sockbufstore;
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_GENIO))
- ktruio = cloneuio(&auio);
-#endif /* KTRACE */
- memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
- CURVNET_SET(so->so_vnet);
- error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
- fromsa, fromlen, &msg_flags,
- (struct sctp_sndrcvinfo *)&sinfo, 1);
- CURVNET_RESTORE();
- if (error != 0) {
- if (auio.uio_resid != len && (error == ERESTART ||
- error == EINTR || error == EWOULDBLOCK))
- error = 0;
- } else {
- if (uap->sinfo)
- error = copyout(&sinfo, uap->sinfo, sizeof (sinfo));
- }
-#ifdef KTRACE
- if (ktruio != NULL) {
- ktruio->uio_resid = len - auio.uio_resid;
- ktrgenio(uap->sd, UIO_READ, ktruio, error);
- }
-#endif /* KTRACE */
- if (error != 0)
- goto out;
- td->td_retval[0] = len - auio.uio_resid;
-
- if (fromlen && uap->from) {
- len = fromlen;
- if (len <= 0 || fromsa == 0)
- len = 0;
- else {
- len = MIN(len, fromsa->sa_len);
- error = copyout(fromsa, uap->from, (size_t)len);
- if (error != 0)
- goto out;
- }
- error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t));
- if (error != 0)
- goto out;
- }
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_STRUCT))
- ktrsockaddr(fromsa);
-#endif
- if (uap->msg_flags) {
- error = copyout(&msg_flags, uap->msg_flags, sizeof (int));
- if (error != 0)
- goto out;
- }
-out:
- free(iov, M_IOV);
-out1:
- if (fp != NULL)
- fdrop(fp, td);
-
- return (error);
-#else /* SCTP */
- return (EOPNOTSUPP);
-#endif /* SCTP */
-}
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 5a37b0b..19feecd 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -667,6 +667,10 @@ bd_speedup(void)
mtx_unlock(&bdlock);
}
+#ifndef NSWBUF_MIN
+#define NSWBUF_MIN 16
+#endif
+
#ifdef __i386__
#define TRANSIENT_DENOM 5
#else
@@ -778,11 +782,10 @@ kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est)
* swbufs are used as temporary holders for I/O, such as paging I/O.
* We have no less then 16 and no more then 256.
*/
- nswbuf = max(min(nbuf/4, 256), 16);
-#ifdef NSWBUF_MIN
+ nswbuf = min(nbuf / 4, 256);
+ TUNABLE_INT_FETCH("kern.nswbuf", &nswbuf);
if (nswbuf < NSWBUF_MIN)
nswbuf = NSWBUF_MIN;
-#endif
/*
* Reserve space for the buffer cache buffers
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 617bda0..b86ffa7 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -504,13 +504,16 @@ vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset,
error = 0;
if ((ioflg & IO_NODELOCKED) == 0) {
- if (rw == UIO_READ) {
- rl_cookie = vn_rangelock_rlock(vp, offset,
- offset + len);
- } else {
- rl_cookie = vn_rangelock_wlock(vp, offset,
- offset + len);
- }
+ if ((ioflg & IO_RANGELOCKED) == 0) {
+ if (rw == UIO_READ) {
+ rl_cookie = vn_rangelock_rlock(vp, offset,
+ offset + len);
+ } else {
+ rl_cookie = vn_rangelock_wlock(vp, offset,
+ offset + len);
+ }
+ } else
+ rl_cookie = NULL;
mp = NULL;
if (rw == UIO_WRITE) {
if (vp->v_type != VCHR &&
@@ -2234,12 +2237,10 @@ vn_utimes_perm(struct vnode *vp, struct vattr *vap, struct ucred *cred,
{
int error;
- error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred, td);
-
/*
- * From utimes(2):
- * Grant permission if the caller is the owner of the file or
- * the super-user. If the time pointer is null, then write
+ * Grant permission if the caller is the owner of the file, or
+ * the super-user, or has ACL_WRITE_ATTRIBUTES permission on
+ * on the file. If the time pointer is null, then write
* permission on the file is also sufficient.
*
* From NFSv4.1, draft 21, 6.2.1.3.1, Discussion of Mask Attributes:
@@ -2247,6 +2248,7 @@ vn_utimes_perm(struct vnode *vp, struct vattr *vap, struct ucred *cred,
* will be allowed to set the times [..] to the current
* server time.
*/
+ error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred, td);
if (error != 0 && (vap->va_vaflags & VA_UTIMES_NULL) != 0)
error = VOP_ACCESS(vp, VWRITE, cred, td);
return (error);
diff --git a/sys/libkern/explicit_bzero.c b/sys/libkern/explicit_bzero.c
new file mode 100644
index 0000000..2468c55
--- /dev/null
+++ b/sys/libkern/explicit_bzero.c
@@ -0,0 +1,24 @@
+/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
+/*
+ * Public domain.
+ * Written by Matthew Dempsky.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/libkern.h>
+
+__attribute__((weak)) void __explicit_bzero_hook(void *, size_t);
+
+__attribute__((weak)) void
+__explicit_bzero_hook(void *buf, size_t len)
+{
+}
+
+void
+explicit_bzero(void *buf, size_t len)
+{
+ memset(buf, 0, len);
+ __explicit_bzero_hook(buf, len);
+}
diff --git a/sys/mips/include/md_var.h b/sys/mips/include/md_var.h
index 71a78e7..f3778a8 100644
--- a/sys/mips/include/md_var.h
+++ b/sys/mips/include/md_var.h
@@ -79,5 +79,5 @@ void busdma_swi(void);
struct dumperinfo;
void dump_add_page(vm_paddr_t);
void dump_drop_page(vm_paddr_t);
-void minidumpsys(struct dumperinfo *);
+int minidumpsys(struct dumperinfo *);
#endif /* !_MACHINE_MD_VAR_H_ */
diff --git a/sys/mips/mips/dump_machdep.c b/sys/mips/mips/dump_machdep.c
index 26f93ff..fa96e79 100644
--- a/sys/mips/mips/dump_machdep.c
+++ b/sys/mips/mips/dump_machdep.c
@@ -266,10 +266,8 @@ dumpsys(struct dumperinfo *di)
size_t hdrsz;
int error;
- if (do_minidump) {
- minidumpsys(di);
- return (0);
- }
+ if (do_minidump)
+ return (minidumpsys(di));
bzero(&ehdr, sizeof(ehdr));
ehdr.e_ident[EI_MAG0] = ELFMAG0;
diff --git a/sys/mips/mips/minidump_machdep.c b/sys/mips/mips/minidump_machdep.c
index cded3ae..2122e00 100644
--- a/sys/mips/mips/minidump_machdep.c
+++ b/sys/mips/mips/minidump_machdep.c
@@ -153,7 +153,7 @@ write_buffer(struct dumperinfo *di, char *ptr, size_t sz)
return (0);
}
-void
+int
minidumpsys(struct dumperinfo *di)
{
struct minidumphdr mdhdr;
@@ -325,7 +325,7 @@ minidumpsys(struct dumperinfo *di)
/* Signal completion, signoff and exit stage left. */
dump_write(di, NULL, 0, 0, 0);
printf("\nDump complete\n");
- return;
+ return (0);
fail:
if (error < 0)
@@ -337,4 +337,5 @@ fail:
printf("\nDump failed. Partition too small.\n");
else
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+ return (error);
}
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 58ddecc..a510658 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -384,32 +384,7 @@ SUBDIR= \
${_xe} \
xl \
${_zfs} \
- zlib \
-
-.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
-_filemon= filemon
-_vmware= vmware
-.endif
-
-.if ${MACHINE_CPUARCH} != "powerpc" && ${MACHINE_CPUARCH} != "arm" && \
- ${MACHINE_CPUARCH} != "mips"
-_syscons= syscons
-_vpo= vpo
-.endif
-
-.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips"
-# no BUS_SPACE_UNSPECIFIED
-# No barrier instruction support (specific to this driver)
-_sym= sym
-# intr_disable() is a macro, causes problems
-.if ${MK_SOURCELESS_UCODE} != "no"
-_cxgb= cxgb
-.endif
-.endif
-
-.if ${MK_SOURCELESS_UCODE} != "no"
-_cxgbe= cxgbe
-.endif
+ zlib
.if ${MK_CRYPT} != "no" || defined(ALL_MODULES)
.if exists(${.CURDIR}/../opencrypto)
@@ -423,23 +398,20 @@ _random= random
.if (${MK_INET_SUPPORT} != "no" || ${MK_INET6_SUPPORT} != "no") || \
defined(ALL_MODULES)
-_carp= carp
+_carp= carp
_toecore= toecore
.endif
.if ${MK_INET_SUPPORT} != "no" || defined(ALL_MODULES)
_if_gre= if_gre
+_ipdivert= ipdivert
+_ipfw= ipfw
.endif
.if ${MK_IPFILTER} != "no" || defined(ALL_MODULES)
_ipfilter= ipfilter
.endif
-.if ${MK_INET_SUPPORT} != "no" || defined(ALL_MODULES)
-_ipdivert= ipdivert
-_ipfw= ipfw
-.endif
-
.if ${MK_NAND} != "no" || defined(ALL_MODULES)
_nandfs= nandfs
_nandsim= nandsim
@@ -460,6 +432,7 @@ _pfsync= pfsync
.if ${MK_SOURCELESS_UCODE} != "no"
_bce= bce
+_cxgbe= cxgbe
_fatm= fatm
_fxp= fxp
_ispfw= ispfw
@@ -471,31 +444,33 @@ _ti= ti
_txp= txp
.endif
-.if ${MACHINE_CPUARCH} == "i386"
-# XXX some of these can move to the general case when de-i386'ed
-# XXX some of these can move now, but are untested on other architectures.
-_3dfx= 3dfx
-_3dfx_linux= 3dfx_linux
+
+.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips" && \
+ ${MACHINE_CPUARCH} != "powerpc"
+_syscons= syscons
+_vpo= vpo
+.endif
+
+.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips"
+# no BUS_SPACE_UNSPECIFIED
+# No barrier instruction support (specific to this driver)
+_sym= sym
+# intr_disable() is a macro, causes problems
+.if ${MK_SOURCELESS_UCODE} != "no"
+_cxgb= cxgb
+.endif
+.endif
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
_agp= agp
-_aic= aic
_an= an
_aout= aout
-_apm= apm
-_arcnet= arcnet
_bktr= bktr
_bxe= bxe
_cardbus= cardbus
_cbb= cbb
-.if ${MK_SOURCELESS_UCODE} != "no"
-_ce= ce
-.endif
-_coff= coff
-.if ${MK_SOURCELESS_UCODE} != "no"
-_cp= cp
-.endif
_cpuctl= cpuctl
_cpufreq= cpufreq
-_cs= cs
.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
_cyclic= cyclic
.endif
@@ -506,21 +481,15 @@ _drm2= drm2
_dtrace= dtrace
.endif
_ed= ed
-_elink= elink
_em= em
-_ep= ep
_et= et
_exca= exca
_ext2fs= ext2fs
-_fe= fe
-_glxiic= glxiic
-_glxsb= glxsb
+_filemon= filemon
_i2c= i2c
.if ${MK_OFED} != "no" || defined(ALL_MODULES)
_ibcore= ibcore
.endif
-_ibcs2= ibcs2
-_ie= ie
_if_ndis= if_ndis
_igb= igb
_io= io
@@ -530,28 +499,15 @@ _ipoib= ipoib
_linprocfs= linprocfs
_linsysfs= linsysfs
_linux= linux
-_mse= mse
-.if ${MK_OFED} != "no" || defined(ALL_MODULES)
-_mlx4= mlx4
-_mlx4ib= mlx4ib
-_mlxen= mlxen
-_mthca= mthca
-.endif
-_ncr= ncr
-_ncv= ncv
_ndis= ndis
-_nsp= nsp
.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
_opensolaris= opensolaris
.endif
_pccard= pccard
-_pcfclock= pcfclock
-_pst= pst
.if ${MK_OFED} != "no" || defined(ALL_MODULES)
_rdma= rdma
.endif
_safe= safe
-_sbni= sbni
_scsi_low= scsi_low
_si= si
_smbfs= smbfs
@@ -559,42 +515,27 @@ _sound= sound
_speaker= speaker
_splash= splash
_sppp= sppp
-_stg= stg
-_streams= streams
-_svr4= svr4
+_vmware= vmware
_vxge= vxge
_wbwd= wbwd
-_wds= wds
_wi= wi
-_xe= xe
.if ${MK_ZFS} != "no" || defined(ALL_MODULES)
_zfs= zfs
.endif
-.if ${MACHINE} == "i386"
+.if ${MACHINE} != "pc98"
_aac= aac
_aacraid= aacraid
_acpi= acpi
.if ${MK_CRYPT} != "no" || defined(ALL_MODULES)
_aesni= aesni
.endif
-.if ${MK_EISA} != "no"
-_ahb= ahb
-.endif
_amdsbwd= amdsbwd
_amdtemp= amdtemp
_arcmsr= arcmsr
_asmc= asmc
-_asr= asr
-_bios= bios
_ciss= ciss
-_cm= cm
_cmx= cmx
_coretemp= coretemp
-.if ${MK_SOURCELESS_UCODE} != "no"
-_ctau= ctau
-.endif
-_dpt= dpt
-_ex= ex
.if ${MK_SOURCELESS_HOST} != "no"
_hpt27xx= hpt27xx
.endif
@@ -625,171 +566,102 @@ _iwnfw= iwnfw
.endif
_ixgb= ixgb
_ixgbe= ixgbe
+.if ${MK_OFED} != "no" || defined(ALL_MODULES)
+_mlx4= mlx4
+_mlx4ib= mlx4ib
+_mlxen= mlxen
+.endif
_mly= mly
+.if ${MK_OFED} != "no" || defined(ALL_MODULES)
+_mthca= mthca
+.endif
_nfe= nfe
_nvd= nvd
_nvme= nvme
_nvram= nvram
_nxge= nxge
-_tpm= tpm
-_viawd= viawd
-_wl= wl
-_wpi= wpi
-.if ${MK_SOURCELESS_UCODE} != "no"
-_wpifw= wpifw
-.endif
.if ${MK_CRYPT} != "no" || defined(ALL_MODULES)
_padlock= padlock
.endif
_s3= s3
+_tpm= tpm
_twa= twa
_vesa= vesa
+_viawd= viawd
_virtio= virtio
+_wpi= wpi
+.if ${MK_SOURCELESS_UCODE} != "no"
+_wpifw= wpifw
+.endif
_x86bios= x86bios
-.elif ${MACHINE} == "pc98"
-_canbepm= canbepm
-_canbus= canbus
-_ct= ct
-_pmc= pmc
-_snc= snc
.endif
.endif
.if ${MACHINE_CPUARCH} == "amd64"
-_aac= aac
-_aacraid= aacraid
-_aout= aout
-_acpi= acpi
-.if ${MK_CRYPT} != "no" || defined(ALL_MODULES)
-_aesni= aesni
-.endif
-_agp= agp
-_an= an
-_amdsbwd= amdsbwd
-_amdtemp= amdtemp
-_arcmsr= arcmsr
-_asmc= asmc
-_bktr= bktr
-_bxe= bxe
-_cardbus= cardbus
-_cbb= cbb
-_cmx= cmx
-_ciss= ciss
-_coretemp= coretemp
-_cpuctl= cpuctl
-_cpufreq= cpufreq
-.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
-_cyclic= cyclic
-.endif
-_dpms= dpms
-_drm= drm
-_drm2= drm2
-.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
-_dtrace= dtrace
-.endif
-_ed= ed
-_et= et
-_em= em
-_exca= exca
-_ext2fs= ext2fs
-.if ${MK_SOURCELESS_HOST} != "no"
-_hpt27xx= hpt27xx
-.endif
-_hptiop= hptiop
-.if ${MK_SOURCELESS_HOST} != "no"
-_hptmv= hptmv
-_hptnr= hptnr
-_hptrr= hptrr
-.endif
-_hyperv= hyperv
-_i2c= i2c
-.if ${MK_OFED} != "no" || defined(ALL_MODULES)
-_ibcore= ibcore
-.endif
-_ichwd= ichwd
-_ida= ida
-_if_ndis= if_ndis
-_igb= igb
-_iir= iir
-_io= io
-_ipmi= ipmi
-.if ${MK_OFED} != "no" || defined(ALL_MODULES)
-_ipoib= ipoib
-.endif
-_ips= ips
-_ipw= ipw
-.if ${MK_SOURCELESS_UCODE} != "no"
-_ipwfw= ipwfw
-.endif
-_isci= isci
-_iwi= iwi
-.if ${MK_SOURCELESS_UCODE} != "no"
-_iwifw= iwifw
-.endif
-_iwn= iwn
-.if ${MK_SOURCELESS_UCODE} != "no"
-_iwnfw= iwnfw
-.endif
-_ixgb= ixgb
-_ixgbe= ixgbe
_ixl= ixl
_ixlv= ixlv
-_linprocfs= linprocfs
-_linsysfs= linsysfs
-_linux= linux
-_mly= mly
-.if ${MK_OFED} != "no" || defined(ALL_MODULES)
-_mlx4= mlx4
-_mlx4ib= mlx4ib
-_mlxen= mlxen
-_mthca= mthca
-.endif
-_ndis= ndis
-_nfe= nfe
_ntb= ntb
-_nvd= nvd
-_nvme= nvme
-_nvram= nvram
-_nxge= nxge
-.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
-_opensolaris= opensolaris
-.endif
-.if ${MK_CRYPT} != "no" || defined(ALL_MODULES)
-_padlock= padlock
-.endif
-_pccard= pccard
_qlxge= qlxge
_qlxgb= qlxgb
_qlxgbe= qlxgbe
-.if ${MK_OFED} != "no" || defined(ALL_MODULES)
-_rdma= rdma
-.endif
-_s3= s3
-_safe= safe
-_scsi_low= scsi_low
_sfxge= sfxge
-_si= si
-_smbfs= smbfs
-_sound= sound
-_speaker= speaker
-_splash= splash
-_sppp= sppp
-_tpm= tpm
-_twa= twa
-_vesa= vesa
-_viawd= viawd
-_virtio= virtio
_vmm= vmm
-_vxge= vxge
-_x86bios= x86bios
-_wbwd= wbwd
-_wi= wi
-_wpi= wpi
+.endif
+
+.if ${MACHINE_CPUARCH} == "i386"
+# XXX some of these can move to the general case when de-i386'ed
+# XXX some of these can move now, but are untested on other architectures.
+_3dfx= 3dfx
+_3dfx_linux= 3dfx_linux
+_aic= aic
+_apm= apm
+_arcnet= arcnet
.if ${MK_SOURCELESS_UCODE} != "no"
-_wpifw= wpifw
+_ce= ce
.endif
-.if ${MK_ZFS} != "no" || defined(ALL_MODULES)
-_zfs= zfs
+_coff= coff
+.if ${MK_SOURCELESS_UCODE} != "no"
+_cp= cp
+.endif
+_cs= cs
+_elink= elink
+_ep= ep
+_fe= fe
+_glxiic= glxiic
+_glxsb= glxsb
+_ibcs2= ibcs2
+_ie= ie
+_mse= mse
+_ncr= ncr
+_ncv= ncv
+_nsp= nsp
+_pcfclock= pcfclock
+_pst= pst
+_sbni= sbni
+_streams= streams
+_stg= stg
+_svr4= svr4
+_wds= wds
+_xe= xe
+.if ${MACHINE} == "i386"
+.if ${MK_EISA} != "no"
+_ahb= ahb
+.endif
+_asr= asr
+_bios= bios
+_cm= cm
+.if ${MK_SOURCELESS_UCODE} != "no"
+_ctau= ctau
+.endif
+_dpt= dpt
+_ex= ex
+_wl= wl
+.elif ${MACHINE} == "pc98"
+_canbepm= canbepm
+_canbus= canbus
+_ct= ct
+_pmc= pmc
+_snc= snc
.endif
.endif
@@ -816,12 +688,12 @@ _dtrace= dtrace
.endif
_exca= exca
_nvram= powermac_nvram
-_pccard= pccard
-_smbfs= smbfs
-_sound= sound
.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
_opensolaris= opensolaris
.endif
+_pccard= pccard
+_smbfs= smbfs
+_sound= sound
_wi= wi
.endif
@@ -846,6 +718,7 @@ _sound= sound
_zfs= zfs
.endif
.endif
+
.endif
.for reject in ${WITHOUT_MODULES}
diff --git a/sys/modules/ipfw/Makefile b/sys/modules/ipfw/Makefile
index 6920e6a..a0045f3 100644
--- a/sys/modules/ipfw/Makefile
+++ b/sys/modules/ipfw/Makefile
@@ -5,7 +5,8 @@
KMOD= ipfw
SRCS= ip_fw2.c ip_fw_pfil.c
SRCS+= ip_fw_dynamic.c ip_fw_log.c
-SRCS+= ip_fw_sockopt.c ip_fw_table.c
+SRCS+= ip_fw_sockopt.c ip_fw_table.c ip_fw_table_algo.c ip_fw_iface.c
+SRCS+= ip_fw_table_value.c
SRCS+= opt_inet.h opt_inet6.h opt_ipdivert.h opt_ipfw.h opt_ipsec.h
CFLAGS+= -DIPFIREWALL
diff --git a/sys/modules/mrsas/Makefile b/sys/modules/mrsas/Makefile
index 7ff6c81..5976b98 100644
--- a/sys/modules/mrsas/Makefile
+++ b/sys/modules/mrsas/Makefile
@@ -1,14 +1,24 @@
+# Makefile for mrsas driver
# $FreeBSD$
-.PATH: ${.CURDIR}/../../dev/mrsas
+KMOD=mrsas
+.PATH: ${.CURDIR}/../../dev/${KMOD}
-KMOD= mrsas
-SRCS= mrsas.c mrsas_cam.c mrsas_ioctl.c mrsas_fp.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_cam.h opt_scsi.h
+.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64"
+SUBDIR+= mrsas_linux
+.endif
+
+SRCS=mrsas.c mrsas_cam.c mrsas_ioctl.c mrsas_fp.c
+SRCS+= device_if.h bus_if.h pci_if.h opt_cam.h opt_scsi.h
#CFLAGS+= -MRSAS_DEBUG
.include <bsd.kmod.mk>
-#CFLAGS+= -fgnu89-inline
+CFLAGS+= -fgnu89-inline
+
+TARGET_ARCH = ${MACHINE_ARCH}
+.if ${TARGET_ARCH} == "amd64"
+CFLAGS+= -DCOMPAT_FREEBSD32 -D_STANDALONE
+.endif
clean_cscope:
rm -f cscope*
diff --git a/sys/modules/mrsas/mrsas_linux/Makefile b/sys/modules/mrsas/mrsas_linux/Makefile
new file mode 100644
index 0000000..3563892
--- /dev/null
+++ b/sys/modules/mrsas/mrsas_linux/Makefile
@@ -0,0 +1,10 @@
+# Makefile for mrsas driver
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/mrsas
+
+KMOD= mrsas_linux
+SRCS= mrsas_linux.c
+SRCS+= device_if.h bus_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c
index 548e81b..106df68 100644
--- a/sys/net/ieee8023ad_lacp.c
+++ b/sys/net/ieee8023ad_lacp.c
@@ -579,12 +579,13 @@ lacp_port_destroy(struct lagg_port *lgp)
lacp_disable_distributing(lp);
lacp_unselect(lp);
+ LIST_REMOVE(lp, lp_next);
+ LACP_UNLOCK(lsc);
+
/* The address may have already been removed by if_purgemaddrs() */
if (!lgp->lp_detaching)
if_delmulti_ifma(lp->lp_ifma);
- LIST_REMOVE(lp, lp_next);
- LACP_UNLOCK(lsc);
free(lp, M_DEVBUF);
}
@@ -745,7 +746,9 @@ lacp_transit_expire(void *vp)
LACP_LOCK_ASSERT(lsc);
+ CURVNET_SET(lsc->lsc_softc->sc_ifp->if_vnet);
LACP_TRACE(NULL);
+ CURVNET_RESTORE();
lsc->lsc_suppress_distributing = FALSE;
}
diff --git a/sys/net/ieee8023ad_lacp.h b/sys/net/ieee8023ad_lacp.h
index 535cf1f..e814f83 100644
--- a/sys/net/ieee8023ad_lacp.h
+++ b/sys/net/ieee8023ad_lacp.h
@@ -75,6 +75,7 @@
"\007DEFAULTED" \
"\010EXPIRED"
+#ifdef _KERNEL
/*
* IEEE802.3 slow protocols
*
@@ -336,3 +337,4 @@ lacp_isdistributing(struct lagg_port *lgp)
#define LACP_LAGIDSTR_MAX \
(1 + LACP_PARTNERSTR_MAX + 1 + LACP_PARTNERSTR_MAX + 1)
#define LACP_STATESTR_MAX (255) /* XXX */
+#endif /* _KERNEL */
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 252404f..6c169dd 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -226,7 +226,8 @@ struct bridge_softc {
u_char sc_defaddr[6]; /* Default MAC address */
};
-static struct mtx bridge_list_mtx;
+static VNET_DEFINE(struct mtx, bridge_list_mtx);
+#define V_bridge_list_mtx VNET(bridge_list_mtx)
eventhandler_tag bridge_detach_cookie = NULL;
int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
@@ -350,36 +351,64 @@ static struct bstp_cb_ops bridge_ops = {
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW, 0, "Bridge");
-static int pfil_onlyip = 1; /* only pass IP[46] packets when pfil is enabled */
-static int pfil_bridge = 1; /* run pfil hooks on the bridge interface */
-static int pfil_member = 1; /* run pfil hooks on the member interface */
-static int pfil_ipfw = 0; /* layer2 filter with ipfw */
-static int pfil_ipfw_arp = 0; /* layer2 filter with ipfw */
-static int pfil_local_phys = 0; /* run pfil hooks on the physical interface for
- locally destined packets */
-static int log_stp = 0; /* log STP state changes */
-static int bridge_inherit_mac = 0; /* share MAC with first bridge member */
-SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RWTUN,
- &pfil_onlyip, 0, "Only pass IP packets when pfil is enabled");
-SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RWTUN,
- &pfil_ipfw_arp, 0, "Filter ARP packets through IPFW layer2");
-SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RWTUN,
- &pfil_bridge, 0, "Packet filter on the bridge interface");
-SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RWTUN,
- &pfil_member, 0, "Packet filter on the member interface");
-SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys, CTLFLAG_RWTUN,
- &pfil_local_phys, 0,
+/* only pass IP[46] packets when pfil is enabled */
+static VNET_DEFINE(int, pfil_onlyip) = 1;
+#define V_pfil_onlyip VNET(pfil_onlyip)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip,
+ CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_onlyip), 0,
+ "Only pass IP packets when pfil is enabled");
+
+/* run pfil hooks on the bridge interface */
+static VNET_DEFINE(int, pfil_bridge) = 1;
+#define V_pfil_bridge VNET(pfil_bridge)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge,
+ CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_bridge), 0,
+ "Packet filter on the bridge interface");
+
+/* layer2 filter with ipfw */
+static VNET_DEFINE(int, pfil_ipfw);
+#define V_pfil_ipfw VNET(pfil_ipfw)
+
+/* layer2 ARP filter with ipfw */
+static VNET_DEFINE(int, pfil_ipfw_arp);
+#define V_pfil_ipfw_arp VNET(pfil_ipfw_arp)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp,
+ CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_ipfw_arp), 0,
+ "Filter ARP packets through IPFW layer2");
+
+/* run pfil hooks on the member interface */
+static VNET_DEFINE(int, pfil_member) = 1;
+#define V_pfil_member VNET(pfil_member)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member,
+ CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_member), 0,
+ "Packet filter on the member interface");
+
+/* run pfil hooks on the physical interface for locally destined packets */
+static VNET_DEFINE(int, pfil_local_phys);
+#define V_pfil_local_phys VNET(pfil_local_phys)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys,
+ CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_local_phys), 0,
"Packet filter on the physical interface for locally destined packets");
-SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp, CTLFLAG_RWTUN,
- &log_stp, 0, "Log STP state changes");
-SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac, CTLFLAG_RWTUN,
- &bridge_inherit_mac, 0,
+
+/* log STP state changes */
+static VNET_DEFINE(int, log_stp);
+#define V_log_stp VNET(log_stp)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp,
+ CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(log_stp), 0,
+ "Log STP state changes");
+
+/* share MAC with first bridge member */
+static VNET_DEFINE(int, bridge_inherit_mac);
+#define V_bridge_inherit_mac VNET(bridge_inherit_mac)
+SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac,
+ CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(bridge_inherit_mac), 0,
"Inherit MAC address from the first bridge member");
static VNET_DEFINE(int, allow_llz_overlap) = 0;
#define V_allow_llz_overlap VNET(allow_llz_overlap)
-SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap, CTLFLAG_RW,
- &VNET_NAME(allow_llz_overlap), 0, "Allow overlap of link-local scope "
+SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap,
+ CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(allow_llz_overlap), 0,
+ "Allow overlap of link-local scope "
"zones of a bridge interface and the member interfaces");
struct bridge_control {
@@ -477,27 +506,52 @@ const struct bridge_control bridge_control_table[] = {
BC_F_COPYIN|BC_F_SUSER },
};
-const int bridge_control_table_size =
- sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
+const int bridge_control_table_size = nitems(bridge_control_table);
+
+static VNET_DEFINE(LIST_HEAD(, bridge_softc), bridge_list);
+#define V_bridge_list VNET(bridge_list)
+#define BRIDGE_LIST_LOCK_INIT(x) mtx_init(&V_bridge_list_mtx, \
+ "if_bridge list", NULL, MTX_DEF)
+#define BRIDGE_LIST_LOCK_DESTROY(x) mtx_destroy(&V_bridge_list_mtx)
+#define BRIDGE_LIST_LOCK(x) mtx_lock(&V_bridge_list_mtx)
+#define BRIDGE_LIST_UNLOCK(x) mtx_unlock(&V_bridge_list_mtx)
-LIST_HEAD(, bridge_softc) bridge_list;
+static VNET_DEFINE(struct if_clone *, bridge_cloner);
+#define V_bridge_cloner VNET(bridge_cloner)
-static struct if_clone *bridge_cloner;
static const char bridge_name[] = "bridge";
+static void
+vnet_bridge_init(const void *unused __unused)
+{
+
+ BRIDGE_LIST_LOCK_INIT();
+ LIST_INIT(&V_bridge_list);
+ V_bridge_cloner = if_clone_simple(bridge_name,
+ bridge_clone_create, bridge_clone_destroy, 0);
+}
+VNET_SYSINIT(vnet_bridge_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_bridge_init, NULL);
+
+static void
+vnet_bridge_uninit(const void *unused __unused)
+{
+
+ if_clone_detach(V_bridge_cloner);
+ BRIDGE_LIST_LOCK_DESTROY();
+}
+VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_bridge_uninit, NULL);
+
static int
bridge_modevent(module_t mod, int type, void *data)
{
switch (type) {
case MOD_LOAD:
- mtx_init(&bridge_list_mtx, "if_bridge list", NULL, MTX_DEF);
- bridge_cloner = if_clone_simple(bridge_name,
- bridge_clone_create, bridge_clone_destroy, 0);
bridge_rtnode_zone = uma_zcreate("bridge_rtnode",
sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL,
UMA_ALIGN_PTR, 0);
- LIST_INIT(&bridge_list);
bridge_input_p = bridge_input;
bridge_output_p = bridge_output;
bridge_dn_p = bridge_dummynet;
@@ -509,13 +563,11 @@ bridge_modevent(module_t mod, int type, void *data)
case MOD_UNLOAD:
EVENTHANDLER_DEREGISTER(ifnet_departure_event,
bridge_detach_cookie);
- if_clone_detach(bridge_cloner);
uma_zdestroy(bridge_rtnode_zone);
bridge_input_p = NULL;
bridge_output_p = NULL;
bridge_dn_p = NULL;
bridge_linkstate_p = NULL;
- mtx_destroy(&bridge_list_mtx);
break;
default:
return (EOPNOTSUPP);
@@ -538,14 +590,14 @@ MODULE_DEPEND(if_bridge, bridgestp, 1, 1, 1);
static int
sysctl_pfil_ipfw(SYSCTL_HANDLER_ARGS)
{
- int enable = pfil_ipfw;
+ int enable = V_pfil_ipfw;
int error;
error = sysctl_handle_int(oidp, &enable, 0, req);
- enable = (enable) ? 1 : 0;
+ enable &= 1;
- if (enable != pfil_ipfw) {
- pfil_ipfw = enable;
+ if (enable != V_pfil_ipfw) {
+ V_pfil_ipfw = enable;
/*
* Disable pfil so that ipfw doesnt run twice, if the user
@@ -553,17 +605,19 @@ sysctl_pfil_ipfw(SYSCTL_HANDLER_ARGS)
* pfil_member. Also allow non-ip packets as ipfw can filter by
* layer2 type.
*/
- if (pfil_ipfw) {
- pfil_onlyip = 0;
- pfil_bridge = 0;
- pfil_member = 0;
+ if (V_pfil_ipfw) {
+ V_pfil_onlyip = 0;
+ V_pfil_bridge = 0;
+ V_pfil_member = 0;
}
}
return (error);
}
-SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw, CTLTYPE_INT|CTLFLAG_RW,
- &pfil_ipfw, 0, &sysctl_pfil_ipfw, "I", "Layer2 filter with IPFW");
+SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_VNET,
+ &VNET_NAME(pfil_ipfw), 0, &sysctl_pfil_ipfw, "I",
+ "Layer2 filter with IPFW");
/*
* bridge_clone_create:
@@ -632,8 +686,8 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
fb = 1;
retry = 0;
- mtx_lock(&bridge_list_mtx);
- LIST_FOREACH(sc2, &bridge_list, sc_list) {
+ BRIDGE_LIST_LOCK();
+ LIST_FOREACH(sc2, &V_bridge_list, sc_list) {
bifp = sc2->sc_ifp;
if (memcmp(sc->sc_defaddr,
IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0) {
@@ -641,7 +695,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
break;
}
}
- mtx_unlock(&bridge_list_mtx);
+ BRIDGE_LIST_UNLOCK();
} while (retry == 1);
bstp_attach(&sc->sc_stp, &bridge_ops);
@@ -650,9 +704,9 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
ifp->if_baudrate = 0;
ifp->if_type = IFT_BRIDGE;
- mtx_lock(&bridge_list_mtx);
- LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
- mtx_unlock(&bridge_list_mtx);
+ BRIDGE_LIST_LOCK();
+ LIST_INSERT_HEAD(&V_bridge_list, sc, sc_list);
+ BRIDGE_LIST_UNLOCK();
return (0);
}
@@ -684,9 +738,9 @@ bridge_clone_destroy(struct ifnet *ifp)
callout_drain(&sc->sc_brcallout);
- mtx_lock(&bridge_list_mtx);
+ BRIDGE_LIST_LOCK();
LIST_REMOVE(sc, sc_list);
- mtx_unlock(&bridge_list_mtx);
+ BRIDGE_LIST_UNLOCK();
bstp_detach(&sc->sc_stp);
ether_ifdetach(ifp);
@@ -952,7 +1006,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
* the mac address of the bridge to the address of the next member, or
* to its default address if no members are left.
*/
- if (bridge_inherit_mac && sc->sc_ifaddr == ifs) {
+ if (V_bridge_inherit_mac && sc->sc_ifaddr == ifs) {
if (LIST_EMPTY(&sc->sc_iflist)) {
bcopy(sc->sc_defaddr,
IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
@@ -1118,7 +1172,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
* member and the MAC address of the bridge has not been changed from
* the default randomly generated one.
*/
- if (bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) &&
+ if (V_bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) &&
!memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) {
bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
sc->sc_ifaddr = ifs;
@@ -1757,8 +1811,8 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp)
}
/* Check if the interface is a span port */
- mtx_lock(&bridge_list_mtx);
- LIST_FOREACH(sc, &bridge_list, sc_list) {
+ BRIDGE_LIST_LOCK();
+ LIST_FOREACH(sc, &V_bridge_list, sc_list) {
BRIDGE_LOCK(sc);
LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
if (ifp == bif->bif_ifp) {
@@ -1768,7 +1822,7 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp)
BRIDGE_UNLOCK(sc);
}
- mtx_unlock(&bridge_list_mtx);
+ BRIDGE_LIST_UNLOCK();
}
/*
@@ -2350,7 +2404,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
if_inc_counter(iface, IFCOUNTER_IPACKETS, 1); \
if_inc_counter(iface, IFCOUNTER_IBYTES, m->m_pkthdr.len); \
/* Filter on the physical interface. */ \
- if (pfil_local_phys && \
+ if (V_pfil_local_phys && \
(PFIL_HOOKED(&V_inet_pfil_hook) \
OR_PFIL_HOOKED_INET6)) { \
if (bridge_pfil(&m, NULL, ifp, \
@@ -3004,7 +3058,7 @@ bridge_state_change(struct ifnet *ifp, int state)
"discarding"
};
- if (log_stp)
+ if (V_log_stp)
log(LOG_NOTICE, "%s: state changed to %s on %s\n",
sc->sc_ifp->if_xname, stpstates[state], ifp->if_xname);
}
@@ -3032,7 +3086,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
KASSERT(M_WRITABLE(*mp), ("%s: modifying a shared mbuf", __func__));
#endif
- if (pfil_bridge == 0 && pfil_member == 0 && pfil_ipfw == 0)
+ if (V_pfil_bridge == 0 && V_pfil_member == 0 && V_pfil_ipfw == 0)
return (0); /* filtering is disabled */
i = min((*mp)->m_pkthdr.len, max_protohdr);
@@ -3074,7 +3128,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
switch (ether_type) {
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
- if (pfil_ipfw_arp == 0)
+ if (V_pfil_ipfw_arp == 0)
return (0); /* Automatically pass */
break;
@@ -3089,12 +3143,12 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
* packets, these will not be checked by pfil(9) and
* passed unconditionally so the default is to drop.
*/
- if (pfil_onlyip)
+ if (V_pfil_onlyip)
goto bad;
}
/* Run the packet through pfil before stripping link headers */
- if (PFIL_HOOKED(&V_link_pfil_hook) && pfil_ipfw != 0 &&
+ if (PFIL_HOOKED(&V_link_pfil_hook) && V_pfil_ipfw != 0 &&
dir == PFIL_OUT && ifp != NULL) {
error = pfil_run_hooks(&V_link_pfil_hook, mp, ifp, dir, NULL);
@@ -3147,21 +3201,21 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
* Keep the order:
* in_if -> bridge_if -> out_if
*/
- if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
+ if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL)
error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
dir, NULL);
if (*mp == NULL || error != 0) /* filter may consume */
break;
- if (pfil_member && ifp != NULL)
+ if (V_pfil_member && ifp != NULL)
error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp,
dir, NULL);
if (*mp == NULL || error != 0) /* filter may consume */
break;
- if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
+ if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL)
error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
dir, NULL);
@@ -3169,7 +3223,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
break;
/* check if we need to fragment the packet */
- if (pfil_member && ifp != NULL && dir == PFIL_OUT) {
+ if (V_pfil_member && ifp != NULL && dir == PFIL_OUT) {
i = (*mp)->m_pkthdr.len;
if (i > ifp->if_mtu) {
error = bridge_fragment(ifp, *mp, &eh2, snap,
@@ -3199,21 +3253,21 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
break;
#ifdef INET6
case ETHERTYPE_IPV6:
- if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
+ if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL)
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
dir, NULL);
if (*mp == NULL || error != 0) /* filter may consume */
break;
- if (pfil_member && ifp != NULL)
+ if (V_pfil_member && ifp != NULL)
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, ifp,
dir, NULL);
if (*mp == NULL || error != 0) /* filter may consume */
break;
- if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
+ if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL)
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
dir, NULL);
break;
diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c
index 4cce484..de36886 100644
--- a/sys/net/if_disc.c
+++ b/sys/net/if_disc.c
@@ -50,6 +50,7 @@
#include <net/if_types.h>
#include <net/route.h>
#include <net/bpf.h>
+#include <net/vnet.h>
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -74,7 +75,8 @@ static void disc_clone_destroy(struct ifnet *);
static const char discname[] = "disc";
static MALLOC_DEFINE(M_DISC, discname, "Discard interface");
-static struct if_clone *disc_cloner;
+static VNET_DEFINE(struct if_clone *, disc_cloner);
+#define V_disc_cloner VNET(disc_cloner)
static int
disc_clone_create(struct if_clone *ifc, int unit, caddr_t params)
@@ -129,17 +131,32 @@ disc_clone_destroy(struct ifnet *ifp)
free(sc, M_DISC);
}
+static void
+vnet_disc_init(const void *unused __unused)
+{
+
+ V_disc_cloner = if_clone_simple(discname, disc_clone_create,
+ disc_clone_destroy, 0);
+}
+VNET_SYSINIT(vnet_disc_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_disc_init, NULL);
+
+static void
+vnet_disc_uninit(const void *unused __unused)
+{
+
+ if_clone_detach(V_disc_cloner);
+}
+VNET_SYSUNINIT(vnet_disc_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_disc_uninit, NULL);
+
static int
disc_modevent(module_t mod, int type, void *data)
{
switch (type) {
case MOD_LOAD:
- disc_cloner = if_clone_simple(discname, disc_clone_create,
- disc_clone_destroy, 0);
- break;
case MOD_UNLOAD:
- if_clone_detach(disc_cloner);
break;
default:
return (EOPNOTSUPP);
@@ -185,6 +202,7 @@ discoutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
static void
discrtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
{
+
RT_LOCK_ASSERT(rt);
rt->rt_mtu = DSMTU;
}
@@ -200,7 +218,6 @@ discioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
int error = 0;
switch (cmd) {
-
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
ifa = (struct ifaddr *)data;
@@ -210,7 +227,6 @@ discioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* Everything else is done at a higher level.
*/
break;
-
case SIOCADDMULTI:
case SIOCDELMULTI:
if (ifr == 0) {
@@ -218,7 +234,6 @@ discioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
switch (ifr->ifr_addr.sa_family) {
-
#ifdef INET
case AF_INET:
break;
@@ -227,17 +242,14 @@ discioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case AF_INET6:
break;
#endif
-
default:
error = EAFNOSUPPORT;
break;
}
break;
-
case SIOCSIFMTU:
ifp->if_mtu = ifr->ifr_mtu;
break;
-
default:
error = EINVAL;
}
diff --git a/sys/net/if_edsc.c b/sys/net/if_edsc.c
index b75f134..a58cc44 100644
--- a/sys/net/if_edsc.c
+++ b/sys/net/if_edsc.c
@@ -51,6 +51,7 @@
#include <net/if_clone.h> /* network interface cloning */
#include <net/if_types.h> /* IFT_ETHER and friends */
#include <net/if_var.h> /* kernel-only part of ifnet(9) */
+#include <net/vnet.h>
static const char edscname[] = "edsc";
@@ -69,7 +70,8 @@ struct edsc_softc {
/*
* Attach to the interface cloning framework.
*/
-static struct if_clone *edsc_cloner;
+static VNET_DEFINE(struct if_clone *, edsc_cloner);
+#define V_edsc_cloner VNET(edsc_cloner)
static int edsc_clone_create(struct if_clone *, int, caddr_t);
static void edsc_clone_destroy(struct ifnet *);
@@ -307,6 +309,36 @@ edsc_start(struct ifnet *ifp)
*/
}
+static void
+vnet_edsc_init(const void *unused __unused)
+{
+
+ /*
+ * Connect to the network interface cloning framework.
+ * The last argument is the number of units to be created
+ * from the outset. It's also the minimum number of units
+ * allowed. We don't want any units created as soon as the
+ * driver is loaded.
+ */
+ V_edsc_cloner = if_clone_simple(edscname, edsc_clone_create,
+ edsc_clone_destroy, 0);
+}
+VNET_SYSINIT(vnet_edsc_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_edsc_init, NULL);
+
+static void
+vnet_edsc_uninit(const void *unused __unused)
+{
+
+ /*
+ * Disconnect from the cloning framework.
+ * Existing interfaces will be disposed of properly.
+ */
+ if_clone_detach(V_edsc_cloner);
+}
+VNET_SYSUNINIT(vnet_edsc_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_edsc_uninit, NULL);
+
/*
* This function provides handlers for module events, namely load and unload.
*/
@@ -316,25 +348,8 @@ edsc_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
- /*
- * Connect to the network interface cloning framework.
- * The last argument is the number of units to be created
- * from the outset. It's also the minimum number of units
- * allowed. We don't want any units created as soon as the
- * driver is loaded.
- */
- edsc_cloner = if_clone_simple(edscname, edsc_clone_create,
- edsc_clone_destroy, 0);
- break;
-
case MOD_UNLOAD:
- /*
- * Disconnect from the cloning framework.
- * Existing interfaces will be disposed of properly.
- */
- if_clone_detach(edsc_cloner);
break;
-
default:
/*
* There are other event types, but we don't handle them.
diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c
index fc78769..b43b7d2 100644
--- a/sys/net/if_enc.c
+++ b/sys/net/if_enc.c
@@ -230,6 +230,7 @@ ipsec_filter(struct mbuf **mp, int dir, int flags)
{
int error, i;
struct ip *ip;
+ struct ifnet *rcvif;
KASSERT(encif != NULL, ("%s: encif is null", __func__));
KASSERT(flags & (ENC_IN|ENC_OUT),
@@ -268,6 +269,8 @@ ipsec_filter(struct mbuf **mp, int dir, int flags)
}
error = 0;
+ rcvif = (*mp)->m_pkthdr.rcvif;
+ (*mp)->m_pkthdr.rcvif = encif;
ip = mtod(*mp, struct ip *);
switch (ip->ip_v) {
#ifdef INET
@@ -298,6 +301,7 @@ ipsec_filter(struct mbuf **mp, int dir, int flags)
if (error != 0)
goto bad;
+ (*mp)->m_pkthdr.rcvif = rcvif;
return (error);
bad:
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index f4cc3d8..5ae9ed3 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -547,6 +547,7 @@ gif_input(struct mbuf *m, int af, struct ifnet *ifp)
}
sc = ifp->if_softc;
m->m_pkthdr.rcvif = ifp;
+ m_clrprotoflags(m);
#ifdef MAC
mac_ifnet_create_mbuf(ifp, m);
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 67895de..7f7e4b5 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -569,15 +569,15 @@ lagg_clone_destroy(struct ifnet *ifp)
static void
lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr)
{
- struct ifnet *ifp = sc->sc_ifp;
+ struct lagg_port lp;
- if (memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0)
- return;
+ LAGG_WLOCK_ASSERT(sc);
+
+ bzero(&lp, sizeof(lp));
+ lp.lp_ifp = sc->sc_ifp;
+ lp.lp_softc = sc;
- bcopy(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
- /* Let the protocol know the MAC has changed */
- lagg_proto_lladdr(sc);
- EVENTHANDLER_INVOKE(iflladdr_event, ifp);
+ lagg_port_lladdr(&lp, lladdr);
}
static void
@@ -648,6 +648,7 @@ lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr)
/* Update the lladdr even if pending, it may have changed */
llq->llq_ifp = ifp;
+ llq->llq_primary = (sc->sc_primary->lp_ifp == ifp) ? 1 : 0;
bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN);
if (!pending)
@@ -680,14 +681,35 @@ lagg_port_setlladdr(void *arg, int pending)
for (llq = head; llq != NULL; llq = head) {
ifp = llq->llq_ifp;
- /* Set the link layer address */
CURVNET_SET(ifp->if_vnet);
- error = if_setlladdr(ifp, llq->llq_lladdr, ETHER_ADDR_LEN);
+ if (llq->llq_primary == 0) {
+ /*
+ * Set the link layer address on the laggport interface.
+ * if_setlladdr() triggers gratuitous ARPs for INET.
+ */
+ error = if_setlladdr(ifp, llq->llq_lladdr,
+ ETHER_ADDR_LEN);
+ if (error)
+ printf("%s: setlladdr failed on %s\n", __func__,
+ ifp->if_xname);
+ } else {
+ /*
+ * Set the link layer address on the lagg interface.
+ * lagg_proto_lladdr() notifies the MAC change to
+ * the aggregation protocol. iflladdr_event handler
+ * may trigger gratuitous ARPs for INET.
+ */
+ if (memcmp(llq->llq_lladdr, IF_LLADDR(ifp),
+ ETHER_ADDR_LEN) != 0) {
+ bcopy(llq->llq_lladdr, IF_LLADDR(ifp),
+ ETHER_ADDR_LEN);
+ LAGG_WLOCK(sc);
+ lagg_proto_lladdr(sc);
+ LAGG_WUNLOCK(sc);
+ EVENTHANDLER_INVOKE(iflladdr_event, ifp);
+ }
+ }
CURVNET_RESTORE();
- if (error)
- printf("%s: setlladdr failed on %s\n", __func__,
- ifp->if_xname);
-
head = SLIST_NEXT(llq, llq_entries);
free(llq, M_DEVBUF);
}
@@ -1639,7 +1661,7 @@ lagg_input(struct ifnet *ifp, struct mbuf *m)
ETHER_BPF_MTAP(scifp, m);
- m = lagg_proto_input(sc, lp, m);
+ m = (lp->lp_detaching == 0) ? lagg_proto_input(sc, lp, m) : NULL;
if (m != NULL) {
if (scifp->if_flags & IFF_MONITOR) {
diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h
index bbb3497..e86ed06 100644
--- a/sys/net/if_lagg.h
+++ b/sys/net/if_lagg.h
@@ -159,6 +159,9 @@ struct lagg_reqopts {
#define SIOCGLAGGOPTS _IOWR('i', 152, struct lagg_reqopts)
#define SIOCSLAGGOPTS _IOW('i', 153, struct lagg_reqopts)
+#define LAGG_OPT_BITS "\020\001USE_FLOWID\005LACP_STRICT" \
+ "\006LACP_TXTEST\007LACP_RXTEST"
+
#ifdef _KERNEL
/*
@@ -203,6 +206,7 @@ struct lagg_mc {
struct lagg_llq {
struct ifnet *llq_ifp;
uint8_t llq_lladdr[ETHER_ADDR_LEN];
+ uint8_t llq_primary;
SLIST_ENTRY(lagg_llq) llq_entries;
};
diff --git a/sys/netgraph/ng_ipfw.c b/sys/netgraph/ng_ipfw.c
index 7863a67..092a041 100644
--- a/sys/netgraph/ng_ipfw.c
+++ b/sys/netgraph/ng_ipfw.c
@@ -90,7 +90,7 @@ static struct ng_type ng_ipfw_typestruct = {
.disconnect = ng_ipfw_disconnect,
};
NETGRAPH_INIT(ipfw, &ng_ipfw_typestruct);
-MODULE_DEPEND(ng_ipfw, ipfw, 2, 2, 2);
+MODULE_DEPEND(ng_ipfw, ipfw, 3, 3, 3);
/* Information we store for each hook */
struct ng_ipfw_hook_priv {
diff --git a/sys/netinet/ip6.h b/sys/netinet/ip6.h
index 8f49841..ff87057 100644
--- a/sys/netinet/ip6.h
+++ b/sys/netinet/ip6.h
@@ -277,12 +277,6 @@ do { \
(((m) = m_pullup((m), (off) + (hlen))) == NULL)) { \
IP6STAT_INC(ip6s_exthdrtoolong); \
return ret; \
- } else if ((m)->m_flags & M_EXT) { \
- if ((m)->m_len < (off) + (hlen)) { \
- IP6STAT_INC(ip6s_exthdrtoolong); \
- m_freem(m); \
- return ret; \
- } \
} else { \
if ((m)->m_len < (off) + (hlen)) { \
IP6STAT_INC(ip6s_exthdrtoolong); \
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index dae8cc0..ed61b4f 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -36,6 +36,9 @@
*/
#define IPFW_DEFAULT_RULE 65535
+#define RESVD_SET 31 /*set for default and persistent rules*/
+#define IPFW_MAX_SETS 32 /* Number of sets supported by ipfw*/
+
/*
* Default number of ipfw tables.
*/
@@ -44,17 +47,17 @@
/*
* Most commands (queue, pipe, tag, untag, limit...) can have a 16-bit
- * argument between 1 and 65534. The value 0 is unused, the value
- * 65535 (IP_FW_TABLEARG) is used to represent 'tablearg', i.e. the
- * can be 1..65534, or 65535 to indicate the use of a 'tablearg'
+ * argument between 1 and 65534. The value 0 (IP_FW_TARG) is used
+ * to represent 'tablearg' value, e.g. indicate the use of a 'tablearg'
* result of the most recent table() lookup.
* Note that 16bit is only a historical limit, resulting from
* the use of a 16-bit fields for that value. In reality, we can have
- * 2^32 pipes, queues, tag values and so on, and use 0 as a tablearg.
+ * 2^32 pipes, queues, tag values and so on.
*/
#define IPFW_ARG_MIN 1
#define IPFW_ARG_MAX 65534
-#define IP_FW_TABLEARG 65535 /* XXX should use 0 */
+#define IP_FW_TABLEARG 65535 /* Compat value for old clients */
+#define IP_FW_TARG 0 /* Current tablearg value */
/*
* Number of entries in the call stack of the call/return commands.
@@ -65,15 +68,43 @@
/* IP_FW3 header/opcodes */
typedef struct _ip_fw3_opheader {
uint16_t opcode; /* Operation opcode */
- uint16_t reserved[3]; /* Align to 64-bit boundary */
+ uint16_t version; /* Opcode version */
+ uint16_t reserved[2]; /* Align to 64-bit boundary */
} ip_fw3_opheader;
-
-/* IPFW extented tables support */
+/* IP_FW3 opcodes */
#define IP_FW_TABLE_XADD 86 /* add entry */
#define IP_FW_TABLE_XDEL 87 /* delete entry */
-#define IP_FW_TABLE_XGETSIZE 88 /* get table size */
+#define IP_FW_TABLE_XGETSIZE 88 /* get table size (deprecated) */
#define IP_FW_TABLE_XLIST 89 /* list table contents */
+#define IP_FW_TABLE_XDESTROY 90 /* destroy table */
+#define IP_FW_TABLES_XLIST 92 /* list all tables */
+#define IP_FW_TABLE_XINFO 93 /* request info for one table */
+#define IP_FW_TABLE_XFLUSH 94 /* flush table data */
+#define IP_FW_TABLE_XCREATE 95 /* create new table */
+#define IP_FW_TABLE_XMODIFY 96 /* modify existing table */
+#define IP_FW_XGET 97 /* Retrieve configuration */
+#define IP_FW_XADD 98 /* add rule */
+#define IP_FW_XDEL 99 /* del rule */
+#define IP_FW_XMOVE 100 /* move rules to different set */
+#define IP_FW_XZERO 101 /* clear accounting */
+#define IP_FW_XRESETLOG 102 /* zero rules logs */
+#define IP_FW_SET_SWAP 103 /* Swap between 2 sets */
+#define IP_FW_SET_MOVE 104 /* Move one set to another one */
+#define IP_FW_SET_ENABLE 105 /* Enable/disable sets */
+#define IP_FW_TABLE_XFIND 106 /* finds an entry */
+#define IP_FW_XIFLIST 107 /* list tracked interfaces */
+#define IP_FW_TABLES_ALIST 108 /* list table algorithms */
+#define IP_FW_TABLE_XSWAP 109 /* swap two tables */
+#define IP_FW_TABLE_VLIST 110 /* dump table value hash */
+
+#define IP_FW_NAT44_XCONFIG 111 /* Create/modify NAT44 instance */
+#define IP_FW_NAT44_DESTROY 112 /* Destroys NAT44 instance */
+#define IP_FW_NAT44_XGETCONFIG 113 /* Get NAT44 instance config */
+#define IP_FW_NAT44_LIST_NAT 114 /* List all NAT44 instances */
+#define IP_FW_NAT44_XGETLOG 115 /* Get log from NAT44 instance */
+
+#define IP_FW_DUMP_SOPTCODES 116 /* Dump available sopts/versions */
/*
* The kernel representation of ipfw rules is made of a list of
@@ -220,6 +251,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_DSCP, /* 2 u32 = DSCP mask */
O_SETDSCP, /* arg1=DSCP value */
+ O_IP_FLOW_LOOKUP, /* arg1=table number, u32=value */
O_LAST_OPCODE /* not an opcode! */
};
@@ -341,6 +373,7 @@ typedef struct _ipfw_insn_if {
union {
struct in_addr ip;
int glob;
+ uint16_t kidx;
} p;
char name[IFNAMSIZ];
} ipfw_insn_if;
@@ -377,6 +410,8 @@ typedef struct _ipfw_insn_log {
u_int32_t log_left; /* how many left to log */
} ipfw_insn_log;
+/* Legacy NAT structures, compat only */
+#ifndef _KERNEL
/*
* Data structures required by both ipfw(8) and ipfw(4) but not part of the
* management API are protected by IPFW_INTERNAL.
@@ -438,6 +473,44 @@ struct cfg_nat {
#define SOF_REDIR sizeof(struct cfg_redir)
#define SOF_SPOOL sizeof(struct cfg_spool)
+#endif /* ifndef _KERNEL */
+
+
+struct nat44_cfg_spool {
+ struct in_addr addr;
+ uint16_t port;
+ uint16_t spare;
+};
+#define NAT44_REDIR_ADDR 0x01
+#define NAT44_REDIR_PORT 0x02
+#define NAT44_REDIR_PROTO 0x04
+
+/* Nat redirect configuration. */
+struct nat44_cfg_redir {
+ struct in_addr laddr; /* local ip address */
+ struct in_addr paddr; /* public ip address */
+ struct in_addr raddr; /* remote ip address */
+ uint16_t lport; /* local port */
+ uint16_t pport; /* public port */
+ uint16_t rport; /* remote port */
+ uint16_t pport_cnt; /* number of public ports */
+ uint16_t rport_cnt; /* number of remote ports */
+ uint16_t mode; /* type of redirect mode */
+ uint16_t spool_cnt; /* num of entry in spool chain */
+ uint16_t spare;
+ uint32_t proto; /* protocol: tcp/udp */
+};
+
+/* Nat configuration data struct. */
+struct nat44_cfg_nat {
+ char name[64]; /* nat name */
+ char if_name[64]; /* interface name */
+ uint32_t size; /* structure size incl. redirs */
+ struct in_addr ip; /* nat IPv4 address */
+ uint32_t mode; /* aliasing mode */
+ uint32_t redir_cnt; /* number of entry in spool chain */
+};
+
/* Nat command. */
typedef struct _ipfw_insn_nat {
ipfw_insn o;
@@ -471,15 +544,17 @@ typedef struct _ipfw_insn_icmp6 {
/*
* Here we have the structure representing an ipfw rule.
*
- * It starts with a general area (with link fields and counters)
- * followed by an array of one or more instructions, which the code
- * accesses as an array of 32-bit values.
- *
- * Given a rule pointer r:
+ * Layout:
+ * struct ip_fw_rule
+ * [ counter block, size = rule->cntr_len ]
+ * [ one or more instructions, size = rule->cmd_len * 4 ]
*
- * r->cmd is the start of the first instruction.
- * ACTION_PTR(r) is the start of the first action (things to do
- * once a rule matched).
+ * It starts with a general area (with link fields).
+ * Counter block may be next (if rule->cntr_len > 0),
+ * followed by an array of one or more instructions, which the code
+ * accesses as an array of 32-bit values. rule->cmd_len represents
+ * the total instructions legth in u32 worrd, while act_ofs represents
+ * rule action offset in u32 words.
*
* When assembling instruction, remember the following:
*
@@ -490,11 +565,41 @@ typedef struct _ipfw_insn_icmp6 {
* + if a rule has an "altq" option, it comes after "log"
* + if a rule has an O_TAG option, it comes after "log" and "altq"
*
- * NOTE: we use a simple linked list of rules because we never need
- * to delete a rule without scanning the list. We do not use
- * queue(3) macros for portability and readability.
+ *
+ * All structures (excluding instructions) are u64-aligned.
+ * Please keep this.
*/
+struct ip_fw_rule {
+ uint16_t act_ofs; /* offset of action in 32-bit units */
+ uint16_t cmd_len; /* # of 32-bit words in cmd */
+ uint16_t spare;
+ uint8_t set; /* rule set (0..31) */
+ uint8_t flags; /* rule flags */
+ uint32_t rulenum; /* rule number */
+ uint32_t id; /* rule id */
+
+ ipfw_insn cmd[1]; /* storage for commands */
+};
+#define IPFW_RULE_NOOPT 0x01 /* Has no options in body */
+
+/* Unaligned version */
+
+/* Base ipfw rule counter block. */
+struct ip_fw_bcounter {
+ uint16_t size; /* Size of counter block, bytes */
+ uint8_t flags; /* flags for given block */
+ uint8_t spare;
+ uint32_t timestamp; /* tv_sec of last match */
+ uint64_t pcnt; /* Packet counter */
+ uint64_t bcnt; /* Byte counter */
+};
+
+
+#ifndef _KERNEL
+/*
+ * Legacy rule format
+ */
struct ip_fw {
struct ip_fw *x_next; /* linked list of rules */
struct ip_fw *next_rule; /* ptr to next [skipto] rule */
@@ -503,8 +608,7 @@ struct ip_fw {
uint16_t act_ofs; /* offset of action in 32-bit units */
uint16_t cmd_len; /* # of 32-bit words in cmd */
uint16_t rulenum; /* rule number */
- uint8_t set; /* rule set (0..31) */
-#define RESVD_SET 31 /* set for default and persistent rules */
+ uint8_t set; /* rule set (0..31) */
uint8_t _pad; /* padding */
uint32_t id; /* rule id */
@@ -515,12 +619,13 @@ struct ip_fw {
ipfw_insn cmd[1]; /* storage for commands */
};
+#endif
#define ACTION_PTR(rule) \
(ipfw_insn *)( (u_int32_t *)((rule)->cmd) + ((rule)->act_ofs) )
-#define RULESIZE(rule) (sizeof(struct ip_fw) + \
- ((struct ip_fw *)(rule))->cmd_len * 4 - 4)
+#define RULESIZE(rule) (sizeof(*(rule)) + (rule)->cmd_len * 4 - 4)
+
#if 1 // should be moved to in.h
/*
@@ -598,9 +703,27 @@ struct _ipfw_dyn_rule {
* These are used for lookup tables.
*/
-#define IPFW_TABLE_CIDR 1 /* Table for holding IPv4/IPv6 prefixes */
+#define IPFW_TABLE_ADDR 1 /* Table for holding IPv4/IPv6 prefixes */
#define IPFW_TABLE_INTERFACE 2 /* Table for holding interface names */
-#define IPFW_TABLE_MAXTYPE 2 /* Maximum valid number */
+#define IPFW_TABLE_NUMBER 3 /* Table for holding ports/uid/gid/etc */
+#define IPFW_TABLE_FLOW 4 /* Table for holding flow data */
+#define IPFW_TABLE_MAXTYPE 4 /* Maximum valid number */
+
+#define IPFW_TABLE_CIDR IPFW_TABLE_ADDR /* compat */
+
+/* Value types */
+#define IPFW_VTYPE_LEGACY 0xFFFFFFFF /* All data is filled in */
+#define IPFW_VTYPE_SKIPTO 0x00000001 /* skipto/call/callreturn */
+#define IPFW_VTYPE_PIPE 0x00000002 /* pipe/queue */
+#define IPFW_VTYPE_FIB 0x00000004 /* setfib */
+#define IPFW_VTYPE_NAT 0x00000008 /* nat */
+#define IPFW_VTYPE_DSCP 0x00000010 /* dscp */
+#define IPFW_VTYPE_TAG 0x00000020 /* tag/untag */
+#define IPFW_VTYPE_DIVERT 0x00000040 /* divert/tee */
+#define IPFW_VTYPE_NETGRAPH 0x00000080 /* netgraph/ngtee */
+#define IPFW_VTYPE_LIMIT 0x00000100 /* IPv6 nexthop */
+#define IPFW_VTYPE_NH4 0x00000200 /* IPv4 nexthop */
+#define IPFW_VTYPE_NH6 0x00000400 /* IPv6 nexthop */
typedef struct _ipfw_table_entry {
in_addr_t addr; /* network address */
@@ -632,7 +755,7 @@ typedef struct _ipfw_table {
} ipfw_table;
typedef struct _ipfw_xtable {
- ip_fw3_opheader opheader; /* eXtended tables are controlled via IP_FW3 */
+ ip_fw3_opheader opheader; /* IP_FW3 opcode */
uint32_t size; /* size of entries in bytes */
uint32_t cnt; /* # of entries */
uint16_t tbl; /* table number */
@@ -640,4 +763,242 @@ typedef struct _ipfw_xtable {
ipfw_table_xentry xent[0]; /* entries */
} ipfw_xtable;
+typedef struct _ipfw_obj_tlv {
+ uint16_t type; /* TLV type */
+ uint16_t flags; /* TLV-specific flags */
+ uint32_t length; /* Total length, aligned to u64 */
+} ipfw_obj_tlv;
+#define IPFW_TLV_TBL_NAME 1
+#define IPFW_TLV_TBLNAME_LIST 2
+#define IPFW_TLV_RULE_LIST 3
+#define IPFW_TLV_DYNSTATE_LIST 4
+#define IPFW_TLV_TBL_ENT 5
+#define IPFW_TLV_DYN_ENT 6
+#define IPFW_TLV_RULE_ENT 7
+#define IPFW_TLV_TBLENT_LIST 8
+#define IPFW_TLV_RANGE 9
+
+/* Object name TLV */
+typedef struct _ipfw_obj_ntlv {
+ ipfw_obj_tlv head; /* TLV header */
+ uint16_t idx; /* Name index */
+ uint8_t spare; /* unused */
+ uint8_t type; /* object type, if applicable */
+ uint32_t set; /* set, if applicable */
+ char name[64]; /* Null-terminated name */
+} ipfw_obj_ntlv;
+
+/* IPv4/IPv6 L4 flow description */
+struct tflow_entry {
+ uint8_t af;
+ uint8_t proto;
+ uint16_t spare;
+ uint16_t sport;
+ uint16_t dport;
+ union {
+ struct {
+ struct in_addr sip;
+ struct in_addr dip;
+ } a4;
+ struct {
+ struct in6_addr sip6;
+ struct in6_addr dip6;
+ } a6;
+ } a;
+};
+
+typedef struct _ipfw_table_value {
+ uint32_t tag; /* O_TAG/O_TAGGED */
+ uint32_t pipe; /* O_PIPE/O_QUEUE */
+ uint16_t divert; /* O_DIVERT/O_TEE */
+ uint16_t skipto; /* skipto, CALLRET */
+ uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */
+ uint32_t fib; /* O_SETFIB */
+ uint32_t nat; /* O_NAT */
+ uint32_t nh4;
+ uint8_t dscp;
+ uint8_t spare0[3];
+ struct in6_addr nh6;
+ uint32_t limit; /* O_LIMIT */
+ uint32_t spare1;
+ uint64_t reserved;
+} ipfw_table_value;
+
+/* Table entry TLV */
+typedef struct _ipfw_obj_tentry {
+ ipfw_obj_tlv head; /* TLV header */
+ uint8_t subtype; /* subtype (IPv4,IPv6) */
+ uint8_t masklen; /* mask length */
+ uint8_t result; /* request result */
+ uint8_t spare0;
+ uint16_t idx; /* Table name index */
+ uint16_t spare1;
+ union {
+ /* Longest field needs to be aligned by 8-byte boundary */
+ struct in_addr addr; /* IPv4 address */
+ uint32_t key; /* uid/gid/port */
+ struct in6_addr addr6; /* IPv6 address */
+ char iface[IF_NAMESIZE]; /* interface name */
+ struct tflow_entry flow;
+ } k;
+ union {
+ ipfw_table_value value; /* value data */
+ uint32_t kidx; /* value kernel index */
+ } v;
+} ipfw_obj_tentry;
+#define IPFW_TF_UPDATE 0x01 /* Update record if exists */
+/* Container TLV */
+#define IPFW_CTF_ATOMIC 0x01 /* Perform atomic operation */
+/* Operation results */
+#define IPFW_TR_IGNORED 0 /* Entry was ignored (rollback) */
+#define IPFW_TR_ADDED 1 /* Entry was succesfully added */
+#define IPFW_TR_UPDATED 2 /* Entry was succesfully updated*/
+#define IPFW_TR_DELETED 3 /* Entry was succesfully deleted*/
+#define IPFW_TR_LIMIT 4 /* Entry was ignored (limit) */
+#define IPFW_TR_NOTFOUND 5 /* Entry was not found */
+#define IPFW_TR_EXISTS 6 /* Entry already exists */
+#define IPFW_TR_ERROR 7 /* Request has failed (unknown) */
+
+typedef struct _ipfw_obj_dyntlv {
+ ipfw_obj_tlv head;
+ ipfw_dyn_rule state;
+} ipfw_obj_dyntlv;
+#define IPFW_DF_LAST 0x01 /* Last state in chain */
+
+/* Containter TLVs */
+typedef struct _ipfw_obj_ctlv {
+ ipfw_obj_tlv head; /* TLV header */
+ uint32_t count; /* Number of sub-TLVs */
+ uint16_t objsize; /* Single object size */
+ uint8_t version; /* TLV version */
+ uint8_t flags; /* TLV-specific flags */
+} ipfw_obj_ctlv;
+
+/* Range TLV */
+typedef struct _ipfw_range_tlv {
+ ipfw_obj_tlv head; /* TLV header */
+ uint32_t flags; /* Range flags */
+ uint16_t start_rule; /* Range start */
+ uint16_t end_rule; /* Range end */
+ uint32_t set; /* Range set to match */
+ uint32_t new_set; /* New set to move/swap to */
+} ipfw_range_tlv;
+#define IPFW_RCFLAG_RANGE 0x01 /* rule range is set */
+#define IPFW_RCFLAG_ALL 0x02 /* match ALL rules */
+#define IPFW_RCFLAG_SET 0x04 /* match rules in given set */
+
+typedef struct _ipfw_ta_tinfo {
+ uint32_t flags; /* Format flags */
+ uint32_t spare;
+ uint8_t taclass4; /* algorithm class */
+ uint8_t spare4;
+ uint16_t itemsize4; /* item size in runtime */
+ uint32_t size4; /* runtime structure size */
+ uint32_t count4; /* number of items in runtime */
+ uint8_t taclass6; /* algorithm class */
+ uint8_t spare6;
+ uint16_t itemsize6; /* item size in runtime */
+ uint32_t size6; /* runtime structure size */
+ uint32_t count6; /* number of items in runtime */
+} ipfw_ta_tinfo;
+#define IPFW_TACLASS_HASH 1 /* algo is based on hash */
+#define IPFW_TACLASS_ARRAY 2 /* algo is based on array */
+#define IPFW_TACLASS_RADIX 3 /* algo is based on radix tree */
+
+#define IPFW_TATFLAGS_DATA 0x0001 /* Has data filled in */
+#define IPFW_TATFLAGS_AFDATA 0x0002 /* Separate data per AF */
+#define IPFW_TATFLAGS_AFITEM 0x0004 /* diff. items per AF */
+
+typedef struct _ipfw_xtable_info {
+ uint8_t type; /* table type (addr,iface,..) */
+ uint8_t tflags; /* type flags */
+ uint16_t mflags; /* modification flags */
+ uint16_t flags; /* generic table flags */
+ uint16_t spare[3];
+ uint32_t vmask; /* bitmask with value types */
+ uint32_t set; /* set table is in */
+ uint32_t kidx; /* kernel index */
+ uint32_t refcnt; /* number of references */
+ uint32_t count; /* Number of records */
+ uint32_t size; /* Total size of records(export)*/
+ uint32_t limit; /* Max number of records */
+ char tablename[64]; /* table name */
+ char algoname[64]; /* algorithm name */
+ ipfw_ta_tinfo ta_info; /* additional algo stats */
+} ipfw_xtable_info;
+/* Generic table flags */
+#define IPFW_TGFLAGS_LOCKED 0x01 /* Tables is locked from changes*/
+/* Table type-specific flags */
+#define IPFW_TFFLAG_SRCIP 0x01
+#define IPFW_TFFLAG_DSTIP 0x02
+#define IPFW_TFFLAG_SRCPORT 0x04
+#define IPFW_TFFLAG_DSTPORT 0x08
+#define IPFW_TFFLAG_PROTO 0x10
+/* Table modification flags */
+#define IPFW_TMFLAGS_LIMIT 0x0002 /* Change limit value */
+#define IPFW_TMFLAGS_LOCK 0x0004 /* Change table lock state */
+
+typedef struct _ipfw_iface_info {
+ char ifname[64]; /* interface name */
+ uint32_t ifindex; /* interface index */
+ uint32_t flags; /* flags */
+ uint32_t refcnt; /* number of references */
+ uint32_t gencnt; /* number of changes */
+ uint64_t spare;
+} ipfw_iface_info;
+#define IPFW_IFFLAG_RESOLVED 0x01 /* Interface exists */
+
+typedef struct _ipfw_ta_info {
+ char algoname[64]; /* algorithm name */
+ uint32_t type; /* lookup type */
+ uint32_t flags;
+ uint32_t refcnt;
+ uint32_t spare0;
+ uint64_t spare1;
+} ipfw_ta_info;
+
+#define IPFW_OBJTYPE_TABLE 1
+typedef struct _ipfw_obj_header {
+ ip_fw3_opheader opheader; /* IP_FW3 opcode */
+ uint32_t spare;
+ uint16_t idx; /* object name index */
+ uint8_t objtype; /* object type */
+ uint8_t objsubtype; /* object subtype */
+ ipfw_obj_ntlv ntlv; /* object name tlv */
+} ipfw_obj_header;
+
+typedef struct _ipfw_obj_lheader {
+ ip_fw3_opheader opheader; /* IP_FW3 opcode */
+ uint32_t set_mask; /* disabled set mask */
+ uint32_t count; /* Total objects count */
+ uint32_t size; /* Total size (incl. header) */
+ uint32_t objsize; /* Size of one object */
+} ipfw_obj_lheader;
+
+#define IPFW_CFG_GET_STATIC 0x01
+#define IPFW_CFG_GET_STATES 0x02
+#define IPFW_CFG_GET_COUNTERS 0x04
+typedef struct _ipfw_cfg_lheader {
+ ip_fw3_opheader opheader; /* IP_FW3 opcode */
+ uint32_t set_mask; /* enabled set mask */
+ uint32_t spare;
+ uint32_t flags; /* Request flags */
+ uint32_t size; /* neded buffer size */
+ uint32_t start_rule;
+ uint32_t end_rule;
+} ipfw_cfg_lheader;
+
+typedef struct _ipfw_range_header {
+ ip_fw3_opheader opheader; /* IP_FW3 opcode */
+ ipfw_range_tlv range;
+} ipfw_range_header;
+
+typedef struct _ipfw_sopt_info {
+ uint16_t opcode;
+ uint8_t version;
+ uint8_t dir;
+ uint8_t spare;
+ uint64_t refcnt;
+} ipfw_sopt_info;
+
#endif /* _IPFW2_H */
diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c
index 897adac..fc87327 100644
--- a/sys/netinet/ip_gre.c
+++ b/sys/netinet/ip_gre.c
@@ -205,7 +205,7 @@ gre_input2(struct mbuf *m ,int hlen, u_char proto)
}
m->m_pkthdr.rcvif = GRE2IFP(sc);
-
+ m_clrprotoflags(m);
netisr_queue(isr, m);
/* Packet is done, no further processing needed. */
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index fa108a3..d076943 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -4069,8 +4069,10 @@ __attribute__((noinline))
if (chk == NULL) {
return (ret_code);
}
+ chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_STREAM_RESET;
chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->no_fr_allowed = 0;
chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr);
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index c9b7722..265be3e 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -6784,13 +6784,6 @@ sctp_sendall_completes(void *ptr, uint32_t val SCTP_UNUSED)
SCTP_FREE(ca, SCTP_M_COPYAL);
}
-
-#define MC_ALIGN(m, len) do { \
- SCTP_BUF_RESV_UF(m, ((MCLBYTES - (len)) & ~(sizeof(long) - 1)); \
-} while (0)
-
-
-
static struct mbuf *
sctp_copy_out_all(struct uio *uio, int len)
{
@@ -8932,16 +8925,11 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
return;
}
chk->send_size = 0;
- mat = op_err;
- while (mat != NULL) {
+ for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) {
chk->send_size += SCTP_BUF_LEN(mat);
- mat = SCTP_BUF_NEXT(mat);
}
- chk->rec.chunk_id.id = SCTP_OPERATION_ERROR;
- chk->rec.chunk_id.can_take_data = 1;
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->data = op_err;
chk->whoTo = NULL;
@@ -9029,12 +9017,12 @@ sctp_send_cookie_echo(struct mbuf *m,
return (-5);
}
chk->copy_by_ref = 0;
- chk->send_size = plen;
chk->rec.chunk_id.id = SCTP_COOKIE_ECHO;
chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
+ chk->send_size = plen;
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
chk->asoc = &stcb->asoc;
chk->data = cookie;
chk->whoTo = net;
@@ -9097,12 +9085,12 @@ sctp_send_heartbeat_ack(struct sctp_tcb *stcb,
return;
}
chk->copy_by_ref = 0;
- chk->send_size = chk_length;
chk->rec.chunk_id.id = SCTP_HEARTBEAT_ACK;
chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = 0;
+ chk->send_size = chk_length;
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->data = outchain;
chk->whoTo = net;
@@ -9134,12 +9122,12 @@ sctp_send_cookie_ack(struct sctp_tcb *stcb)
return;
}
chk->copy_by_ref = 0;
- chk->send_size = sizeof(struct sctp_chunkhdr);
chk->rec.chunk_id.id = SCTP_COOKIE_ACK;
chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = 0;
+ chk->send_size = sizeof(struct sctp_chunkhdr);
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->data = cookie_ack;
if (chk->asoc->last_control_chunk_from != NULL) {
@@ -9180,9 +9168,10 @@ sctp_send_shutdown_ack(struct sctp_tcb *stcb, struct sctp_nets *net)
return;
}
chk->copy_by_ref = 0;
- chk->send_size = sizeof(struct sctp_chunkhdr);
chk->rec.chunk_id.id = SCTP_SHUTDOWN_ACK;
chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = 0;
+ chk->send_size = sizeof(struct sctp_chunkhdr);
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
chk->flags = 0;
@@ -9223,9 +9212,10 @@ sctp_send_shutdown(struct sctp_tcb *stcb, struct sctp_nets *net)
return;
}
chk->copy_by_ref = 0;
- chk->send_size = sizeof(struct sctp_shutdown_chunk);
chk->rec.chunk_id.id = SCTP_SHUTDOWN;
chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = 0;
+ chk->send_size = sizeof(struct sctp_shutdown_chunk);
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
chk->flags = 0;
@@ -9276,13 +9266,13 @@ sctp_send_asconf(struct sctp_tcb *stcb, struct sctp_nets *net, int addr_locked)
return;
}
chk->copy_by_ref = 0;
- chk->data = m_asconf;
- chk->send_size = len;
chk->rec.chunk_id.id = SCTP_ASCONF;
chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
+ chk->data = m_asconf;
+ chk->send_size = len;
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
chk->asoc = &stcb->asoc;
chk->whoTo = net;
if (chk->whoTo) {
@@ -9371,7 +9361,9 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
return;
}
chk->copy_by_ref = 0;
-
+ chk->rec.chunk_id.id = SCTP_ASCONF_ACK;
+ chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
chk->whoTo = net;
if (chk->whoTo) {
atomic_add_int(&chk->whoTo->ref_count, 1);
@@ -9380,11 +9372,8 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
chk->send_size = 0;
/* Get size */
chk->send_size = ack->len;
- chk->rec.chunk_id.id = SCTP_ASCONF_ACK;
- chk->rec.chunk_id.can_take_data = 1;
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; /* XXX */
chk->asoc = &stcb->asoc;
TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
@@ -10264,6 +10253,7 @@ send_forward_tsn(struct sctp_tcb *stcb,
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_FORWARD_CUM_TSN;
chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = 0;
chk->asoc = asoc;
chk->whoTo = NULL;
chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
@@ -10497,6 +10487,7 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
/* Clear our pkt counts */
asoc->data_pkts_seen = 0;
+ a_chk->flags = 0;
a_chk->asoc = asoc;
a_chk->snd_count = 0;
a_chk->send_size = 0; /* fill in later */
@@ -11274,6 +11265,7 @@ sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net, int so_locked
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_HEARTBEAT_REQUEST;
chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->send_size = sizeof(struct sctp_heartbeat_chunk);
@@ -11375,10 +11367,11 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
if (chk == NULL) {
return;
}
- chk->copy_by_ref = 0;
SCTP_STAT_INCR(sctps_queue_upd_ecne);
+ chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_ECN_ECHO;
chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->send_size = sizeof(struct sctp_ecne_chunk);
chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_NOWAIT, 1, MT_HEADER);
@@ -11438,6 +11431,9 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
return;
}
chk->copy_by_ref = 0;
+ chk->rec.chunk_id.id = SCTP_PACKET_DROPPED;
+ chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = 0;
len -= iphlen;
chk->send_size = len;
/* Validate that we do not have an ABORT in here. */
@@ -11524,8 +11520,6 @@ jump_out:
} else {
chk->whoTo = NULL;
}
- chk->rec.chunk_id.id = SCTP_PACKET_DROPPED;
- chk->rec.chunk_id.can_take_data = 1;
drp->ch.chunk_type = SCTP_PACKET_DROPPED;
drp->ch.chunk_length = htons(chk->send_size);
spc = SCTP_SB_LIMIT_RCV(stcb->sctp_socket);
@@ -11591,6 +11585,7 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, u
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_ECN_CWR;
chk->rec.chunk_id.can_take_data = 1;
+ chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->send_size = sizeof(struct sctp_cwr_chunk);
chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_NOWAIT, 1, MT_HEADER);
@@ -11853,7 +11848,7 @@ sctp_add_an_in_stream(struct sctp_tmit_chunk *chk,
int
sctp_send_str_reset_req(struct sctp_tcb *stcb,
- int number_entries, uint16_t * list,
+ uint16_t number_entries, uint16_t * list,
uint8_t send_out_req,
uint8_t send_in_req,
uint8_t send_tsn_req,
@@ -11886,6 +11881,14 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
+ if (number_entries > (MCLBYTES -
+ SCTP_MIN_OVERHEAD -
+ sizeof(struct sctp_chunkhdr) -
+ sizeof(struct sctp_stream_reset_out_request)) /
+ sizeof(uint16_t)) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return (ENOMEM);
+ }
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
@@ -11894,6 +11897,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_STREAM_RESET;
chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->book_size = sizeof(struct sctp_chunkhdr);
chk->send_size = SCTP_SIZE32(chk->book_size);
diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h
index 59af5af..8789df9 100644
--- a/sys/netinet/sctp_output.h
+++ b/sys/netinet/sctp_output.h
@@ -181,8 +181,8 @@ sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *,
uint32_t, uint32_t, uint32_t, uint32_t);
int
-sctp_send_str_reset_req(struct sctp_tcb *, int, uint16_t *, uint8_t, uint8_t,
- uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
+sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *, uint8_t,
+ uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
void
sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *,
diff --git a/sys/netinet/sctp_syscalls.c b/sys/netinet/sctp_syscalls.c
new file mode 100644
index 0000000..3d0f549
--- /dev/null
+++ b/sys/netinet/sctp_syscalls.c
@@ -0,0 +1,588 @@
+/*-
+ * Copyright (c) 1982, 1986, 1989, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that 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.
+ * 4. 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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_capsicum.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_sctp.h"
+#include "opt_compat.h"
+#include "opt_ktrace.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capsicum.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysproto.h>
+#include <sys/malloc.h>
+#include <sys/filedesc.h>
+#include <sys/event.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filio.h>
+#include <sys/jail.h>
+#include <sys/mount.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sf_buf.h>
+#include <sys/sysent.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/signalvar.h>
+#include <sys/syscall.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32_util.h>
+#endif
+
+#include <net/vnet.h>
+
+#include <security/audit/audit.h>
+#include <security/mac/mac_framework.h>
+
+#include <netinet/sctp.h>
+#include <netinet/sctp_peeloff.h>
+
+static struct syscall_helper_data sctp_syscalls[] = {
+ SYSCALL_INIT_HELPER(sctp_peeloff),
+ SYSCALL_INIT_HELPER(sctp_generic_sendmsg),
+ SYSCALL_INIT_HELPER(sctp_generic_sendmsg_iov),
+ SYSCALL_INIT_HELPER(sctp_generic_recvmsg),
+ SYSCALL_INIT_LAST
+};
+
+static void
+sctp_syscalls_init(void *unused __unused)
+{
+ int error;
+
+ error = syscall_helper_register(sctp_syscalls);
+ KASSERT((error == 0),
+ ("%s: syscall_helper_register failed for sctp syscalls", __func__));
+#ifdef COMPAT_FREEBSD32
+ error = syscall32_helper_register(sctp_syscalls);
+ KASSERT((error == 0),
+ ("%s: syscall32_helper_register failed for sctp syscalls",
+ __func__));
+#endif
+}
+SYSINIT(sctp_syscalls, SI_SUB_SYSCALLS, SI_ORDER_ANY, sctp_syscalls_init, NULL);
+
+/*
+ * SCTP syscalls.
+ * Functionality only compiled in if SCTP is defined in the kernel Makefile,
+ * otherwise all return EOPNOTSUPP.
+ * XXX: We should make this loadable one day.
+ */
+int
+sys_sctp_peeloff(td, uap)
+ struct thread *td;
+ struct sctp_peeloff_args /* {
+ int sd;
+ caddr_t name;
+ } */ *uap;
+{
+#if (defined(INET) || defined(INET6)) && defined(SCTP)
+ struct file *nfp = NULL;
+ struct socket *head, *so;
+ cap_rights_t rights;
+ u_int fflag;
+ int error, fd;
+
+ AUDIT_ARG_FD(uap->sd);
+ error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
+ &head, &fflag);
+ if (error != 0)
+ goto done2;
+ if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto done;
+ }
+ error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
+ if (error != 0)
+ goto done;
+ /*
+ * At this point we know we do have a assoc to pull
+ * we proceed to get the fd setup. This may block
+ * but that is ok.
+ */
+
+ error = falloc(td, &nfp, &fd, 0);
+ if (error != 0)
+ goto done;
+ td->td_retval[0] = fd;
+
+ CURVNET_SET(head->so_vnet);
+ so = sonewconn(head, SS_ISCONNECTED);
+ if (so == NULL) {
+ error = ENOMEM;
+ goto noconnection;
+ }
+ /*
+ * Before changing the flags on the socket, we have to bump the
+ * reference count. Otherwise, if the protocol calls sofree(),
+ * the socket will be released due to a zero refcount.
+ */
+ SOCK_LOCK(so);
+ soref(so); /* file descriptor reference */
+ SOCK_UNLOCK(so);
+
+ ACCEPT_LOCK();
+
+ TAILQ_REMOVE(&head->so_comp, so, so_list);
+ head->so_qlen--;
+ so->so_state |= (head->so_state & SS_NBIO);
+ so->so_state &= ~SS_NOFDREF;
+ so->so_qstate &= ~SQ_COMP;
+ so->so_head = NULL;
+ ACCEPT_UNLOCK();
+ finit(nfp, fflag, DTYPE_SOCKET, so, &socketops);
+ error = sctp_do_peeloff(head, so, (sctp_assoc_t)uap->name);
+ if (error != 0)
+ goto noconnection;
+ if (head->so_sigio != NULL)
+ fsetown(fgetown(&head->so_sigio), &so->so_sigio);
+
+noconnection:
+ /*
+ * close the new descriptor, assuming someone hasn't ripped it
+ * out from under us.
+ */
+ if (error != 0)
+ fdclose(td->td_proc->p_fd, nfp, fd, td);
+
+ /*
+ * Release explicitly held references before returning.
+ */
+ CURVNET_RESTORE();
+done:
+ if (nfp != NULL)
+ fdrop(nfp, td);
+ fputsock(head);
+done2:
+ return (error);
+#else /* SCTP */
+ return (EOPNOTSUPP);
+#endif /* SCTP */
+}
+
+int
+sys_sctp_generic_sendmsg (td, uap)
+ struct thread *td;
+ struct sctp_generic_sendmsg_args /* {
+ int sd,
+ caddr_t msg,
+ int mlen,
+ caddr_t to,
+ __socklen_t tolen,
+ struct sctp_sndrcvinfo *sinfo,
+ int flags
+ } */ *uap;
+{
+#if (defined(INET) || defined(INET6)) && defined(SCTP)
+ struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
+ struct socket *so;
+ struct file *fp = NULL;
+ struct sockaddr *to = NULL;
+#ifdef KTRACE
+ struct uio *ktruio = NULL;
+#endif
+ struct uio auio;
+ struct iovec iov[1];
+ cap_rights_t rights;
+ int error = 0, len;
+
+ if (uap->sinfo != NULL) {
+ error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
+ if (error != 0)
+ return (error);
+ u_sinfo = &sinfo;
+ }
+
+ cap_rights_init(&rights, CAP_SEND);
+ if (uap->tolen != 0) {
+ error = getsockaddr(&to, uap->to, uap->tolen);
+ if (error != 0) {
+ to = NULL;
+ goto sctp_bad2;
+ }
+ cap_rights_set(&rights, CAP_CONNECT);
+ }
+
+ AUDIT_ARG_FD(uap->sd);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
+ if (error != 0)
+ goto sctp_bad;
+#ifdef KTRACE
+ if (to && (KTRPOINT(td, KTR_STRUCT)))
+ ktrsockaddr(to);
+#endif
+
+ iov[0].iov_base = uap->msg;
+ iov[0].iov_len = uap->mlen;
+
+ so = (struct socket *)fp->f_data;
+ if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto sctp_bad;
+ }
+#ifdef MAC
+ error = mac_socket_check_send(td->td_ucred, so);
+ if (error != 0)
+ goto sctp_bad;
+#endif /* MAC */
+
+ auio.uio_iov = iov;
+ auio.uio_iovcnt = 1;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_td = td;
+ auio.uio_offset = 0; /* XXX */
+ auio.uio_resid = 0;
+ len = auio.uio_resid = uap->mlen;
+ CURVNET_SET(so->so_vnet);
+ error = sctp_lower_sosend(so, to, &auio, (struct mbuf *)NULL,
+ (struct mbuf *)NULL, uap->flags, u_sinfo, td);
+ CURVNET_RESTORE();
+ if (error != 0) {
+ if (auio.uio_resid != len && (error == ERESTART ||
+ error == EINTR || error == EWOULDBLOCK))
+ error = 0;
+ /* Generation of SIGPIPE can be controlled per socket. */
+ if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
+ !(uap->flags & MSG_NOSIGNAL)) {
+ PROC_LOCK(td->td_proc);
+ tdsignal(td, SIGPIPE);
+ PROC_UNLOCK(td->td_proc);
+ }
+ }
+ if (error == 0)
+ td->td_retval[0] = len - auio.uio_resid;
+#ifdef KTRACE
+ if (ktruio != NULL) {
+ ktruio->uio_resid = td->td_retval[0];
+ ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
+ }
+#endif /* KTRACE */
+sctp_bad:
+ if (fp != NULL)
+ fdrop(fp, td);
+sctp_bad2:
+ free(to, M_SONAME);
+ return (error);
+#else /* SCTP */
+ return (EOPNOTSUPP);
+#endif /* SCTP */
+}
+
+int
+sys_sctp_generic_sendmsg_iov(td, uap)
+ struct thread *td;
+ struct sctp_generic_sendmsg_iov_args /* {
+ int sd,
+ struct iovec *iov,
+ int iovlen,
+ caddr_t to,
+ __socklen_t tolen,
+ struct sctp_sndrcvinfo *sinfo,
+ int flags
+ } */ *uap;
+{
+#if (defined(INET) || defined(INET6)) && defined(SCTP)
+ struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL;
+ struct socket *so;
+ struct file *fp = NULL;
+ struct sockaddr *to = NULL;
+#ifdef KTRACE
+ struct uio *ktruio = NULL;
+#endif
+ struct uio auio;
+ struct iovec *iov, *tiov;
+ cap_rights_t rights;
+ ssize_t len;
+ int error, i;
+
+ if (uap->sinfo != NULL) {
+ error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
+ if (error != 0)
+ return (error);
+ u_sinfo = &sinfo;
+ }
+ cap_rights_init(&rights, CAP_SEND);
+ if (uap->tolen != 0) {
+ error = getsockaddr(&to, uap->to, uap->tolen);
+ if (error != 0) {
+ to = NULL;
+ goto sctp_bad2;
+ }
+ cap_rights_set(&rights, CAP_CONNECT);
+ }
+
+ AUDIT_ARG_FD(uap->sd);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
+ if (error != 0)
+ goto sctp_bad1;
+
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
+ uap->iovlen, &iov, EMSGSIZE);
+ else
+#endif
+ error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
+ if (error != 0)
+ goto sctp_bad1;
+#ifdef KTRACE
+ if (to && (KTRPOINT(td, KTR_STRUCT)))
+ ktrsockaddr(to);
+#endif
+
+ so = (struct socket *)fp->f_data;
+ if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto sctp_bad;
+ }
+#ifdef MAC
+ error = mac_socket_check_send(td->td_ucred, so);
+ if (error != 0)
+ goto sctp_bad;
+#endif /* MAC */
+
+ auio.uio_iov = iov;
+ auio.uio_iovcnt = uap->iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_td = td;
+ auio.uio_offset = 0; /* XXX */
+ auio.uio_resid = 0;
+ tiov = iov;
+ for (i = 0; i <uap->iovlen; i++, tiov++) {
+ if ((auio.uio_resid += tiov->iov_len) < 0) {
+ error = EINVAL;
+ goto sctp_bad;
+ }
+ }
+ len = auio.uio_resid;
+ CURVNET_SET(so->so_vnet);
+ error = sctp_lower_sosend(so, to, &auio,
+ (struct mbuf *)NULL, (struct mbuf *)NULL,
+ uap->flags, u_sinfo, td);
+ CURVNET_RESTORE();
+ if (error != 0) {
+ if (auio.uio_resid != len && (error == ERESTART ||
+ error == EINTR || error == EWOULDBLOCK))
+ error = 0;
+ /* Generation of SIGPIPE can be controlled per socket */
+ if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE) &&
+ !(uap->flags & MSG_NOSIGNAL)) {
+ PROC_LOCK(td->td_proc);
+ tdsignal(td, SIGPIPE);
+ PROC_UNLOCK(td->td_proc);
+ }
+ }
+ if (error == 0)
+ td->td_retval[0] = len - auio.uio_resid;
+#ifdef KTRACE
+ if (ktruio != NULL) {
+ ktruio->uio_resid = td->td_retval[0];
+ ktrgenio(uap->sd, UIO_WRITE, ktruio, error);
+ }
+#endif /* KTRACE */
+sctp_bad:
+ free(iov, M_IOV);
+sctp_bad1:
+ if (fp != NULL)
+ fdrop(fp, td);
+sctp_bad2:
+ free(to, M_SONAME);
+ return (error);
+#else /* SCTP */
+ return (EOPNOTSUPP);
+#endif /* SCTP */
+}
+
+int
+sys_sctp_generic_recvmsg(td, uap)
+ struct thread *td;
+ struct sctp_generic_recvmsg_args /* {
+ int sd,
+ struct iovec *iov,
+ int iovlen,
+ struct sockaddr *from,
+ __socklen_t *fromlenaddr,
+ struct sctp_sndrcvinfo *sinfo,
+ int *msg_flags
+ } */ *uap;
+{
+#if (defined(INET) || defined(INET6)) && defined(SCTP)
+ uint8_t sockbufstore[256];
+ struct uio auio;
+ struct iovec *iov, *tiov;
+ struct sctp_sndrcvinfo sinfo;
+ struct socket *so;
+ struct file *fp = NULL;
+ struct sockaddr *fromsa;
+ cap_rights_t rights;
+#ifdef KTRACE
+ struct uio *ktruio = NULL;
+#endif
+ ssize_t len;
+ int error, fromlen, i, msg_flags;
+
+ AUDIT_ARG_FD(uap->sd);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd,
+ cap_rights_init(&rights, CAP_RECV), &fp, NULL);
+ if (error != 0)
+ return (error);
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ error = freebsd32_copyiniov((struct iovec32 *)uap->iov,
+ uap->iovlen, &iov, EMSGSIZE);
+ else
+#endif
+ error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE);
+ if (error != 0)
+ goto out1;
+
+ so = fp->f_data;
+ if (so->so_proto->pr_protocol != IPPROTO_SCTP) {
+ error = EOPNOTSUPP;
+ goto out;
+ }
+#ifdef MAC
+ error = mac_socket_check_receive(td->td_ucred, so);
+ if (error != 0)
+ goto out;
+#endif /* MAC */
+
+ if (uap->fromlenaddr != NULL) {
+ error = copyin(uap->fromlenaddr, &fromlen, sizeof (fromlen));
+ if (error != 0)
+ goto out;
+ } else {
+ fromlen = 0;
+ }
+ if (uap->msg_flags) {
+ error = copyin(uap->msg_flags, &msg_flags, sizeof (int));
+ if (error != 0)
+ goto out;
+ } else {
+ msg_flags = 0;
+ }
+ auio.uio_iov = iov;
+ auio.uio_iovcnt = uap->iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_READ;
+ auio.uio_td = td;
+ auio.uio_offset = 0; /* XXX */
+ auio.uio_resid = 0;
+ tiov = iov;
+ for (i = 0; i <uap->iovlen; i++, tiov++) {
+ if ((auio.uio_resid += tiov->iov_len) < 0) {
+ error = EINVAL;
+ goto out;
+ }
+ }
+ len = auio.uio_resid;
+ fromsa = (struct sockaddr *)sockbufstore;
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_GENIO))
+ ktruio = cloneuio(&auio);
+#endif /* KTRACE */
+ memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
+ CURVNET_SET(so->so_vnet);
+ error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL,
+ fromsa, fromlen, &msg_flags,
+ (struct sctp_sndrcvinfo *)&sinfo, 1);
+ CURVNET_RESTORE();
+ if (error != 0) {
+ if (auio.uio_resid != len && (error == ERESTART ||
+ error == EINTR || error == EWOULDBLOCK))
+ error = 0;
+ } else {
+ if (uap->sinfo)
+ error = copyout(&sinfo, uap->sinfo, sizeof (sinfo));
+ }
+#ifdef KTRACE
+ if (ktruio != NULL) {
+ ktruio->uio_resid = len - auio.uio_resid;
+ ktrgenio(uap->sd, UIO_READ, ktruio, error);
+ }
+#endif /* KTRACE */
+ if (error != 0)
+ goto out;
+ td->td_retval[0] = len - auio.uio_resid;
+
+ if (fromlen && uap->from) {
+ len = fromlen;
+ if (len <= 0 || fromsa == 0)
+ len = 0;
+ else {
+ len = MIN(len, fromsa->sa_len);
+ error = copyout(fromsa, uap->from, (size_t)len);
+ if (error != 0)
+ goto out;
+ }
+ error = copyout(&len, uap->fromlenaddr, sizeof (socklen_t));
+ if (error != 0)
+ goto out;
+ }
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_STRUCT))
+ ktrsockaddr(fromsa);
+#endif
+ if (uap->msg_flags) {
+ error = copyout(&msg_flags, uap->msg_flags, sizeof (int));
+ if (error != 0)
+ goto out;
+ }
+out:
+ free(iov, M_IOV);
+out1:
+ if (fp != NULL)
+ fdrop(fp, td);
+
+ return (error);
+#else /* SCTP */
+ return (EOPNOTSUPP);
+#endif /* SCTP */
+}
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index e1fa351..e1ad178 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -4431,6 +4431,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
+ if (sizeof(struct sctp_reset_streams) +
+ strrst->srs_number_streams * sizeof(uint16_t) > optsize) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
if (stcb->asoc.stream_reset_outstanding) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
error = EALREADY;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index fde23ef..1e87a17 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -6832,7 +6832,8 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
#endif
static void
-sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
+sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored,
+ const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED)
{
struct ip *iph;
@@ -6968,7 +6969,7 @@ sctp_over_udp_start(void)
}
/* Call the special UDP hook. */
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
- sctp_recv_udp_tunneled_packet))) {
+ sctp_recv_udp_tunneled_packet, NULL))) {
sctp_over_udp_stop();
return (ret);
}
@@ -6992,7 +6993,7 @@ sctp_over_udp_start(void)
}
/* Call the special UDP hook. */
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
- sctp_recv_udp_tunneled_packet))) {
+ sctp_recv_udp_tunneled_packet, NULL))) {
sctp_over_udp_stop();
return (ret);
}
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 0697767..7db0e50 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -675,6 +675,12 @@ just_return:
send:
SOCKBUF_LOCK_ASSERT(&so->so_snd);
+ if (len > 0) {
+ if (len >= tp->t_maxseg)
+ tp->t_flags2 |= TF2_PLPMTU_MAXSEGSNT;
+ else
+ tp->t_flags2 &= ~TF2_PLPMTU_MAXSEGSNT;
+ }
/*
* Before ESTABLISHED, force sending of initial options
* unless TCP set not to do any options.
@@ -806,41 +812,40 @@ send:
* Check if we should limit by maximum segment
* size and count:
*/
- if (if_hw_tsomaxsegcount != 0 && if_hw_tsomaxsegsize != 0) {
+ if (if_hw_tsomaxsegcount != 0 &&
+ if_hw_tsomaxsegsize != 0) {
max_len = 0;
mb = sbsndmbuf(&so->so_snd, off, &moff);
while (mb != NULL && (u_int)max_len < len) {
- u_int cur_length;
- u_int cur_frags;
+ u_int mlen;
+ u_int frags;
/*
* Get length of mbuf fragment
- * and how many hardware
- * frags, rounded up, it would
- * use:
+ * and how many hardware frags,
+ * rounded up, it would use:
*/
- cur_length = (mb->m_len - moff);
- cur_frags = (cur_length + if_hw_tsomaxsegsize -
- 1) / if_hw_tsomaxsegsize;
+ mlen = (mb->m_len - moff);
+ frags = howmany(mlen,
+ if_hw_tsomaxsegsize);
/* Handle special case: Zero Length Mbuf */
- if (cur_frags == 0)
- cur_frags = 1;
+ if (frags == 0)
+ frags = 1;
/*
* Check if the fragment limit
- * will be reached or
- * exceeded:
+ * will be reached or exceeded:
*/
- if (cur_frags >= if_hw_tsomaxsegcount) {
- max_len += min(cur_length,
+ if (frags >= if_hw_tsomaxsegcount) {
+ max_len += min(mlen,
if_hw_tsomaxsegcount *
if_hw_tsomaxsegsize);
break;
}
- max_len += cur_length;
- if_hw_tsomaxsegcount -= cur_frags;
+ max_len += mlen;
+ if_hw_tsomaxsegcount -= frags;
moff = 0;
mb = mb->m_next;
}
@@ -1304,8 +1309,12 @@ send:
*
* NB: Don't set DF on small MTU/MSS to have a safe fallback.
*/
- if (V_path_mtu_discovery && tp->t_maxopd > V_tcp_minmss)
+ if (V_path_mtu_discovery && tp->t_maxopd > V_tcp_minmss) {
ip->ip_off |= htons(IP_DF);
+ tp->t_flags2 |= TF2_PLPMTU_PMTUD;
+ } else {
+ tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
+ }
if (tp->t_state == TCPS_SYN_SENT)
TCP_PROBE5(connect__request, NULL, tp, ip, tp, th);
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 1767e1e..62a9b6d 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -66,6 +66,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
+#ifdef INET6
+#include <netinet6/tcp6_var.h>
+#endif
#include <netinet/tcpip.h>
#ifdef TCPDEBUG
#include <netinet/tcp_debug.h>
@@ -127,6 +130,54 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
&tcp_rexmit_drop_options, 0,
"Drop TCP options from 3rd and later retransmitted SYN");
+static VNET_DEFINE(int, tcp_pmtud_blackhole_detect);
+#define V_tcp_pmtud_blackhole_detect VNET(tcp_pmtud_blackhole_detect)
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_detection,
+ CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_VNET,
+ &VNET_NAME(tcp_pmtud_blackhole_detect), 0,
+ "Path MTU Discovery Black Hole Detection Enabled");
+
+static VNET_DEFINE(int, tcp_pmtud_blackhole_activated);
+#define V_tcp_pmtud_blackhole_activated \
+ VNET(tcp_pmtud_blackhole_activated)
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated,
+ CTLTYPE_INT|CTLFLAG_RD|CTLFLAG_VNET,
+ &VNET_NAME(tcp_pmtud_blackhole_activated), 0,
+ "Path MTU Discovery Black Hole Detection, Activation Count");
+
+static VNET_DEFINE(int, tcp_pmtud_blackhole_activated_min_mss);
+#define V_tcp_pmtud_blackhole_activated_min_mss \
+ VNET(tcp_pmtud_blackhole_activated_min_mss)
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_activated_min_mss,
+ CTLTYPE_INT|CTLFLAG_RD|CTLFLAG_VNET,
+ &VNET_NAME(tcp_pmtud_blackhole_activated_min_mss), 0,
+ "Path MTU Discovery Black Hole Detection, Activation Count at min MSS");
+
+static VNET_DEFINE(int, tcp_pmtud_blackhole_failed);
+#define V_tcp_pmtud_blackhole_failed VNET(tcp_pmtud_blackhole_failed)
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_failed,
+ CTLTYPE_INT|CTLFLAG_RD|CTLFLAG_VNET,
+ &VNET_NAME(tcp_pmtud_blackhole_failed), 0,
+ "Path MTU Discovery Black Hole Detection, Failure Count");
+
+#ifdef INET
+static VNET_DEFINE(int, tcp_pmtud_blackhole_mss) = 1200;
+#define V_tcp_pmtud_blackhole_mss VNET(tcp_pmtud_blackhole_mss)
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, pmtud_blackhole_mss,
+ CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_VNET,
+ &VNET_NAME(tcp_pmtud_blackhole_mss), 0,
+ "Path MTU Discovery Black Hole Detection lowered MSS");
+#endif
+
+#ifdef INET6
+static VNET_DEFINE(int, tcp_v6pmtud_blackhole_mss) = 1220;
+#define V_tcp_v6pmtud_blackhole_mss VNET(tcp_v6pmtud_blackhole_mss)
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, v6pmtud_blackhole_mss,
+ CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_VNET,
+ &VNET_NAME(tcp_v6pmtud_blackhole_mss), 0,
+ "Path MTU Discovery IPv6 Black Hole Detection lowered MSS");
+#endif
+
#ifdef RSS
static int per_cpu_timers = 1;
#else
@@ -539,6 +590,7 @@ tcp_timer_rexmt(void * xtp)
ostate = tp->t_state;
#endif
+
INP_INFO_RLOCK(&V_tcbinfo);
inp = tp->t_inpcb;
/*
@@ -640,6 +692,102 @@ tcp_timer_rexmt(void * xtp)
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
TCPT_RANGESET(tp->t_rxtcur, rexmt,
tp->t_rttmin, TCPTV_REXMTMAX);
+
+ if (V_tcp_pmtud_blackhole_detect && (tp->t_state == TCPS_ESTABLISHED)) {
+ int optlen;
+#ifdef INET6
+ int isipv6;
+#endif
+
+ if (((tp->t_flags2 & (TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) ==
+ (TF2_PLPMTU_PMTUD|TF2_PLPMTU_MAXSEGSNT)) &&
+ (tp->t_rxtshift <= 2)) {
+ /*
+ * Enter Path MTU Black-hole Detection mechanism:
+ * - Disable Path MTU Discovery (IP "DF" bit).
+ * - Reduce MTU to lower value than what we
+ * negotiated with peer.
+ */
+ /* Record that we may have found a black hole. */
+ tp->t_flags2 |= TF2_PLPMTU_BLACKHOLE;
+
+ /* Keep track of previous MSS. */
+ optlen = tp->t_maxopd - tp->t_maxseg;
+ tp->t_pmtud_saved_maxopd = tp->t_maxopd;
+
+ /*
+ * Reduce the MSS to blackhole value or to the default
+ * in an attempt to retransmit.
+ */
+#ifdef INET6
+ isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) ? 1 : 0;
+ if (isipv6 &&
+ tp->t_maxopd > V_tcp_v6pmtud_blackhole_mss) {
+ /* Use the sysctl tuneable blackhole MSS. */
+ tp->t_maxopd = V_tcp_v6pmtud_blackhole_mss;
+ V_tcp_pmtud_blackhole_activated++;
+ } else if (isipv6) {
+ /* Use the default MSS. */
+ tp->t_maxopd = V_tcp_v6mssdflt;
+ /*
+ * Disable Path MTU Discovery when we switch to
+ * minmss.
+ */
+ tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
+ V_tcp_pmtud_blackhole_activated_min_mss++;
+ }
+#endif
+#if defined(INET6) && defined(INET)
+ else
+#endif
+#ifdef INET
+ if (tp->t_maxopd > V_tcp_pmtud_blackhole_mss) {
+ /* Use the sysctl tuneable blackhole MSS. */
+ tp->t_maxopd = V_tcp_pmtud_blackhole_mss;
+ V_tcp_pmtud_blackhole_activated++;
+ } else {
+ /* Use the default MSS. */
+ tp->t_maxopd = V_tcp_mssdflt;
+ /*
+ * Disable Path MTU Discovery when we switch to
+ * minmss.
+ */
+ tp->t_flags2 &= ~TF2_PLPMTU_PMTUD;
+ V_tcp_pmtud_blackhole_activated_min_mss++;
+ }
+#endif
+ tp->t_maxseg = tp->t_maxopd - optlen;
+ /*
+ * Reset the slow-start flight size
+ * as it may depend on the new MSS.
+ */
+ if (CC_ALGO(tp)->conn_init != NULL)
+ CC_ALGO(tp)->conn_init(tp->ccv);
+ } else {
+ /*
+ * If further retransmissions are still unsuccessful
+ * with a lowered MTU, maybe this isn't a blackhole and
+ * we restore the previous MSS and blackhole detection
+ * flags.
+ */
+ if ((tp->t_flags2 & TF2_PLPMTU_BLACKHOLE) &&
+ (tp->t_rxtshift > 4)) {
+ tp->t_flags2 |= TF2_PLPMTU_PMTUD;
+ tp->t_flags2 &= ~TF2_PLPMTU_BLACKHOLE;
+ optlen = tp->t_maxopd - tp->t_maxseg;
+ tp->t_maxopd = tp->t_pmtud_saved_maxopd;
+ tp->t_maxseg = tp->t_maxopd - optlen;
+ V_tcp_pmtud_blackhole_failed++;
+ /*
+ * Reset the slow-start flight size as it
+ * may depend on the new MSS.
+ */
+ if (CC_ALGO(tp)->conn_init != NULL)
+ CC_ALGO(tp)->conn_init(tp->ccv);
+ }
+ }
+ }
+
/*
* Disable RFC1323 and SACK if we haven't got any response to
* our third SYN to work-around some broken terminal servers
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index ac87f88..9fe6447 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -200,6 +200,8 @@ struct tcpcb {
u_int t_keepcnt; /* number of keepalives before close */
u_int t_tsomax; /* TSO total burst length limit in bytes */
+ u_int t_pmtud_saved_maxopd; /* pre-blackhole MSS */
+ u_int t_flags2; /* More tcpcb flags storage */
uint32_t t_ispare[6]; /* 5 UTO, 1 TBD */
uint32_t t_tsomaxsegcount; /* TSO maximum segment count */
@@ -278,6 +280,13 @@ struct tcpcb {
#endif /* TCP_SIGNATURE */
/*
+ * Flags for PLPMTU handling, t_flags2
+ */
+#define TF2_PLPMTU_BLACKHOLE 0x00000001 /* Possible PLPMTUD Black Hole. */
+#define TF2_PLPMTU_PMTUD 0x00000002 /* Allowed to attempt PLPMTUD. */
+#define TF2_PLPMTU_MAXSEGSNT 0x00000004 /* Last seg sent was full seg. */
+
+/*
* Structure to hold TCP options that are only used during segment
* processing (in tcp_input), but not held in the tcpcb.
* It's basically used to reduce the number of parameters
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 92edcd1..3a3d60e 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -312,13 +312,11 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
*/
up = intoudpcb(inp);
if (up->u_tun_func != NULL) {
- (*up->u_tun_func)(n, off, inp);
+ (*up->u_tun_func)(n, off, inp, (struct sockaddr *)udp_in,
+ up->u_tun_ctx);
return;
}
- if (n == NULL)
- return;
-
off += sizeof(struct udphdr);
#ifdef IPSEC
@@ -578,8 +576,12 @@ udp_input(struct mbuf **mp, int *offp, int proto)
if (last != NULL) {
struct mbuf *n;
- n = m_copy(m, 0, M_COPYALL);
- udp_append(last, ip, n, iphlen, &udp_in);
+ if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
+ UDP_PROBE(receive, NULL, last, ip,
+ last, uh);
+ udp_append(last, ip, n, iphlen,
+ &udp_in);
+ }
INP_RUNLOCK(last);
}
last = inp;
@@ -608,6 +610,7 @@ udp_input(struct mbuf **mp, int *offp, int proto)
INP_INFO_RUNLOCK(pcbinfo);
goto badunlocked;
}
+ UDP_PROBE(receive, NULL, last, ip, last, uh);
udp_append(last, ip, m, iphlen, &udp_in);
INP_RUNLOCK(last);
INP_INFO_RUNLOCK(pcbinfo);
@@ -1715,7 +1718,7 @@ udp_attach(struct socket *so, int proto, struct thread *td)
#endif /* INET */
int
-udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f)
+udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, void *ctx)
{
struct inpcb *inp;
struct udpcb *up;
@@ -1731,6 +1734,7 @@ udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f)
return (EBUSY);
}
up->u_tun_func = f;
+ up->u_tun_ctx = ctx;
INP_WUNLOCK(inp);
return (0);
}
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 04b4dbb..2e0a4f8 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -55,7 +55,8 @@ struct udpiphdr {
struct inpcb;
struct mbuf;
-typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *);
+typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *,
+ const struct sockaddr *, void *);
/*
* UDP control block; one per udp.
@@ -65,6 +66,7 @@ struct udpcb {
u_int u_flags; /* Generic UDP flags. */
uint16_t u_rxcslen; /* Coverage for incoming datagrams. */
uint16_t u_txcslen; /* Coverage for outgoing datagrams. */
+ void *u_tun_ctx; /* Tunneling callback context. */
};
#define intoudpcb(ip) ((struct udpcb *)(ip)->inp_ppcb)
@@ -176,7 +178,8 @@ void udplite_input(struct mbuf *, int);
struct inpcb *udp_notify(struct inpcb *inp, int errno);
int udp_shutdown(struct socket *so);
-int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f);
+int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f,
+ void *ctx);
#endif /* _KERNEL */
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index e36f778..de79816 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -141,9 +141,19 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off,
{
struct socket *so;
struct mbuf *opts;
+ struct udpcb *up;
INP_LOCK_ASSERT(inp);
+ /*
+ * Engage the tunneling protocol.
+ */
+ up = intoudpcb(inp);
+ if (up->u_tun_func != NULL) {
+ (*up->u_tun_func)(n, off, inp, (struct sockaddr *)fromsa,
+ up->u_tun_ctx);
+ return;
+ }
#ifdef IPSEC
/* Check AH/ESP integrity. */
if (ipsec6_in_reject(n, inp)) {
@@ -265,7 +275,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
if (uh_sum != 0) {
UDPSTAT_INC(udps_badsum);
- /*goto badunlocked;*/
+ goto badunlocked;
}
/*
@@ -361,20 +371,9 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
INP_RLOCK(last);
- up = intoudpcb(last);
- if (up->u_tun_func == NULL) {
- udp6_append(last, n, off, &fromsa);
- } else {
- /*
- * Engage the tunneling
- * protocol we will have to
- * leave the info_lock up,
- * since we are hunting
- * through multiple UDP's.
- *
- */
- (*up->u_tun_func)(n, off, last);
- }
+ UDP_PROBE(receive, NULL, last, ip6,
+ last, uh);
+ udp6_append(last, n, off, &fromsa);
INP_RUNLOCK(last);
}
}
@@ -404,16 +403,8 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
}
INP_RLOCK(last);
INP_INFO_RUNLOCK(pcbinfo);
- up = intoudpcb(last);
UDP_PROBE(receive, NULL, last, ip6, last, uh);
- if (up->u_tun_func == NULL) {
- udp6_append(last, m, off, &fromsa);
- } else {
- /*
- * Engage the tunneling protocol.
- */
- (*up->u_tun_func)(m, off, last);
- }
+ udp6_append(last, m, off, &fromsa);
INP_RUNLOCK(last);
return (IPPROTO_DONE);
}
@@ -492,15 +483,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
}
}
UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
- if (up->u_tun_func == NULL) {
- udp6_append(inp, m, off, &fromsa);
- } else {
- /*
- * Engage the tunneling protocol.
- */
-
- (*up->u_tun_func)(m, off, inp);
- }
+ udp6_append(inp, m, off, &fromsa);
INP_RUNLOCK(inp);
return (IPPROTO_DONE);
diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c
index 5268686..06f80df 100644
--- a/sys/netpfil/ipfw/ip_dummynet.c
+++ b/sys/netpfil/ipfw/ip_dummynet.c
@@ -2294,7 +2294,7 @@ static moduledata_t dummynet_mod = {
#define DN_SI_SUB SI_SUB_PROTO_IFATTACHDOMAIN
#define DN_MODEV_ORD (SI_ORDER_ANY - 128) /* after ipfw */
DECLARE_MODULE(dummynet, dummynet_mod, DN_SI_SUB, DN_MODEV_ORD);
-MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
+MODULE_DEPEND(dummynet, ipfw, 3, 3, 3);
MODULE_VERSION(dummynet, 3);
/*
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index a66f190..f0db362 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/condvar.h>
+#include <sys/counter.h>
#include <sys/eventhandler.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -52,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/rwlock.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
@@ -101,10 +103,6 @@ __FBSDID("$FreeBSD$");
* All ipfw global variables are here.
*/
-/* ipfw_vnet_ready controls when we are open for business */
-static VNET_DEFINE(int, ipfw_vnet_ready) = 0;
-#define V_ipfw_vnet_ready VNET(ipfw_vnet_ready)
-
static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
@@ -121,9 +119,20 @@ VNET_DEFINE(int, autoinc_step);
VNET_DEFINE(int, fw_one_pass) = 1;
VNET_DEFINE(unsigned int, fw_tables_max);
+VNET_DEFINE(unsigned int, fw_tables_sets) = 0; /* Don't use set-aware tables */
/* Use 128 tables by default */
static unsigned int default_fw_tables = IPFW_TABLES_DEFAULT;
+#ifndef LINEAR_SKIPTO
+static int jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
+ int tablearg, int jump_backwards);
+#define JUMP(ch, f, num, targ, back) jump_fast(ch, f, num, targ, back)
+#else
+static int jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
+ int tablearg, int jump_backwards);
+#define JUMP(ch, f, num, targ, back) jump_linear(ch, f, num, targ, back)
+#endif
+
/*
* Each rule belongs to one of 32 different sets (0..31).
* The variable set_disable contains one bit per set.
@@ -144,6 +153,9 @@ VNET_DEFINE(int, verbose_limit);
/* layer3_chain contains the list of rules for layer 3 */
VNET_DEFINE(struct ip_fw_chain, layer3_chain);
+/* ipfw_vnet_ready controls when we are open for business */
+VNET_DEFINE(int, ipfw_vnet_ready) = 0;
+
VNET_DEFINE(int, ipfw_nat_ready) = 0;
ipfw_nat_t *ipfw_nat_ptr = NULL;
@@ -156,6 +168,7 @@ ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
#ifdef SYSCTL_NODE
uint32_t dummy_def = IPFW_DEFAULT_RULE;
static int sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS);
+static int sysctl_ipfw_tables_sets(SYSCTL_HANDLER_ARGS);
SYSBEGIN(f3)
@@ -177,7 +190,10 @@ SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
"The default/max possible rule number.");
SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, tables_max,
CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_ipfw_table_num, "IU",
- "Maximum number of tables");
+ "Maximum number of concurrently used tables");
+SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, tables_sets,
+ CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_ipfw_tables_sets, "IU",
+ "Use per-set namespace for tables");
SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
&default_to_accept, 0,
"Make the default rule accept all packets.");
@@ -361,8 +377,8 @@ iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain,
/* Check by name or by IP address */
if (cmd->name[0] != '\0') { /* match by name */
if (cmd->name[0] == '\1') /* use tablearg to match */
- return ipfw_lookup_table_extended(chain, cmd->p.glob,
- ifp->if_xname, tablearg, IPFW_TABLE_INTERFACE);
+ return ipfw_lookup_table_extended(chain, cmd->p.kidx, 0,
+ &ifp->if_index, tablearg);
/* Check name */
if (cmd->p.glob) {
if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
@@ -789,9 +805,10 @@ set_match(struct ip_fw_args *args, int slot,
args->rule.rulenum = chain->map[slot]->rulenum;
}
+#ifndef LINEAR_SKIPTO
/*
* Helper function to enable cached rule lookups using
- * x_next and next_rule fields in ipfw rule.
+ * cached_id and cached_pos fields in ipfw rule.
*/
static int
jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
@@ -799,28 +816,51 @@ jump_fast(struct ip_fw_chain *chain, struct ip_fw *f, int num,
{
int f_pos;
- /* If possible use cached f_pos (in f->next_rule),
- * whose version is written in f->next_rule
+ /* If possible use cached f_pos (in f->cached_pos),
+ * whose version is written in f->cached_id
* (horrible hacks to avoid changing the ABI).
*/
- if (num != IP_FW_TABLEARG && (uintptr_t)f->x_next == chain->id)
- f_pos = (uintptr_t)f->next_rule;
+ if (num != IP_FW_TARG && f->cached_id == chain->id)
+ f_pos = f->cached_pos;
else {
- int i = IP_FW_ARG_TABLEARG(num);
+ int i = IP_FW_ARG_TABLEARG(chain, num, skipto);
/* make sure we do not jump backward */
if (jump_backwards == 0 && i <= f->rulenum)
i = f->rulenum + 1;
- f_pos = ipfw_find_rule(chain, i, 0);
+ if (chain->idxmap != NULL)
+ f_pos = chain->idxmap[i];
+ else
+ f_pos = ipfw_find_rule(chain, i, 0);
/* update the cache */
- if (num != IP_FW_TABLEARG) {
- f->next_rule = (void *)(uintptr_t)f_pos;
- f->x_next = (void *)(uintptr_t)chain->id;
+ if (num != IP_FW_TARG) {
+ f->cached_id = chain->id;
+ f->cached_pos = f_pos;
}
}
return (f_pos);
}
+#else
+/*
+ * Helper function to enable real fast rule lookups.
+ */
+static int
+jump_linear(struct ip_fw_chain *chain, struct ip_fw *f, int num,
+ int tablearg, int jump_backwards)
+{
+ int f_pos;
+
+ num = IP_FW_ARG_TABLEARG(chain, num, skipto);
+ /* make sure we do not jump backward */
+ if (jump_backwards == 0 && num <= f->rulenum)
+ num = f->rulenum + 1;
+ f_pos = chain->idxmap[num];
+
+ return (f_pos);
+}
+#endif
+#define TARG(k, f) IP_FW_ARG_TABLEARG(chain, k, f)
/*
* The main check routine for the firewall.
*
@@ -980,6 +1020,7 @@ ipfw_chk(struct ip_fw_args *args)
int is_ipv4 = 0;
int done = 0; /* flag to exit the outer loop */
+ IPFW_RLOCK_TRACKER;
if (m->m_flags & M_SKIP_FIREWALL || (! V_ipfw_vnet_ready))
return (IP_FW_PASS); /* accept */
@@ -1467,9 +1508,9 @@ do { \
proto != IPPROTO_UDP)
break;
else if (v == 2)
- key = htonl(dst_port);
+ key = dst_port;
else if (v == 3)
- key = htonl(src_port);
+ key = src_port;
#ifndef USERSPACE
else if (v == 4 || v == 5) {
check_uidgid(
@@ -1488,7 +1529,6 @@ do { \
else if (v == 5 /* O_JAIL */)
key = ucred_cache.xid;
#endif /* !__FreeBSD__ */
- key = htonl(key);
} else
#endif /* !USERSPACE */
break;
@@ -1507,8 +1547,9 @@ do { \
void *pkey = (cmd->opcode == O_IP_DST_LOOKUP) ?
&args->f_id.dst_ip6: &args->f_id.src_ip6;
match = ipfw_lookup_table_extended(chain,
- cmd->arg1, pkey, &v,
- IPFW_TABLE_CIDR);
+ cmd->arg1,
+ sizeof(struct in6_addr),
+ pkey, &v);
if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
if (match)
@@ -1516,6 +1557,17 @@ do { \
}
break;
+ case O_IP_FLOW_LOOKUP:
+ {
+ uint32_t v = 0;
+ match = ipfw_lookup_table_extended(chain,
+ cmd->arg1, 0, &args->f_id, &v);
+ if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
+ match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
+ if (match)
+ tablearg = v;
+ }
+ break;
case O_IP_SRC_MASK:
case O_IP_DST_MASK:
if (is_ipv4) {
@@ -1722,9 +1774,11 @@ do { \
break;
case O_TCPOPTS:
- PULLUP_LEN(hlen, ulp, (TCP(ulp)->th_off << 2));
- match = (proto == IPPROTO_TCP && offset == 0 &&
- tcpopts_match(TCP(ulp), cmd));
+ if (proto == IPPROTO_TCP && offset == 0 && ulp){
+ PULLUP_LEN(hlen, ulp,
+ (TCP(ulp)->th_off << 2));
+ match = tcpopts_match(TCP(ulp), cmd);
+ }
break;
case O_TCPSEQ:
@@ -1798,7 +1852,7 @@ do { \
}
case O_LOG:
- ipfw_log(f, hlen, args, m,
+ ipfw_log(chain, f, hlen, args, m,
oif, offset | ip6f_mf, tablearg, ip);
match = 1;
break;
@@ -1920,7 +1974,7 @@ do { \
case O_TAG: {
struct m_tag *mtag;
- uint32_t tag = IP_FW_ARG_TABLEARG(cmd->arg1);
+ uint32_t tag = TARG(cmd->arg1, tag);
/* Packet is already tagged with this tag? */
mtag = m_tag_locate(m, MTAG_IPFW, tag, NULL);
@@ -2001,7 +2055,7 @@ do { \
case O_TAGGED: {
struct m_tag *mtag;
- uint32_t tag = IP_FW_ARG_TABLEARG(cmd->arg1);
+ uint32_t tag = TARG(cmd->arg1, tag);
if (cmdlen == 1) {
match = m_tag_locate(m, MTAG_IPFW,
@@ -2072,7 +2126,7 @@ do { \
*/
case O_LIMIT:
case O_KEEP_STATE:
- if (ipfw_install_state(f,
+ if (ipfw_install_state(chain, f,
(ipfw_insn_limit *)cmd, args, tablearg)) {
/* error or limit violation */
retval = IP_FW_DENY;
@@ -2139,7 +2193,7 @@ do { \
case O_PIPE:
case O_QUEUE:
set_match(args, f_pos, chain);
- args->rule.info = IP_FW_ARG_TABLEARG(cmd->arg1);
+ args->rule.info = TARG(cmd->arg1, pipe);
if (cmd->opcode == O_PIPE)
args->rule.info |= IPFW_IS_PIPE;
if (V_fw_one_pass)
@@ -2159,7 +2213,7 @@ do { \
retval = (cmd->opcode == O_DIVERT) ?
IP_FW_DIVERT : IP_FW_TEE;
set_match(args, f_pos, chain);
- args->rule.info = IP_FW_ARG_TABLEARG(cmd->arg1);
+ args->rule.info = TARG(cmd->arg1, divert);
break;
case O_COUNT:
@@ -2169,7 +2223,7 @@ do { \
case O_SKIPTO:
IPFW_INC_RULE_COUNTER(f, pktlen);
- f_pos = jump_fast(chain, f, cmd->arg1, tablearg, 0);
+ f_pos = JUMP(chain, f, cmd->arg1, tablearg, 0);
/*
* Skip disabled rules, and re-enter
* the inner loop with the correct
@@ -2258,7 +2312,7 @@ do { \
if (IS_CALL) {
stack[mtag->m_tag_id] = f->rulenum;
mtag->m_tag_id++;
- f_pos = jump_fast(chain, f, cmd->arg1,
+ f_pos = JUMP(chain, f, cmd->arg1,
tablearg, 1);
} else { /* `return' action */
mtag->m_tag_id--;
@@ -2366,7 +2420,7 @@ do { \
case O_NETGRAPH:
case O_NGTEE:
set_match(args, f_pos, chain);
- args->rule.info = IP_FW_ARG_TABLEARG(cmd->arg1);
+ args->rule.info = TARG(cmd->arg1, netgraph);
if (V_fw_one_pass)
args->rule.info |= IPFW_ONEPASS;
retval = (cmd->opcode == O_NETGRAPH) ?
@@ -2379,7 +2433,7 @@ do { \
uint32_t fib;
IPFW_INC_RULE_COUNTER(f, pktlen);
- fib = IP_FW_ARG_TABLEARG(cmd->arg1);
+ fib = TARG(cmd->arg1, fib) & 0x7FFFF;
if (fib >= rt_numfibs)
fib = 0;
M_SETFIB(m, fib);
@@ -2391,7 +2445,7 @@ do { \
case O_SETDSCP: {
uint16_t code;
- code = IP_FW_ARG_TABLEARG(cmd->arg1) & 0x3F;
+ code = TARG(cmd->arg1, dscp) & 0x3F;
l = 0; /* exit inner loop */
if (is_ipv4) {
uint16_t a;
@@ -2433,14 +2487,14 @@ do { \
}
t = ((ipfw_insn_nat *)cmd)->nat;
if (t == NULL) {
- nat_id = IP_FW_ARG_TABLEARG(cmd->arg1);
+ nat_id = TARG(cmd->arg1, nat);
t = (*lookup_nat_ptr)(&chain->nat, nat_id);
if (t == NULL) {
retval = IP_FW_DENY;
break;
}
- if (cmd->arg1 != IP_FW_TABLEARG)
+ if (cmd->arg1 != IP_FW_TARG)
((ipfw_insn_nat *)cmd)->nat = t;
}
retval = ipfw_nat_ptr(args, t, m);
@@ -2549,6 +2603,25 @@ sysctl_ipfw_table_num(SYSCTL_HANDLER_ARGS)
return (ipfw_resize_tables(&V_layer3_chain, ntables));
}
+
+/*
+ * Switches table namespace between global and per-set.
+ */
+static int
+sysctl_ipfw_tables_sets(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ unsigned int sets;
+
+ sets = V_fw_tables_sets;
+
+ error = sysctl_handle_int(oidp, &sets, 0, req);
+ /* Read operation or some error */
+ if ((error != 0) || (req->newptr == NULL))
+ return (error);
+
+ return (ipfw_switch_tables_namespace(&V_layer3_chain, sets));
+}
#endif
/*
@@ -2604,7 +2677,9 @@ ipfw_init(void)
if (default_fw_tables > IPFW_TABLES_MAX)
default_fw_tables = IPFW_TABLES_MAX;
+ ipfw_init_sopt_handler();
ipfw_log_bpf(1); /* init */
+ ipfw_iface_init();
return (error);
}
@@ -2615,7 +2690,9 @@ static void
ipfw_destroy(void)
{
+ ipfw_iface_destroy();
ipfw_log_bpf(0); /* uninit */
+ ipfw_destroy_sopt_handler();
printf("IP firewall unloaded\n");
}
@@ -2626,12 +2703,14 @@ ipfw_destroy(void)
static int
vnet_ipfw_init(const void *unused)
{
- int error;
+ int error, first;
struct ip_fw *rule = NULL;
struct ip_fw_chain *chain;
chain = &V_layer3_chain;
+ first = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
+
/* First set up some values that are compile time options */
V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
V_fw_deny_unknown_exthdrs = 1;
@@ -2645,16 +2724,15 @@ vnet_ipfw_init(const void *unused)
LIST_INIT(&chain->nat);
#endif
+ ipfw_init_counters();
/* insert the default rule and create the initial map */
chain->n_rules = 1;
- chain->static_len = sizeof(struct ip_fw);
chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
- if (chain->map)
- rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO);
+ rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
/* Set initial number of tables */
V_fw_tables_max = default_fw_tables;
- error = ipfw_init_tables(chain);
+ error = ipfw_init_tables(chain, first);
if (error) {
printf("ipfw2: setting up tables failed\n");
free(chain->map, M_IPFW);
@@ -2671,9 +2749,14 @@ vnet_ipfw_init(const void *unused)
rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
chain->default_rule = chain->map[0] = rule;
chain->id = rule->id = 1;
+ /* Pre-calculate rules length for legacy dump format */
+ chain->static_len = sizeof(struct ip_fw_rule0);
IPFW_LOCK_INIT(chain);
ipfw_dyn_init(chain);
+#ifdef LINEAR_SKIPTO
+ ipfw_init_skipto_cache(chain);
+#endif
/* First set up some values that are compile time options */
V_ipfw_vnet_ready = 1; /* Open for business */
@@ -2691,7 +2774,7 @@ vnet_ipfw_init(const void *unused)
* In layer2 we have the same behaviour, except that V_ether_ipfw
* is checked on each packet because there are no pfil hooks.
*/
- V_ip_fw_ctl_ptr = ipfw_ctl;
+ V_ip_fw_ctl_ptr = ipfw_ctl3;
error = ipfw_attach_hooks(1);
return (error);
}
@@ -2702,9 +2785,9 @@ vnet_ipfw_init(const void *unused)
static int
vnet_ipfw_uninit(const void *unused)
{
- struct ip_fw *reap, *rule;
+ struct ip_fw *reap;
struct ip_fw_chain *chain = &V_layer3_chain;
- int i;
+ int i, last;
V_ipfw_vnet_ready = 0; /* tell new callers to go away */
/*
@@ -2714,6 +2797,9 @@ vnet_ipfw_uninit(const void *unused)
*/
(void)ipfw_attach_hooks(0 /* detach */);
V_ip_fw_ctl_ptr = NULL;
+
+ last = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
+
IPFW_UH_WLOCK(chain);
IPFW_UH_WUNLOCK(chain);
IPFW_UH_WLOCK(chain);
@@ -2722,22 +2808,23 @@ vnet_ipfw_uninit(const void *unused)
ipfw_dyn_uninit(0); /* run the callout_drain */
IPFW_WUNLOCK(chain);
- ipfw_destroy_tables(chain);
reap = NULL;
IPFW_WLOCK(chain);
- for (i = 0; i < chain->n_rules; i++) {
- rule = chain->map[i];
- rule->x_next = reap;
- reap = rule;
- }
- if (chain->map)
- free(chain->map, M_IPFW);
+ for (i = 0; i < chain->n_rules; i++)
+ ipfw_reap_add(chain, &reap, chain->map[i]);
+ free(chain->map, M_IPFW);
+#ifdef LINEAR_SKIPTO
+ ipfw_destroy_skipto_cache(chain);
+#endif
IPFW_WUNLOCK(chain);
IPFW_UH_WUNLOCK(chain);
+ ipfw_destroy_tables(chain, last);
if (reap != NULL)
ipfw_reap_rules(reap);
+ vnet_ipfw_iface_destroy(chain);
IPFW_LOCK_DESTROY(chain);
ipfw_dyn_uninit(1); /* free the remaining parts */
+ ipfw_destroy_counters();
return (0);
}
@@ -2789,7 +2876,8 @@ static moduledata_t ipfwmod = {
#define IPFW_VNET_ORDER (IPFW_MODEVENT_ORDER + 2) /* Later still. */
DECLARE_MODULE(ipfw, ipfwmod, IPFW_SI_SUB_FIREWALL, IPFW_MODEVENT_ORDER);
-MODULE_VERSION(ipfw, 2);
+FEATURE(ipfw_ctl3, "ipfw new sockopt calls");
+MODULE_VERSION(ipfw, 3);
/* should declare some dependencies here */
/*
diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c
index af546f4..e585362 100644
--- a/sys/netpfil/ipfw/ip_fw_dynamic.c
+++ b/sys/netpfil/ipfw/ip_fw_dynamic.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/lock.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
@@ -196,8 +197,7 @@ static int ipfw_dyn_count; /* number of objects */
static int last_log; /* Log ratelimiting */
static void ipfw_dyn_tick(void *vnetx);
-static void check_dyn_rules(struct ip_fw_chain *, struct ip_fw *,
- int, int, int);
+static void check_dyn_rules(struct ip_fw_chain *, ipfw_range_tlv *, int, int);
#ifdef SYSCTL_NODE
static int sysctl_ipfw_dyn_count(SYSCTL_HANDLER_ARGS);
@@ -673,8 +673,8 @@ lookup_dyn_parent(struct ipfw_flow_id *pkt, int *pindex, struct ip_fw *rule)
* session limitations are enforced.
*/
int
-ipfw_install_state(struct ip_fw *rule, ipfw_insn_limit *cmd,
- struct ip_fw_args *args, uint32_t tablearg)
+ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
+ ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg)
{
ipfw_dyn_rule *q;
int i;
@@ -717,10 +717,10 @@ ipfw_install_state(struct ip_fw *rule, ipfw_insn_limit *cmd,
uint16_t limit_mask = cmd->limit_mask;
int pindex;
- conn_limit = IP_FW_ARG_TABLEARG(cmd->conn_limit);
+ conn_limit = IP_FW_ARG_TABLEARG(chain, cmd->conn_limit, limit);
DEB(
- if (cmd->conn_limit == IP_FW_TABLEARG)
+ if (cmd->conn_limit == IP_FW_TARG)
printf("ipfw: %s: O_LIMIT rule, conn_limit: %u "
"(tablearg)\n", __func__, conn_limit);
else
@@ -1008,7 +1008,7 @@ ipfw_dyn_tick(void * vnetx)
check_ka = 1;
}
- check_dyn_rules(chain, NULL, RESVD_SET, check_ka, 1);
+ check_dyn_rules(chain, NULL, check_ka, 1);
callout_reset_on(&V_ipfw_timeout, hz, ipfw_dyn_tick, vnetx, 0);
@@ -1040,8 +1040,8 @@ ipfw_dyn_tick(void * vnetx)
* are not freed by other instance (see stage 2, 3)
*/
static void
-check_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule,
- int set, int check_ka, int timer)
+check_dyn_rules(struct ip_fw_chain *chain, ipfw_range_tlv *rt,
+ int check_ka, int timer)
{
struct mbuf *m0, *m, *mnext, **mtailp;
struct ip *h;
@@ -1105,12 +1105,10 @@ check_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule,
/*
* Remove rules which are:
* 1) expired
- * 2) created by given rule
- * 3) created by any rule in given set
+ * 2) matches deletion range
*/
if ((TIME_LEQ(q->expire, time_uptime)) ||
- ((rule != NULL) && (q->rule == rule)) ||
- ((set != RESVD_SET) && (q->rule->set == set))) {
+ (rt != NULL && ipfw_match_range(q->rule, rt))) {
if (TIME_LE(time_uptime, q->expire) &&
q->dyn_type == O_KEEP_STATE &&
V_dyn_keep_states != 0) {
@@ -1324,8 +1322,7 @@ check_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule,
* Deletes all dynamic rules originated by given rule or all rules in
* given set. Specify RESVD_SET to indicate set should not be used.
* @chain - pointer to current ipfw rules chain
- * @rule - delete all states originated by given rule if != NULL
- * @set - delete all states originated by any rule in set @set if != RESVD_SET
+ * @rr - delete all states originated by rules in matched range.
*
* Function has to be called with IPFW_UH_WLOCK held.
* Additionally, function assume that dynamic rule/set is
@@ -1333,10 +1330,39 @@ check_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule,
* 'deleted' rules.
*/
void
-ipfw_expire_dyn_rules(struct ip_fw_chain *chain, struct ip_fw *rule, int set)
+ipfw_expire_dyn_rules(struct ip_fw_chain *chain, ipfw_range_tlv *rt)
{
- check_dyn_rules(chain, rule, set, 0, 0);
+ check_dyn_rules(chain, rt, 0, 0);
+}
+
+/*
+ * Check if rule contains at least one dynamic opcode.
+ *
+ * Returns 1 if such opcode is found, 0 otherwise.
+ */
+int
+ipfw_is_dyn_rule(struct ip_fw *rule)
+{
+ int cmdlen, l;
+ ipfw_insn *cmd;
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ switch (cmd->opcode) {
+ case O_LIMIT:
+ case O_KEEP_STATE:
+ case O_PROBE_STATE:
+ case O_CHECK_STATE:
+ return (1);
+ }
+ }
+
+ return (0);
}
void
@@ -1444,7 +1470,7 @@ sysctl_ipfw_dyn_count(SYSCTL_HANDLER_ARGS)
#endif
/*
- * Returns number of dynamic rules.
+ * Returns size of dynamic states in legacy format
*/
int
ipfw_dyn_len(void)
@@ -1455,7 +1481,92 @@ ipfw_dyn_len(void)
}
/*
- * Fill given buffer with dynamic states.
+ * Returns number of dynamic states.
+ * Used by dump format v1 (current).
+ */
+int
+ipfw_dyn_get_count(void)
+{
+
+ return (V_ipfw_dyn_v == NULL) ? 0 : DYN_COUNT;
+}
+
+static void
+export_dyn_rule(ipfw_dyn_rule *src, ipfw_dyn_rule *dst)
+{
+
+ memcpy(dst, src, sizeof(*src));
+ memcpy(&(dst->rule), &(src->rule->rulenum), sizeof(src->rule->rulenum));
+ /*
+ * store set number into high word of
+ * dst->rule pointer.
+ */
+ memcpy((char *)&dst->rule + sizeof(src->rule->rulenum),
+ &(src->rule->set), sizeof(src->rule->set));
+ /*
+ * store a non-null value in "next".
+ * The userland code will interpret a
+ * NULL here as a marker
+ * for the last dynamic rule.
+ */
+ memcpy(&dst->next, &dst, sizeof(dst));
+ dst->expire =
+ TIME_LEQ(dst->expire, time_uptime) ? 0 : dst->expire - time_uptime;
+}
+
+/*
+ * Fills int buffer given by @sd with dynamic states.
+ * Used by dump format v1 (current).
+ *
+ * Returns 0 on success.
+ */
+int
+ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd)
+{
+ ipfw_dyn_rule *p;
+ ipfw_obj_dyntlv *dst, *last;
+ ipfw_obj_ctlv *ctlv;
+ int i;
+ size_t sz;
+
+ if (V_ipfw_dyn_v == NULL)
+ return (0);
+
+ IPFW_UH_RLOCK_ASSERT(chain);
+
+ ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv));
+ if (ctlv == NULL)
+ return (ENOMEM);
+ sz = sizeof(ipfw_obj_dyntlv);
+ ctlv->head.type = IPFW_TLV_DYNSTATE_LIST;
+ ctlv->objsize = sz;
+ last = NULL;
+
+ for (i = 0 ; i < V_curr_dyn_buckets; i++) {
+ IPFW_BUCK_LOCK(i);
+ for (p = V_ipfw_dyn_v[i].head ; p != NULL; p = p->next) {
+ dst = (ipfw_obj_dyntlv *)ipfw_get_sopt_space(sd, sz);
+ if (dst == NULL) {
+ IPFW_BUCK_UNLOCK(i);
+ return (ENOMEM);
+ }
+
+ export_dyn_rule(p, &dst->state);
+ dst->head.length = sz;
+ dst->head.type = IPFW_TLV_DYN_ENT;
+ last = dst;
+ }
+ IPFW_BUCK_UNLOCK(i);
+ }
+
+ if (last != NULL) /* mark last dynamic rule */
+ last->head.flags = IPFW_DF_LAST;
+
+ return (0);
+}
+
+/*
+ * Fill given buffer with dynamic states (legacy format).
* IPFW_UH_RLOCK has to be held while calling.
*/
void
@@ -1477,28 +1588,9 @@ ipfw_get_dynamic(struct ip_fw_chain *chain, char **pbp, const char *ep)
if (bp + sizeof *p <= ep) {
ipfw_dyn_rule *dst =
(ipfw_dyn_rule *)bp;
- bcopy(p, dst, sizeof *p);
- bcopy(&(p->rule->rulenum), &(dst->rule),
- sizeof(p->rule->rulenum));
- /*
- * store set number into high word of
- * dst->rule pointer.
- */
- bcopy(&(p->rule->set),
- (char *)&dst->rule +
- sizeof(p->rule->rulenum),
- sizeof(p->rule->set));
- /*
- * store a non-null value in "next".
- * The userland code will interpret a
- * NULL here as a marker
- * for the last dynamic rule.
- */
- bcopy(&dst, &dst->next, sizeof(dst));
+
+ export_dyn_rule(p, dst);
last = dst;
- dst->expire =
- TIME_LEQ(dst->expire, time_uptime) ?
- 0 : dst->expire - time_uptime ;
bp += sizeof(ipfw_dyn_rule);
}
}
diff --git a/sys/netpfil/ipfw/ip_fw_iface.c b/sys/netpfil/ipfw/ip_fw_iface.c
new file mode 100644
index 0000000..7e9c992
--- /dev/null
+++ b/sys/netpfil/ipfw/ip_fw_iface.c
@@ -0,0 +1,537 @@
+/*-
+ * Copyright (c) 2014 Yandex LLC.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_iface.c 267384 2014-06-12 09:59:11Z melifaro $");
+
+/*
+ * Kernel interface tracking API.
+ *
+ */
+
+#include "opt_ipfw.h"
+#include "opt_inet.h"
+#ifndef INET
+#error IPFIREWALL requires INET.
+#endif /* INET */
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
+#include <sys/rmlock.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/eventhandler.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/vnet.h>
+
+#include <netinet/in.h>
+#include <netinet/ip_var.h> /* struct ipfw_rule_ref */
+#include <netinet/ip_fw.h>
+
+#include <netpfil/ipfw/ip_fw_private.h>
+
+#define CHAIN_TO_II(ch) ((struct namedobj_instance *)ch->ifcfg)
+
+#define DEFAULT_IFACES 128
+
+static void handle_ifdetach(struct ip_fw_chain *ch, struct ipfw_iface *iif,
+ uint16_t ifindex);
+static void handle_ifattach(struct ip_fw_chain *ch, struct ipfw_iface *iif,
+ uint16_t ifindex);
+static int list_ifaces(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+
+static struct ipfw_sopt_handler scodes[] = {
+ { IP_FW_XIFLIST, 0, HDIR_GET, list_ifaces },
+};
+
+/*
+ * FreeBSD Kernel interface.
+ */
+static void ipfw_kifhandler(void *arg, struct ifnet *ifp);
+static int ipfw_kiflookup(char *name);
+static void iface_khandler_register(void);
+static void iface_khandler_deregister(void);
+
+static eventhandler_tag ipfw_ifdetach_event, ipfw_ifattach_event;
+static int num_vnets = 0;
+static struct mtx vnet_mtx;
+
+/*
+ * Checks if kernel interface is contained in our tracked
+ * interface list and calls attach/detach handler.
+ */
+static void
+ipfw_kifhandler(void *arg, struct ifnet *ifp)
+{
+ struct ip_fw_chain *ch;
+ struct ipfw_iface *iif;
+ struct namedobj_instance *ii;
+ uintptr_t htype;
+
+ if (V_ipfw_vnet_ready == 0)
+ return;
+
+ ch = &V_layer3_chain;
+ htype = (uintptr_t)arg;
+
+ IPFW_UH_WLOCK(ch);
+ ii = CHAIN_TO_II(ch);
+ if (ii == NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ return;
+ }
+ iif = (struct ipfw_iface*)ipfw_objhash_lookup_name(ii, 0,
+ if_name(ifp));
+ if (iif != NULL) {
+ if (htype == 1)
+ handle_ifattach(ch, iif, ifp->if_index);
+ else
+ handle_ifdetach(ch, iif, ifp->if_index);
+ }
+ IPFW_UH_WUNLOCK(ch);
+}
+
+/*
+ * Reference current VNET as iface tracking API user.
+ * Registers interface tracking handlers for first VNET.
+ */
+static void
+iface_khandler_register()
+{
+ int create;
+
+ create = 0;
+
+ mtx_lock(&vnet_mtx);
+ if (num_vnets == 0)
+ create = 1;
+ num_vnets++;
+ mtx_unlock(&vnet_mtx);
+
+ if (create == 0)
+ return;
+
+ printf("IPFW: starting up interface tracker\n");
+
+ ipfw_ifdetach_event = EVENTHANDLER_REGISTER(
+ ifnet_departure_event, ipfw_kifhandler, NULL,
+ EVENTHANDLER_PRI_ANY);
+ ipfw_ifattach_event = EVENTHANDLER_REGISTER(
+ ifnet_arrival_event, ipfw_kifhandler, (void*)((uintptr_t)1),
+ EVENTHANDLER_PRI_ANY);
+}
+
+/*
+ *
+ * Detach interface event handlers on last VNET instance
+ * detach.
+ */
+static void
+iface_khandler_deregister()
+{
+ int destroy;
+
+ destroy = 0;
+ mtx_lock(&vnet_mtx);
+ if (num_vnets == 1)
+ destroy = 1;
+ num_vnets--;
+ mtx_unlock(&vnet_mtx);
+
+ if (destroy == 0)
+ return;
+
+ EVENTHANDLER_DEREGISTER(ifnet_arrival_event,
+ ipfw_ifattach_event);
+ EVENTHANDLER_DEREGISTER(ifnet_departure_event,
+ ipfw_ifdetach_event);
+}
+
+/*
+ * Retrieves ifindex for given @name.
+ *
+ * Returns ifindex or 0.
+ */
+static int
+ipfw_kiflookup(char *name)
+{
+ struct ifnet *ifp;
+ int ifindex;
+
+ ifindex = 0;
+
+ if ((ifp = ifunit_ref(name)) != NULL) {
+ ifindex = ifp->if_index;
+ if_rele(ifp);
+ }
+
+ return (ifindex);
+}
+
+/*
+ * Global ipfw startup hook.
+ * Since we perform lazy initialization, do nothing except
+ * mutex init.
+ */
+int
+ipfw_iface_init()
+{
+
+ mtx_init(&vnet_mtx, "IPFW ifhandler mtx", NULL, MTX_DEF);
+ IPFW_ADD_SOPT_HANDLER(1, scodes);
+ return (0);
+}
+
+/*
+ * Global ipfw destroy hook.
+ * Unregister khandlers iff init has been done.
+ */
+void
+ipfw_iface_destroy()
+{
+
+ IPFW_DEL_SOPT_HANDLER(1, scodes);
+ mtx_destroy(&vnet_mtx);
+}
+
+/*
+ * Perform actual init on internal request.
+ * Inits both namehash and global khandler.
+ */
+static void
+vnet_ipfw_iface_init(struct ip_fw_chain *ch)
+{
+ struct namedobj_instance *ii;
+
+ ii = ipfw_objhash_create(DEFAULT_IFACES);
+ IPFW_UH_WLOCK(ch);
+ if (ch->ifcfg == NULL) {
+ ch->ifcfg = ii;
+ ii = NULL;
+ }
+ IPFW_UH_WUNLOCK(ch);
+
+ if (ii != NULL) {
+ /* Already initialized. Free namehash. */
+ ipfw_objhash_destroy(ii);
+ } else {
+ /* We're the first ones. Init kernel hooks. */
+ iface_khandler_register();
+ }
+}
+
+static void
+destroy_iface(struct namedobj_instance *ii, struct named_object *no,
+ void *arg)
+{
+
+ /* Assume all consumers have been already detached */
+ free(no, M_IPFW);
+}
+
+/*
+ * Per-VNET ipfw detach hook.
+ *
+ */
+void
+vnet_ipfw_iface_destroy(struct ip_fw_chain *ch)
+{
+ struct namedobj_instance *ii;
+
+ IPFW_UH_WLOCK(ch);
+ ii = CHAIN_TO_II(ch);
+ ch->ifcfg = NULL;
+ IPFW_UH_WUNLOCK(ch);
+
+ if (ii != NULL) {
+ ipfw_objhash_foreach(ii, destroy_iface, ch);
+ ipfw_objhash_destroy(ii);
+ iface_khandler_deregister();
+ }
+}
+
+/*
+ * Notify the subsystem that we are interested in tracking
+ * interface @name. This function has to be called without
+ * holding any locks to permit allocating the necessary states
+ * for proper interface tracking.
+ *
+ * Returns 0 on success.
+ */
+int
+ipfw_iface_ref(struct ip_fw_chain *ch, char *name,
+ struct ipfw_ifc *ic)
+{
+ struct namedobj_instance *ii;
+ struct ipfw_iface *iif, *tmp;
+
+ if (strlen(name) >= sizeof(iif->ifname))
+ return (EINVAL);
+
+ IPFW_UH_WLOCK(ch);
+
+ ii = CHAIN_TO_II(ch);
+ if (ii == NULL) {
+
+ /*
+ * First request to subsystem.
+ * Let's perform init.
+ */
+ IPFW_UH_WUNLOCK(ch);
+ vnet_ipfw_iface_init(ch);
+ IPFW_UH_WLOCK(ch);
+ ii = CHAIN_TO_II(ch);
+ }
+
+ iif = (struct ipfw_iface *)ipfw_objhash_lookup_name(ii, 0, name);
+
+ if (iif != NULL) {
+ iif->no.refcnt++;
+ ic->iface = iif;
+ IPFW_UH_WUNLOCK(ch);
+ return (0);
+ }
+
+ IPFW_UH_WUNLOCK(ch);
+
+ /* Not found. Let's create one */
+ iif = malloc(sizeof(struct ipfw_iface), M_IPFW, M_WAITOK | M_ZERO);
+ TAILQ_INIT(&iif->consumers);
+ iif->no.name = iif->ifname;
+ strlcpy(iif->ifname, name, sizeof(iif->ifname));
+
+ /*
+ * Ref & link to the list.
+ *
+ * We assume ifnet_arrival_event / ifnet_departure_event
+ * are not holding any locks.
+ */
+ iif->no.refcnt = 1;
+ IPFW_UH_WLOCK(ch);
+
+ tmp = (struct ipfw_iface *)ipfw_objhash_lookup_name(ii, 0, name);
+ if (tmp != NULL) {
+ /* Interface has been created since unlock. Ref and return */
+ tmp->no.refcnt++;
+ ic->iface = tmp;
+ IPFW_UH_WUNLOCK(ch);
+ free(iif, M_IPFW);
+ return (0);
+ }
+
+ iif->ifindex = ipfw_kiflookup(name);
+ if (iif->ifindex != 0)
+ iif->resolved = 1;
+
+ ipfw_objhash_add(ii, &iif->no);
+ ic->iface = iif;
+
+ IPFW_UH_WUNLOCK(ch);
+
+ return (0);
+}
+
+/*
+ * Adds @ic to the list of iif interface consumers.
+ * Must be called with holding both UH+WLOCK.
+ * Callback may be immediately called (if interface exists).
+ */
+void
+ipfw_iface_add_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic)
+{
+ struct ipfw_iface *iif;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+ IPFW_WLOCK_ASSERT(ch);
+
+ iif = ic->iface;
+
+ TAILQ_INSERT_TAIL(&iif->consumers, ic, next);
+ if (iif->resolved != 0)
+ ic->cb(ch, ic->cbdata, iif->ifindex);
+}
+
+/*
+ * Unlinks interface tracker object @ic from interface.
+ * Must be called while holding UH lock.
+ */
+void
+ipfw_iface_del_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic)
+{
+ struct ipfw_iface *iif;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ iif = ic->iface;
+ TAILQ_REMOVE(&iif->consumers, ic, next);
+}
+
+/*
+ * Unreference interface specified by @ic.
+ * Must be called without holding any locks.
+ */
+void
+ipfw_iface_unref(struct ip_fw_chain *ch, struct ipfw_ifc *ic)
+{
+ struct ipfw_iface *iif;
+
+ iif = ic->iface;
+ ic->iface = NULL;
+
+ IPFW_UH_WLOCK(ch);
+ iif->no.refcnt--;
+ /* TODO: check for references & delete */
+ IPFW_UH_WUNLOCK(ch);
+}
+
+/*
+ * Interface arrival handler.
+ */
+static void
+handle_ifattach(struct ip_fw_chain *ch, struct ipfw_iface *iif,
+ uint16_t ifindex)
+{
+ struct ipfw_ifc *ic;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ iif->gencnt++;
+ iif->resolved = 1;
+ iif->ifindex = ifindex;
+
+ IPFW_WLOCK(ch);
+ TAILQ_FOREACH(ic, &iif->consumers, next)
+ ic->cb(ch, ic->cbdata, iif->ifindex);
+ IPFW_WUNLOCK(ch);
+}
+
+/*
+ * Interface departure handler.
+ */
+static void
+handle_ifdetach(struct ip_fw_chain *ch, struct ipfw_iface *iif,
+ uint16_t ifindex)
+{
+ struct ipfw_ifc *ic;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ IPFW_WLOCK(ch);
+ TAILQ_FOREACH(ic, &iif->consumers, next)
+ ic->cb(ch, ic->cbdata, 0);
+ IPFW_WUNLOCK(ch);
+
+ iif->gencnt++;
+ iif->resolved = 0;
+ iif->ifindex = 0;
+}
+
+struct dump_iface_args {
+ struct ip_fw_chain *ch;
+ struct sockopt_data *sd;
+};
+
+static void
+export_iface_internal(struct namedobj_instance *ii, struct named_object *no,
+ void *arg)
+{
+ ipfw_iface_info *i;
+ struct dump_iface_args *da;
+ struct ipfw_iface *iif;
+
+ da = (struct dump_iface_args *)arg;
+
+ i = (ipfw_iface_info *)ipfw_get_sopt_space(da->sd, sizeof(*i));
+ KASSERT(i != 0, ("previously checked buffer is not enough"));
+
+ iif = (struct ipfw_iface *)no;
+
+ strlcpy(i->ifname, iif->ifname, sizeof(i->ifname));
+ if (iif->resolved)
+ i->flags |= IPFW_IFFLAG_RESOLVED;
+ i->ifindex = iif->ifindex;
+ i->refcnt = iif->no.refcnt;
+ i->gencnt = iif->gencnt;
+}
+
+/*
+ * Lists all interface currently tracked by ipfw.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_iface_info x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+list_ifaces(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ struct namedobj_instance *ii;
+ struct _ipfw_obj_lheader *olh;
+ struct dump_iface_args da;
+ uint32_t count, size;
+
+ olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
+ if (olh == NULL)
+ return (EINVAL);
+ if (sd->valsize < olh->size)
+ return (EINVAL);
+
+ IPFW_UH_RLOCK(ch);
+ ii = CHAIN_TO_II(ch);
+ if (ii != NULL)
+ count = ipfw_objhash_count(ii);
+ else
+ count = 0;
+ size = count * sizeof(ipfw_iface_info) + sizeof(ipfw_obj_lheader);
+
+ /* Fill in header regadless of buffer size */
+ olh->count = count;
+ olh->objsize = sizeof(ipfw_iface_info);
+
+ if (size > olh->size) {
+ olh->size = size;
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOMEM);
+ }
+ olh->size = size;
+
+ da.ch = ch;
+ da.sd = sd;
+
+ if (ii != NULL)
+ ipfw_objhash_foreach(ii, export_iface_internal, &da);
+ IPFW_UH_RUNLOCK(ch);
+
+ return (0);
+}
+
diff --git a/sys/netpfil/ipfw/ip_fw_log.c b/sys/netpfil/ipfw/ip_fw_log.c
index b9ef96d..ef7b35a 100644
--- a/sys/netpfil/ipfw/ip_fw_log.c
+++ b/sys/netpfil/ipfw/ip_fw_log.c
@@ -240,14 +240,15 @@ ipfw_log_bpf(int onoff)
}
#endif /* !WITHOUT_BPF */
+#define TARG(k, f) IP_FW_ARG_TABLEARG(chain, k, f)
/*
* We enter here when we have a rule with O_LOG.
* XXX this function alone takes about 2Kbytes of code!
*/
void
-ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
- struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg,
- struct ip *ip)
+ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
+ struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif,
+ u_short offset, uint32_t tablearg, struct ip *ip)
{
char *action;
int limit_reached = 0;
@@ -343,27 +344,27 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
break;
case O_DIVERT:
snprintf(SNPARGS(action2, 0), "Divert %d",
- cmd->arg1);
+ TARG(cmd->arg1, divert));
break;
case O_TEE:
snprintf(SNPARGS(action2, 0), "Tee %d",
- cmd->arg1);
+ TARG(cmd->arg1, divert));
break;
case O_SETFIB:
snprintf(SNPARGS(action2, 0), "SetFib %d",
- IP_FW_ARG_TABLEARG(cmd->arg1));
+ TARG(cmd->arg1, fib));
break;
case O_SKIPTO:
snprintf(SNPARGS(action2, 0), "SkipTo %d",
- IP_FW_ARG_TABLEARG(cmd->arg1));
+ TARG(cmd->arg1, skipto));
break;
case O_PIPE:
snprintf(SNPARGS(action2, 0), "Pipe %d",
- IP_FW_ARG_TABLEARG(cmd->arg1));
+ TARG(cmd->arg1, pipe));
break;
case O_QUEUE:
snprintf(SNPARGS(action2, 0), "Queue %d",
- IP_FW_ARG_TABLEARG(cmd->arg1));
+ TARG(cmd->arg1, pipe));
break;
case O_FORWARD_IP: {
ipfw_insn_sa *sa = (ipfw_insn_sa *)cmd;
diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c
index 2d1002f..0b377c5 100644
--- a/sys/netpfil/ipfw/ip_fw_nat.c
+++ b/sys/netpfil/ipfw/ip_fw_nat.c
@@ -36,8 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/rwlock.h>
-
-#define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */
+#include <sys/rmlock.h>
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
@@ -55,6 +54,45 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h> /* XXX for in_cksum */
+struct cfg_spool {
+ LIST_ENTRY(cfg_spool) _next; /* chain of spool instances */
+ struct in_addr addr;
+ uint16_t port;
+};
+
+/* Nat redirect configuration. */
+struct cfg_redir {
+ LIST_ENTRY(cfg_redir) _next; /* chain of redir instances */
+ uint16_t mode; /* type of redirect mode */
+ uint16_t proto; /* protocol: tcp/udp */
+ struct in_addr laddr; /* local ip address */
+ struct in_addr paddr; /* public ip address */
+ struct in_addr raddr; /* remote ip address */
+ uint16_t lport; /* local port */
+ uint16_t pport; /* public port */
+ uint16_t rport; /* remote port */
+ uint16_t pport_cnt; /* number of public ports */
+ uint16_t rport_cnt; /* number of remote ports */
+ struct alias_link **alink;
+ u_int16_t spool_cnt; /* num of entry in spool chain */
+ /* chain of spool instances */
+ LIST_HEAD(spool_chain, cfg_spool) spool_chain;
+};
+
+/* Nat configuration data struct. */
+struct cfg_nat {
+ /* chain of nat instances */
+ LIST_ENTRY(cfg_nat) _next;
+ int id; /* nat id */
+ struct in_addr ip; /* nat ip address */
+ struct libalias *lib; /* libalias instance */
+ int mode; /* aliasing mode */
+ int redir_cnt; /* number of entry in spool chain */
+ /* chain of redir instances */
+ LIST_HEAD(redir_chain, cfg_redir) redir_chain;
+ char if_name[IF_NAMESIZE]; /* interface name */
+};
+
static eventhandler_tag ifaddr_event_tag;
static void
@@ -117,11 +155,11 @@ del_redir_spool_cfg(struct cfg_nat *n, struct redir_chain *head)
LIST_FOREACH_SAFE(r, head, _next, tmp_r) {
num = 1; /* Number of alias_link to delete. */
switch (r->mode) {
- case REDIR_PORT:
+ case NAT44_REDIR_PORT:
num = r->pport_cnt;
/* FALLTHROUGH */
- case REDIR_ADDR:
- case REDIR_PROTO:
+ case NAT44_REDIR_ADDR:
+ case NAT44_REDIR_PROTO:
/* Delete all libalias redirect entry. */
for (i = 0; i < num; i++)
LibAliasRedirectDelete(n->lib, r->alink[i]);
@@ -142,27 +180,41 @@ del_redir_spool_cfg(struct cfg_nat *n, struct redir_chain *head)
}
}
-static void
+static int
add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
{
- struct cfg_redir *r, *ser_r;
- struct cfg_spool *s, *ser_s;
+ struct cfg_redir *r;
+ struct cfg_spool *s;
+ struct nat44_cfg_redir *ser_r;
+ struct nat44_cfg_spool *ser_s;
+
int cnt, off, i;
for (cnt = 0, off = 0; cnt < ptr->redir_cnt; cnt++) {
- ser_r = (struct cfg_redir *)&buf[off];
- r = malloc(SOF_REDIR, M_IPFW, M_WAITOK | M_ZERO);
- memcpy(r, ser_r, SOF_REDIR);
+ ser_r = (struct nat44_cfg_redir *)&buf[off];
+ r = malloc(sizeof(*r), M_IPFW, M_WAITOK | M_ZERO);
+ r->mode = ser_r->mode;
+ r->laddr = ser_r->laddr;
+ r->paddr = ser_r->paddr;
+ r->raddr = ser_r->raddr;
+ r->lport = ser_r->lport;
+ r->pport = ser_r->pport;
+ r->rport = ser_r->rport;
+ r->pport_cnt = ser_r->pport_cnt;
+ r->rport_cnt = ser_r->rport_cnt;
+ r->proto = ser_r->proto;
+ r->spool_cnt = ser_r->spool_cnt;
+ //memcpy(r, ser_r, SOF_REDIR);
LIST_INIT(&r->spool_chain);
- off += SOF_REDIR;
+ off += sizeof(struct nat44_cfg_redir);
r->alink = malloc(sizeof(struct alias_link *) * r->pport_cnt,
M_IPFW, M_WAITOK | M_ZERO);
switch (r->mode) {
- case REDIR_ADDR:
+ case NAT44_REDIR_ADDR:
r->alink[0] = LibAliasRedirectAddr(ptr->lib, r->laddr,
r->paddr);
break;
- case REDIR_PORT:
+ case NAT44_REDIR_PORT:
for (i = 0 ; i < r->pport_cnt; i++) {
/* If remotePort is all ports, set it to 0. */
u_short remotePortCopy = r->rport + i;
@@ -178,7 +230,7 @@ add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
}
}
break;
- case REDIR_PROTO:
+ case NAT44_REDIR_PROTO:
r->alink[0] = LibAliasRedirectProto(ptr->lib ,r->laddr,
r->raddr, r->paddr, r->proto);
break;
@@ -186,23 +238,27 @@ add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
printf("unknown redirect mode: %u\n", r->mode);
break;
}
- /* XXX perhaps return an error instead of panic ? */
- if (r->alink[0] == NULL)
- panic("LibAliasRedirect* returned NULL");
+ if (r->alink[0] == NULL) {
+ printf("LibAliasRedirect* returned NULL\n");
+ return (EINVAL);
+ }
/* LSNAT handling. */
for (i = 0; i < r->spool_cnt; i++) {
- ser_s = (struct cfg_spool *)&buf[off];
- s = malloc(SOF_REDIR, M_IPFW, M_WAITOK | M_ZERO);
- memcpy(s, ser_s, SOF_SPOOL);
+ ser_s = (struct nat44_cfg_spool *)&buf[off];
+ s = malloc(sizeof(*s), M_IPFW, M_WAITOK | M_ZERO);
+ s->addr = ser_s->addr;
+ s->port = ser_s->port;
LibAliasAddServer(ptr->lib, r->alink[0],
s->addr, htons(s->port));
- off += SOF_SPOOL;
+ off += sizeof(struct nat44_cfg_spool);
/* Hook spool entry. */
LIST_INSERT_HEAD(&r->spool_chain, s, _next);
}
/* And finally hook this redir entry. */
LIST_INSERT_HEAD(&ptr->redir_chain, r, _next);
}
+
+ return (0);
}
/*
@@ -392,60 +448,68 @@ lookup_nat(struct nat_list *l, int nat_id)
return res;
}
-static int
-ipfw_nat_cfg(struct sockopt *sopt)
+static struct cfg_nat *
+lookup_nat_name(struct nat_list *l, char *name)
{
- struct cfg_nat *cfg, *ptr;
- char *buf;
- struct ip_fw_chain *chain = &V_layer3_chain;
- size_t len;
- int gencnt, error = 0;
+ struct cfg_nat *res;
+ int id;
+ char *errptr;
- len = sopt->sopt_valsize;
- buf = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
- if ((error = sooptcopyin(sopt, buf, len, sizeof(struct cfg_nat))) != 0)
- goto out;
+ id = strtol(name, &errptr, 10);
+ if (id == 0 || *errptr != '\0')
+ return (NULL);
- cfg = (struct cfg_nat *)buf;
- if (cfg->id < 0) {
- error = EINVAL;
- goto out;
+ LIST_FOREACH(res, l, _next) {
+ if (res->id == id)
+ break;
}
+ return (res);
+}
+
+/* IP_FW3 configuration routines */
+
+static void
+nat44_config(struct ip_fw_chain *chain, struct nat44_cfg_nat *ucfg)
+{
+ struct cfg_nat *ptr, *tcfg;
+ int gencnt;
/*
* Find/create nat rule.
*/
- IPFW_WLOCK(chain);
+ IPFW_UH_WLOCK(chain);
gencnt = chain->gencnt;
- ptr = lookup_nat(&chain->nat, cfg->id);
+ ptr = lookup_nat_name(&chain->nat, ucfg->name);
if (ptr == NULL) {
- IPFW_WUNLOCK(chain);
+ IPFW_UH_WUNLOCK(chain);
/* New rule: allocate and init new instance. */
ptr = malloc(sizeof(struct cfg_nat), M_IPFW, M_WAITOK | M_ZERO);
ptr->lib = LibAliasInit(NULL);
LIST_INIT(&ptr->redir_chain);
} else {
/* Entry already present: temporarily unhook it. */
+ IPFW_WLOCK(chain);
LIST_REMOVE(ptr, _next);
- flush_nat_ptrs(chain, cfg->id);
+ flush_nat_ptrs(chain, ptr->id);
IPFW_WUNLOCK(chain);
+ IPFW_UH_WUNLOCK(chain);
}
/*
- * Basic nat configuration.
+ * Basic nat (re)configuration.
*/
- ptr->id = cfg->id;
+ ptr->id = strtol(ucfg->name, NULL, 10);
/*
* XXX - what if this rule doesn't nat any ip and just
* redirect?
* do we set aliasaddress to 0.0.0.0?
*/
- ptr->ip = cfg->ip;
- ptr->redir_cnt = cfg->redir_cnt;
- ptr->mode = cfg->mode;
- LibAliasSetMode(ptr->lib, cfg->mode, ~0);
+ ptr->ip = ucfg->ip;
+ ptr->redir_cnt = ucfg->redir_cnt;
+ ptr->mode = ucfg->mode;
+ strlcpy(ptr->if_name, ucfg->if_name, sizeof(ptr->if_name));
+ LibAliasSetMode(ptr->lib, ptr->mode, ~0);
LibAliasSetAddress(ptr->lib, ptr->ip);
- memcpy(ptr->if_name, cfg->if_name, IF_NAMESIZE);
/*
* Redir and LSNAT configuration.
@@ -453,16 +517,455 @@ ipfw_nat_cfg(struct sockopt *sopt)
/* Delete old cfgs. */
del_redir_spool_cfg(ptr, &ptr->redir_chain);
/* Add new entries. */
- add_redir_spool_cfg(&buf[(sizeof(struct cfg_nat))], ptr);
+ add_redir_spool_cfg((char *)(ucfg + 1), ptr);
+ IPFW_UH_WLOCK(chain);
- IPFW_WLOCK(chain);
/* Extra check to avoid race with another ipfw_nat_cfg() */
- if (gencnt != chain->gencnt &&
- ((cfg = lookup_nat(&chain->nat, ptr->id)) != NULL))
- LIST_REMOVE(cfg, _next);
+ tcfg = NULL;
+ if (gencnt != chain->gencnt)
+ tcfg = lookup_nat_name(&chain->nat, ucfg->name);
+ IPFW_WLOCK(chain);
+ if (tcfg != NULL)
+ LIST_REMOVE(tcfg, _next);
LIST_INSERT_HEAD(&chain->nat, ptr, _next);
+ IPFW_WUNLOCK(chain);
chain->gencnt++;
+
+ IPFW_UH_WUNLOCK(chain);
+
+ if (tcfg != NULL)
+ free(tcfg, M_IPFW);
+}
+
+/*
+ * Creates/configure nat44 instance
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header nat44_cfg_nat .. ]
+ *
+ * Returns 0 on success
+ */
+static int
+nat44_cfg(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_header *oh;
+ struct nat44_cfg_nat *ucfg;
+ int id;
+ size_t read;
+ char *errptr;
+
+ /* Check minimum header size */
+ if (sd->valsize < (sizeof(*oh) + sizeof(*ucfg)))
+ return (EINVAL);
+
+ oh = (ipfw_obj_header *)sd->kbuf;
+
+ /* Basic length checks for TLVs */
+ if (oh->ntlv.head.length != sizeof(oh->ntlv))
+ return (EINVAL);
+
+ ucfg = (struct nat44_cfg_nat *)(oh + 1);
+
+ /* Check if name is properly terminated and looks like number */
+ if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
+ return (EINVAL);
+ id = strtol(ucfg->name, &errptr, 10);
+ if (id == 0 || *errptr != '\0')
+ return (EINVAL);
+
+ read = sizeof(*oh) + sizeof(*ucfg);
+ /* Check number of redirs */
+ if (sd->valsize < read + ucfg->redir_cnt*sizeof(struct nat44_cfg_redir))
+ return (EINVAL);
+
+ nat44_config(chain, ucfg);
+ return (0);
+}
+
+/*
+ * Destroys given nat instances.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ]
+ *
+ * Returns 0 on success
+ */
+static int
+nat44_destroy(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_header *oh;
+ struct cfg_nat *ptr;
+ ipfw_obj_ntlv *ntlv;
+
+ /* Check minimum header size */
+ if (sd->valsize < sizeof(*oh))
+ return (EINVAL);
+
+ oh = (ipfw_obj_header *)sd->kbuf;
+
+ /* Basic length checks for TLVs */
+ if (oh->ntlv.head.length != sizeof(oh->ntlv))
+ return (EINVAL);
+
+ ntlv = &oh->ntlv;
+ /* Check if name is properly terminated */
+ if (strnlen(ntlv->name, sizeof(ntlv->name)) == sizeof(ntlv->name))
+ return (EINVAL);
+
+ IPFW_UH_WLOCK(chain);
+ ptr = lookup_nat_name(&chain->nat, ntlv->name);
+ if (ptr == NULL) {
+ IPFW_UH_WUNLOCK(chain);
+ return (ESRCH);
+ }
+ IPFW_WLOCK(chain);
+ LIST_REMOVE(ptr, _next);
+ flush_nat_ptrs(chain, ptr->id);
IPFW_WUNLOCK(chain);
+ IPFW_UH_WUNLOCK(chain);
+
+ del_redir_spool_cfg(ptr, &ptr->redir_chain);
+ LibAliasUninit(ptr->lib);
+ free(ptr, M_IPFW);
+
+ return (0);
+}
+
+static void
+export_nat_cfg(struct cfg_nat *ptr, struct nat44_cfg_nat *ucfg)
+{
+
+ snprintf(ucfg->name, sizeof(ucfg->name), "%d", ptr->id);
+ ucfg->ip = ptr->ip;
+ ucfg->redir_cnt = ptr->redir_cnt;
+ ucfg->mode = ptr->mode;
+ strlcpy(ucfg->if_name, ptr->if_name, sizeof(ucfg->if_name));
+}
+
+/*
+ * Gets config for given nat instance
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header nat44_cfg_nat .. ]
+ *
+ * Returns 0 on success
+ */
+static int
+nat44_get_cfg(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_header *oh;
+ struct nat44_cfg_nat *ucfg;
+ struct cfg_nat *ptr;
+ struct cfg_redir *r;
+ struct cfg_spool *s;
+ struct nat44_cfg_redir *ser_r;
+ struct nat44_cfg_spool *ser_s;
+ size_t sz;
+
+ sz = sizeof(*oh) + sizeof(*ucfg);
+ /* Check minimum header size */
+ if (sd->valsize < sz)
+ return (EINVAL);
+
+ oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
+
+ /* Basic length checks for TLVs */
+ if (oh->ntlv.head.length != sizeof(oh->ntlv))
+ return (EINVAL);
+
+ ucfg = (struct nat44_cfg_nat *)(oh + 1);
+
+ /* Check if name is properly terminated */
+ if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
+ return (EINVAL);
+
+ IPFW_UH_RLOCK(chain);
+ ptr = lookup_nat_name(&chain->nat, ucfg->name);
+ if (ptr == NULL) {
+ IPFW_UH_RUNLOCK(chain);
+ return (ESRCH);
+ }
+
+ export_nat_cfg(ptr, ucfg);
+
+ /* Estimate memory amount */
+ sz = sizeof(struct nat44_cfg_nat);
+ LIST_FOREACH(r, &ptr->redir_chain, _next) {
+ sz += sizeof(struct nat44_cfg_redir);
+ LIST_FOREACH(s, &r->spool_chain, _next)
+ sz += sizeof(struct nat44_cfg_spool);
+ }
+
+ ucfg->size = sz;
+ if (sd->valsize < sz + sizeof(*oh)) {
+
+ /*
+ * Submitted buffer size is not enough.
+ * WE've already filled in @ucfg structure with
+ * relevant info including size, so we
+ * can return. Buffer will be flushed automatically.
+ */
+ IPFW_UH_RUNLOCK(chain);
+ return (ENOMEM);
+ }
+
+ /* Size OK, let's copy data */
+ LIST_FOREACH(r, &ptr->redir_chain, _next) {
+ ser_r = (struct nat44_cfg_redir *)ipfw_get_sopt_space(sd,
+ sizeof(*ser_r));
+ ser_r->mode = r->mode;
+ ser_r->laddr = r->laddr;
+ ser_r->paddr = r->paddr;
+ ser_r->raddr = r->raddr;
+ ser_r->lport = r->lport;
+ ser_r->pport = r->pport;
+ ser_r->rport = r->rport;
+ ser_r->pport_cnt = r->pport_cnt;
+ ser_r->rport_cnt = r->rport_cnt;
+ ser_r->proto = r->proto;
+ ser_r->spool_cnt = r->spool_cnt;
+
+ LIST_FOREACH(s, &r->spool_chain, _next) {
+ ser_s = (struct nat44_cfg_spool *)ipfw_get_sopt_space(
+ sd, sizeof(*ser_s));
+
+ ser_s->addr = s->addr;
+ ser_s->port = s->port;
+ }
+ }
+
+ IPFW_UH_RUNLOCK(chain);
+
+ return (0);
+}
+
+/*
+ * Lists all nat44 instances currently available in kernel.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_lheader ]
+ * Reply: [ ipfw_obj_lheader nat44_cfg_nat x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+nat44_list_nat(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_lheader *olh;
+ struct nat44_cfg_nat *ucfg;
+ struct cfg_nat *ptr;
+ int nat_count;
+
+ /* Check minimum header size */
+ if (sd->valsize < sizeof(ipfw_obj_lheader))
+ return (EINVAL);
+
+ olh = (ipfw_obj_lheader *)ipfw_get_sopt_header(sd, sizeof(*olh));
+ IPFW_UH_RLOCK(chain);
+ nat_count = 0;
+ LIST_FOREACH(ptr, &chain->nat, _next)
+ nat_count++;
+
+ olh->count = nat_count;
+ olh->objsize = sizeof(struct nat44_cfg_nat);
+ olh->size = sizeof(*olh) + olh->count * olh->objsize;
+
+ if (sd->valsize < olh->size) {
+ IPFW_UH_RUNLOCK(chain);
+ return (ENOMEM);
+ }
+
+ LIST_FOREACH(ptr, &chain->nat, _next) {
+ ucfg = (struct nat44_cfg_nat *)ipfw_get_sopt_space(sd,
+ sizeof(*ucfg));
+ export_nat_cfg(ptr, ucfg);
+ }
+
+ IPFW_UH_RUNLOCK(chain);
+
+ return (0);
+}
+
+/*
+ * Gets log for given nat instance
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header nat44_cfg_nat ]
+ * Reply: [ ipfw_obj_header nat44_cfg_nat LOGBUFFER ]
+ *
+ * Returns 0 on success
+ */
+static int
+nat44_get_log(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_header *oh;
+ struct nat44_cfg_nat *ucfg;
+ struct cfg_nat *ptr;
+ void *pbuf;
+ size_t sz;
+
+ sz = sizeof(*oh) + sizeof(*ucfg);
+ /* Check minimum header size */
+ if (sd->valsize < sz)
+ return (EINVAL);
+
+ oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
+
+ /* Basic length checks for TLVs */
+ if (oh->ntlv.head.length != sizeof(oh->ntlv))
+ return (EINVAL);
+
+ ucfg = (struct nat44_cfg_nat *)(oh + 1);
+
+ /* Check if name is properly terminated */
+ if (strnlen(ucfg->name, sizeof(ucfg->name)) == sizeof(ucfg->name))
+ return (EINVAL);
+
+ IPFW_UH_RLOCK(chain);
+ ptr = lookup_nat_name(&chain->nat, ucfg->name);
+ if (ptr == NULL) {
+ IPFW_UH_RUNLOCK(chain);
+ return (ESRCH);
+ }
+
+ if (ptr->lib->logDesc == NULL) {
+ IPFW_UH_RUNLOCK(chain);
+ return (ENOENT);
+ }
+
+ export_nat_cfg(ptr, ucfg);
+
+ /* Estimate memory amount */
+ ucfg->size = sizeof(struct nat44_cfg_nat) + LIBALIAS_BUF_SIZE;
+ if (sd->valsize < sz + sizeof(*oh)) {
+
+ /*
+ * Submitted buffer size is not enough.
+ * WE've already filled in @ucfg structure with
+ * relevant info including size, so we
+ * can return. Buffer will be flushed automatically.
+ */
+ IPFW_UH_RUNLOCK(chain);
+ return (ENOMEM);
+ }
+
+ pbuf = (void *)ipfw_get_sopt_space(sd, LIBALIAS_BUF_SIZE);
+ memcpy(pbuf, ptr->lib->logDesc, LIBALIAS_BUF_SIZE);
+
+ IPFW_UH_RUNLOCK(chain);
+
+ return (0);
+}
+
+static struct ipfw_sopt_handler scodes[] = {
+ { IP_FW_NAT44_XCONFIG, 0, HDIR_SET, nat44_cfg },
+ { IP_FW_NAT44_DESTROY, 0, HDIR_SET, nat44_destroy },
+ { IP_FW_NAT44_XGETCONFIG, 0, HDIR_GET, nat44_get_cfg },
+ { IP_FW_NAT44_LIST_NAT, 0, HDIR_GET, nat44_list_nat },
+ { IP_FW_NAT44_XGETLOG, 0, HDIR_GET, nat44_get_log },
+};
+
+
+/*
+ * Legacy configuration routines
+ */
+
+struct cfg_spool_legacy {
+ LIST_ENTRY(cfg_spool_legacy) _next;
+ struct in_addr addr;
+ u_short port;
+};
+
+struct cfg_redir_legacy {
+ LIST_ENTRY(cfg_redir) _next;
+ u_int16_t mode;
+ struct in_addr laddr;
+ struct in_addr paddr;
+ struct in_addr raddr;
+ u_short lport;
+ u_short pport;
+ u_short rport;
+ u_short pport_cnt;
+ u_short rport_cnt;
+ int proto;
+ struct alias_link **alink;
+ u_int16_t spool_cnt;
+ LIST_HEAD(, cfg_spool_legacy) spool_chain;
+};
+
+struct cfg_nat_legacy {
+ LIST_ENTRY(cfg_nat_legacy) _next;
+ int id;
+ struct in_addr ip;
+ char if_name[IF_NAMESIZE];
+ int mode;
+ struct libalias *lib;
+ int redir_cnt;
+ LIST_HEAD(, cfg_redir_legacy) redir_chain;
+};
+
+static int
+ipfw_nat_cfg(struct sockopt *sopt)
+{
+ struct cfg_nat_legacy *cfg;
+ struct nat44_cfg_nat *ucfg;
+ struct cfg_redir_legacy *rdir;
+ struct nat44_cfg_redir *urdir;
+ char *buf;
+ size_t len, len2;
+ int error, i;
+
+ len = sopt->sopt_valsize;
+ len2 = len + 128;
+
+ /*
+ * Allocate 2x buffer to store converted structures.
+ * new redir_cfg has shrinked, so we're sure that
+ * new buffer size is enough.
+ */
+ buf = malloc(roundup2(len, 8) + len2, M_TEMP, M_WAITOK | M_ZERO);
+ error = sooptcopyin(sopt, buf, len, sizeof(struct cfg_nat_legacy));
+ if (error != 0)
+ goto out;
+
+ cfg = (struct cfg_nat_legacy *)buf;
+ if (cfg->id < 0) {
+ error = EINVAL;
+ goto out;
+ }
+
+ ucfg = (struct nat44_cfg_nat *)&buf[roundup2(len, 8)];
+ snprintf(ucfg->name, sizeof(ucfg->name), "%d", cfg->id);
+ strlcpy(ucfg->if_name, cfg->if_name, sizeof(ucfg->if_name));
+ ucfg->ip = cfg->ip;
+ ucfg->mode = cfg->mode;
+ ucfg->redir_cnt = cfg->redir_cnt;
+
+ if (len < sizeof(*cfg) + cfg->redir_cnt * sizeof(*rdir)) {
+ error = EINVAL;
+ goto out;
+ }
+
+ urdir = (struct nat44_cfg_redir *)(ucfg + 1);
+ rdir = (struct cfg_redir_legacy *)(cfg + 1);
+ for (i = 0; i < cfg->redir_cnt; i++) {
+ urdir->mode = rdir->mode;
+ urdir->laddr = rdir->laddr;
+ urdir->paddr = rdir->paddr;
+ urdir->raddr = rdir->raddr;
+ urdir->lport = rdir->lport;
+ urdir->pport = rdir->pport;
+ urdir->rport = rdir->rport;
+ urdir->pport_cnt = rdir->pport_cnt;
+ urdir->rport_cnt = rdir->rport_cnt;
+ urdir->proto = rdir->proto;
+ urdir->spool_cnt = rdir->spool_cnt;
+
+ urdir++;
+ rdir++;
+ }
+
+ nat44_config(&V_layer3_chain, ucfg);
out:
free(buf, M_TEMP);
@@ -478,15 +981,17 @@ ipfw_nat_del(struct sockopt *sopt)
sooptcopyin(sopt, &i, sizeof i, sizeof i);
/* XXX validate i */
- IPFW_WLOCK(chain);
+ IPFW_UH_WLOCK(chain);
ptr = lookup_nat(&chain->nat, i);
if (ptr == NULL) {
- IPFW_WUNLOCK(chain);
+ IPFW_UH_WUNLOCK(chain);
return (EINVAL);
}
+ IPFW_WLOCK(chain);
LIST_REMOVE(ptr, _next);
flush_nat_ptrs(chain, i);
IPFW_WUNLOCK(chain);
+ IPFW_UH_WUNLOCK(chain);
del_redir_spool_cfg(ptr, &ptr->redir_chain);
LibAliasUninit(ptr->lib);
free(ptr, M_IPFW);
@@ -498,28 +1003,31 @@ ipfw_nat_get_cfg(struct sockopt *sopt)
{
struct ip_fw_chain *chain = &V_layer3_chain;
struct cfg_nat *n;
+ struct cfg_nat_legacy *ucfg;
struct cfg_redir *r;
struct cfg_spool *s;
+ struct cfg_redir_legacy *ser_r;
+ struct cfg_spool_legacy *ser_s;
char *data;
int gencnt, nat_cnt, len, error;
nat_cnt = 0;
len = sizeof(nat_cnt);
- IPFW_RLOCK(chain);
+ IPFW_UH_RLOCK(chain);
retry:
gencnt = chain->gencnt;
/* Estimate memory amount */
LIST_FOREACH(n, &chain->nat, _next) {
nat_cnt++;
- len += sizeof(struct cfg_nat);
+ len += sizeof(struct cfg_nat_legacy);
LIST_FOREACH(r, &n->redir_chain, _next) {
- len += sizeof(struct cfg_redir);
+ len += sizeof(struct cfg_redir_legacy);
LIST_FOREACH(s, &r->spool_chain, _next)
- len += sizeof(struct cfg_spool);
+ len += sizeof(struct cfg_spool_legacy);
}
}
- IPFW_RUNLOCK(chain);
+ IPFW_UH_RUNLOCK(chain);
data = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
bcopy(&nat_cnt, data, sizeof(nat_cnt));
@@ -527,25 +1035,43 @@ retry:
nat_cnt = 0;
len = sizeof(nat_cnt);
- IPFW_RLOCK(chain);
+ IPFW_UH_RLOCK(chain);
if (gencnt != chain->gencnt) {
free(data, M_TEMP);
goto retry;
}
/* Serialize all the data. */
LIST_FOREACH(n, &chain->nat, _next) {
- bcopy(n, &data[len], sizeof(struct cfg_nat));
- len += sizeof(struct cfg_nat);
+ ucfg = (struct cfg_nat_legacy *)&data[len];
+ ucfg->id = n->id;
+ ucfg->ip = n->ip;
+ ucfg->redir_cnt = n->redir_cnt;
+ ucfg->mode = n->mode;
+ strlcpy(ucfg->if_name, n->if_name, sizeof(ucfg->if_name));
+ len += sizeof(struct cfg_nat_legacy);
LIST_FOREACH(r, &n->redir_chain, _next) {
- bcopy(r, &data[len], sizeof(struct cfg_redir));
- len += sizeof(struct cfg_redir);
+ ser_r = (struct cfg_redir_legacy *)&data[len];
+ ser_r->mode = r->mode;
+ ser_r->laddr = r->laddr;
+ ser_r->paddr = r->paddr;
+ ser_r->raddr = r->raddr;
+ ser_r->lport = r->lport;
+ ser_r->pport = r->pport;
+ ser_r->rport = r->rport;
+ ser_r->pport_cnt = r->pport_cnt;
+ ser_r->rport_cnt = r->rport_cnt;
+ ser_r->proto = r->proto;
+ ser_r->spool_cnt = r->spool_cnt;
+ len += sizeof(struct cfg_redir_legacy);
LIST_FOREACH(s, &r->spool_chain, _next) {
- bcopy(s, &data[len], sizeof(struct cfg_spool));
- len += sizeof(struct cfg_spool);
+ ser_s = (struct cfg_spool_legacy *)&data[len];
+ ser_s->addr = s->addr;
+ ser_s->port = s->port;
+ len += sizeof(struct cfg_spool_legacy);
}
}
}
- IPFW_RUNLOCK(chain);
+ IPFW_UH_RUNLOCK(chain);
error = sooptcopyout(sopt, data, len);
free(data, M_TEMP);
@@ -560,6 +1086,7 @@ ipfw_nat_get_log(struct sockopt *sopt)
struct cfg_nat *ptr;
int i, size;
struct ip_fw_chain *chain;
+ IPFW_RLOCK_TRACKER;
chain = &V_layer3_chain;
@@ -631,6 +1158,7 @@ ipfw_nat_init(void)
ipfw_nat_del_ptr = ipfw_nat_del;
ipfw_nat_get_cfg_ptr = ipfw_nat_get_cfg;
ipfw_nat_get_log_ptr = ipfw_nat_get_log;
+ IPFW_ADD_SOPT_HANDLER(1, scodes);
ifaddr_event_tag = EVENTHANDLER_REGISTER(ifaddr_event, ifaddr_change,
NULL, EVENTHANDLER_PRI_ANY);
@@ -642,6 +1170,7 @@ ipfw_nat_destroy(void)
EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_event_tag);
/* deregister ipfw_nat */
+ IPFW_DEL_SOPT_HANDLER(1, scodes);
ipfw_nat_ptr = NULL;
lookup_nat_ptr = NULL;
ipfw_nat_cfg_ptr = NULL;
@@ -683,7 +1212,7 @@ static moduledata_t ipfw_nat_mod = {
DECLARE_MODULE(ipfw_nat, ipfw_nat_mod, IPFW_NAT_SI_SUB_FIREWALL, SI_ORDER_ANY);
MODULE_DEPEND(ipfw_nat, libalias, 1, 1, 1);
-MODULE_DEPEND(ipfw_nat, ipfw, 2, 2, 2);
+MODULE_DEPEND(ipfw_nat, ipfw, 3, 3, 3);
MODULE_VERSION(ipfw_nat, 1);
SYSINIT(ipfw_nat_init, IPFW_NAT_SI_SUB_FIREWALL, IPFW_NAT_MODULE_ORDER,
diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h
index e4a2f31..bd13ae6 100644
--- a/sys/netpfil/ipfw/ip_fw_private.h
+++ b/sys/netpfil/ipfw/ip_fw_private.h
@@ -152,10 +152,11 @@ void ipfw_nat_destroy(void);
/* In ip_fw_log.c */
struct ip;
+struct ip_fw_chain;
void ipfw_log_bpf(int);
-void ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
- struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg,
- struct ip *ip);
+void ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
+ struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif,
+ u_short offset, uint32_t tablearg, struct ip *ip);
VNET_DECLARE(u_int64_t, norule_counter);
#define V_norule_counter VNET(norule_counter)
VNET_DECLARE(int, verbose_limit);
@@ -176,22 +177,26 @@ enum { /* result for matching dynamic rules */
* Eventually we may implement it with a callback on the function.
*/
struct ip_fw_chain;
-void ipfw_expire_dyn_rules(struct ip_fw_chain *, struct ip_fw *, int);
+struct sockopt_data;
+int ipfw_is_dyn_rule(struct ip_fw *rule);
+void ipfw_expire_dyn_rules(struct ip_fw_chain *, ipfw_range_tlv *);
void ipfw_dyn_unlock(ipfw_dyn_rule *q);
struct tcphdr;
struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *,
u_int32_t, u_int32_t, int);
-int ipfw_install_state(struct ip_fw *rule, ipfw_insn_limit *cmd,
- struct ip_fw_args *args, uint32_t tablearg);
+int ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
+ ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg);
ipfw_dyn_rule *ipfw_lookup_dyn_rule(struct ipfw_flow_id *pkt,
int *match_direction, struct tcphdr *tcp);
void ipfw_remove_dyn_children(struct ip_fw *rule);
void ipfw_get_dynamic(struct ip_fw_chain *chain, char **bp, const char *ep);
+int ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd);
void ipfw_dyn_init(struct ip_fw_chain *); /* per-vnet initialization */
void ipfw_dyn_uninit(int); /* per-vnet deinitialization */
int ipfw_dyn_len(void);
+int ipfw_dyn_get_count(void);
/* common variables */
VNET_DECLARE(int, fw_one_pass);
@@ -203,6 +208,9 @@ VNET_DECLARE(int, fw_verbose);
VNET_DECLARE(struct ip_fw_chain, layer3_chain);
#define V_layer3_chain VNET(layer3_chain)
+VNET_DECLARE(int, ipfw_vnet_ready);
+#define V_ipfw_vnet_ready VNET(ipfw_vnet_ready)
+
VNET_DECLARE(u_int32_t, set_disable);
#define V_set_disable VNET(set_disable)
@@ -212,23 +220,68 @@ VNET_DECLARE(int, autoinc_step);
VNET_DECLARE(unsigned int, fw_tables_max);
#define V_fw_tables_max VNET(fw_tables_max)
+VNET_DECLARE(unsigned int, fw_tables_sets);
+#define V_fw_tables_sets VNET(fw_tables_sets)
+
+struct tables_config;
+
+#ifdef _KERNEL
+typedef struct ip_fw_cntr {
+ uint64_t pcnt; /* Packet counter */
+ uint64_t bcnt; /* Byte counter */
+ uint64_t timestamp; /* tv_sec of last match */
+} ip_fw_cntr;
+
+/*
+ * Here we have the structure representing an ipfw rule.
+ *
+ * It starts with a general area
+ * followed by an array of one or more instructions, which the code
+ * accesses as an array of 32-bit values.
+ *
+ * Given a rule pointer r:
+ *
+ * r->cmd is the start of the first instruction.
+ * ACTION_PTR(r) is the start of the first action (things to do
+ * once a rule matched).
+ */
+
+struct ip_fw {
+ uint16_t act_ofs; /* offset of action in 32-bit units */
+ uint16_t cmd_len; /* # of 32-bit words in cmd */
+ uint16_t rulenum; /* rule number */
+ uint8_t set; /* rule set (0..31) */
+ uint8_t flags; /* currently unused */
+ counter_u64_t cntr; /* Pointer to rule counters */
+ uint32_t timestamp; /* tv_sec of last match */
+ uint32_t id; /* rule id */
+ uint32_t cached_id; /* used by jump_fast */
+ uint32_t cached_pos; /* used by jump_fast */
+
+ ipfw_insn cmd[1]; /* storage for commands */
+};
+
+#endif
+
struct ip_fw_chain {
struct ip_fw **map; /* array of rule ptrs to ease lookup */
uint32_t id; /* ruleset id */
int n_rules; /* number of static rules */
LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */
- struct radix_node_head **tables; /* IPv4 tables */
- struct radix_node_head **xtables; /* extended tables */
- uint8_t *tabletype; /* Array of table types */
+ void *tablestate; /* runtime table info */
+ void *valuestate; /* runtime table value info */
+ int *idxmap; /* skipto array of rules */
#if defined( __linux__ ) || defined( _WIN32 )
spinlock_t rwmtx;
#else
- struct rwlock rwmtx;
+ struct rmlock rwmtx;
#endif
- int static_len; /* total len of static rules */
+ int static_len; /* total len of static rules (v0) */
uint32_t gencnt; /* NAT generation count */
- struct ip_fw *reap; /* list of rules to reap */
struct ip_fw *default_rule;
+ struct tables_config *tblcfg; /* tables module data */
+ void *ifcfg; /* interface module data */
+ int *idxmap_back; /* standby skipto array of rules */
#if defined( __linux__ ) || defined( _WIN32 )
spinlock_t uh_lock;
#else
@@ -236,9 +289,76 @@ struct ip_fw_chain {
#endif
};
+/* 64-byte structure representing multi-field table value */
+struct table_value {
+ uint32_t tag; /* O_TAG/O_TAGGED */
+ uint32_t pipe; /* O_PIPE/O_QUEUE */
+ uint16_t divert; /* O_DIVERT/O_TEE */
+ uint16_t skipto; /* skipto, CALLRET */
+ uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */
+ uint32_t fib; /* O_SETFIB */
+ uint32_t nat; /* O_NAT */
+ uint32_t nh4;
+ uint8_t dscp;
+ uint8_t spare0[3];
+ /* -- 32 bytes -- */
+ struct in6_addr nh6;
+ uint32_t limit; /* O_LIMIT */
+ uint32_t spare1;
+ uint64_t refcnt; /* Number of references */
+};
+
+struct namedobj_instance;
+
+struct named_object {
+ TAILQ_ENTRY(named_object) nn_next; /* namehash */
+ TAILQ_ENTRY(named_object) nv_next; /* valuehash */
+ char *name; /* object name */
+ uint8_t type; /* object type */
+ uint8_t compat; /* Object name is number */
+ uint16_t kidx; /* object kernel index */
+ uint16_t uidx; /* userland idx for compat records */
+ uint32_t set; /* set object belongs to */
+ uint32_t refcnt; /* number of references */
+};
+TAILQ_HEAD(namedobjects_head, named_object);
+
struct sockopt; /* used by tcp_var.h */
+struct sockopt_data {
+ caddr_t kbuf; /* allocated buffer */
+ size_t ksize; /* given buffer size */
+ size_t koff; /* data already used */
+ size_t kavail; /* number of bytes available */
+ size_t ktotal; /* total bytes pushed */
+ struct sockopt *sopt; /* socket data */
+ caddr_t sopt_val; /* sopt user buffer */
+ size_t valsize; /* original data size */
+};
+
+struct ipfw_ifc;
+
+typedef void (ipfw_ifc_cb)(struct ip_fw_chain *ch, void *cbdata,
+ uint16_t ifindex);
+
+struct ipfw_iface {
+ struct named_object no;
+ char ifname[64];
+ int resolved;
+ uint16_t ifindex;
+ uint16_t spare;
+ uint64_t gencnt;
+ TAILQ_HEAD(, ipfw_ifc) consumers;
+};
+
+struct ipfw_ifc {
+ TAILQ_ENTRY(ipfw_ifc) next;
+ struct ipfw_iface *iface;
+ ipfw_ifc_cb *cb;
+ void *cbdata;
+};
/* Macro for working with various counters */
+#ifdef USERSPACE
#define IPFW_INC_RULE_COUNTER(_cntr, _bytes) do { \
(_cntr)->pcnt++; \
(_cntr)->bcnt += _bytes; \
@@ -260,13 +380,40 @@ struct sockopt; /* used by tcp_var.h */
(_cntr)->pcnt = 0; \
(_cntr)->bcnt = 0; \
} while (0)
+#else
+#define IPFW_INC_RULE_COUNTER(_cntr, _bytes) do { \
+ counter_u64_add((_cntr)->cntr, 1); \
+ counter_u64_add((_cntr)->cntr + 1, _bytes); \
+ if ((_cntr)->timestamp != time_uptime) \
+ (_cntr)->timestamp = time_uptime; \
+ } while (0)
-#define IP_FW_ARG_TABLEARG(a) (((a) == IP_FW_TABLEARG) ? tablearg : (a))
+#define IPFW_INC_DYN_COUNTER(_cntr, _bytes) do { \
+ (_cntr)->pcnt++; \
+ (_cntr)->bcnt += _bytes; \
+ } while (0)
+
+#define IPFW_ZERO_RULE_COUNTER(_cntr) do { \
+ counter_u64_zero((_cntr)->cntr); \
+ counter_u64_zero((_cntr)->cntr + 1); \
+ (_cntr)->timestamp = 0; \
+ } while (0)
+
+#define IPFW_ZERO_DYN_COUNTER(_cntr) do { \
+ (_cntr)->pcnt = 0; \
+ (_cntr)->bcnt = 0; \
+ } while (0)
+#endif
+
+#define TARG_VAL(ch, k, f) ((struct table_value *)((ch)->valuestate))[k].f
+#define IP_FW_ARG_TABLEARG(ch, a, f) \
+ (((a) == IP_FW_TARG) ? TARG_VAL(ch, tablearg, f) : (a))
/*
* The lock is heavily used by ip_fw2.c (the main file) and ip_fw_nat.c
* so the variable and the macros must be here.
*/
+#if defined( __linux__ ) || defined( _WIN32 )
#define IPFW_LOCK_INIT(_chain) do { \
rw_init(&(_chain)->rwmtx, "IPFW static rules"); \
rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \
@@ -280,12 +427,35 @@ struct sockopt; /* used by tcp_var.h */
#define IPFW_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_RLOCKED)
#define IPFW_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_WLOCKED)
+#define IPFW_RLOCK_TRACKER
#define IPFW_RLOCK(p) rw_rlock(&(p)->rwmtx)
#define IPFW_RUNLOCK(p) rw_runlock(&(p)->rwmtx)
#define IPFW_WLOCK(p) rw_wlock(&(p)->rwmtx)
#define IPFW_WUNLOCK(p) rw_wunlock(&(p)->rwmtx)
#define IPFW_PF_RLOCK(p) IPFW_RLOCK(p)
#define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p)
+#else /* FreeBSD */
+#define IPFW_LOCK_INIT(_chain) do { \
+ rm_init(&(_chain)->rwmtx, "IPFW static rules"); \
+ rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \
+ } while (0)
+
+#define IPFW_LOCK_DESTROY(_chain) do { \
+ rm_destroy(&(_chain)->rwmtx); \
+ rw_destroy(&(_chain)->uh_lock); \
+ } while (0)
+
+#define IPFW_RLOCK_ASSERT(_chain) rm_assert(&(_chain)->rwmtx, RA_RLOCKED)
+#define IPFW_WLOCK_ASSERT(_chain) rm_assert(&(_chain)->rwmtx, RA_WLOCKED)
+
+#define IPFW_RLOCK_TRACKER struct rm_priotracker _tracker
+#define IPFW_RLOCK(p) rm_rlock(&(p)->rwmtx, &_tracker)
+#define IPFW_RUNLOCK(p) rm_runlock(&(p)->rwmtx, &_tracker)
+#define IPFW_WLOCK(p) rm_wlock(&(p)->rwmtx)
+#define IPFW_WUNLOCK(p) rm_wunlock(&(p)->rwmtx)
+#define IPFW_PF_RLOCK(p) IPFW_RLOCK(p)
+#define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p)
+#endif
#define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED)
#define IPFW_UH_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_WLOCKED)
@@ -295,32 +465,172 @@ struct sockopt; /* used by tcp_var.h */
#define IPFW_UH_WLOCK(p) rw_wlock(&(p)->uh_lock)
#define IPFW_UH_WUNLOCK(p) rw_wunlock(&(p)->uh_lock)
+struct obj_idx {
+ uint16_t uidx; /* internal index supplied by userland */
+ uint16_t kidx; /* kernel object index */
+ uint16_t off; /* tlv offset from rule end in 4-byte words */
+ uint8_t spare;
+ uint8_t type; /* object type within its category */
+};
+
+struct rule_check_info {
+ uint16_t flags; /* rule-specific check flags */
+ uint16_t table_opcodes; /* count of opcodes referencing table */
+ uint16_t urule_numoff; /* offset of rulenum in bytes */
+ uint8_t version; /* rule version */
+ uint8_t spare;
+ ipfw_obj_ctlv *ctlv; /* name TLV containter */
+ struct ip_fw *krule; /* resulting rule pointer */
+ caddr_t urule; /* original rule pointer */
+ struct obj_idx obuf[8]; /* table references storage */
+};
+
+/* Legacy interface support */
+/*
+ * FreeBSD 8 export rule format
+ */
+struct ip_fw_rule0 {
+ struct ip_fw *x_next; /* linked list of rules */
+ struct ip_fw *next_rule; /* ptr to next [skipto] rule */
+ /* 'next_rule' is used to pass up 'set_disable' status */
+
+ uint16_t act_ofs; /* offset of action in 32-bit units */
+ uint16_t cmd_len; /* # of 32-bit words in cmd */
+ uint16_t rulenum; /* rule number */
+ uint8_t set; /* rule set (0..31) */
+ uint8_t _pad; /* padding */
+ uint32_t id; /* rule id */
+
+ /* These fields are present in all rules. */
+ uint64_t pcnt; /* Packet counter */
+ uint64_t bcnt; /* Byte counter */
+ uint32_t timestamp; /* tv_sec of last match */
+
+ ipfw_insn cmd[1]; /* storage for commands */
+};
+
+struct ip_fw_bcounter0 {
+ uint64_t pcnt; /* Packet counter */
+ uint64_t bcnt; /* Byte counter */
+ uint32_t timestamp; /* tv_sec of last match */
+};
+
+/* Kernel rule length */
+/*
+ * RULE _K_ SIZE _V_ ->
+ * get kernel size from userland rool version _V_.
+ * RULE _U_ SIZE _V_ ->
+ * get user size version _V_ from kernel rule
+ * RULESIZE _V_ ->
+ * get user size rule length
+ */
+/* FreeBSD8 <> current kernel format */
+#define RULEUSIZE0(r) (sizeof(struct ip_fw_rule0) + (r)->cmd_len * 4 - 4)
+#define RULEKSIZE0(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8)
+/* FreeBSD11 <> current kernel format */
+#define RULEUSIZE1(r) (roundup2(sizeof(struct ip_fw_rule) + \
+ (r)->cmd_len * 4 - 4, 8))
+#define RULEKSIZE1(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8)
+
+
+/* In ip_fw_iface.c */
+int ipfw_iface_init(void);
+void ipfw_iface_destroy(void);
+void vnet_ipfw_iface_destroy(struct ip_fw_chain *ch);
+int ipfw_iface_ref(struct ip_fw_chain *ch, char *name,
+ struct ipfw_ifc *ic);
+void ipfw_iface_unref(struct ip_fw_chain *ch, struct ipfw_ifc *ic);
+void ipfw_iface_add_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic);
+void ipfw_iface_del_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic);
+
/* In ip_fw_sockopt.c */
+void ipfw_init_skipto_cache(struct ip_fw_chain *chain);
+void ipfw_destroy_skipto_cache(struct ip_fw_chain *chain);
int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id);
-int ipfw_add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule);
-int ipfw_ctl(struct sockopt *sopt);
+int ipfw_ctl3(struct sockopt *sopt);
int ipfw_chk(struct ip_fw_args *args);
+void ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head,
+ struct ip_fw *rule);
void ipfw_reap_rules(struct ip_fw *head);
+void ipfw_init_counters(void);
+void ipfw_destroy_counters(void);
+struct ip_fw *ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize);
+int ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt);
+
+typedef int (sopt_handler_f)(struct ip_fw_chain *ch,
+ ip_fw3_opheader *op3, struct sockopt_data *sd);
+struct ipfw_sopt_handler {
+ uint16_t opcode;
+ uint8_t version;
+ uint8_t dir;
+ sopt_handler_f *handler;
+ uint64_t refcnt;
+};
+#define HDIR_SET 0x01 /* Handler is used to set some data */
+#define HDIR_GET 0x02 /* Handler is used to retrieve data */
+#define HDIR_BOTH HDIR_GET|HDIR_SET
+
+void ipfw_init_sopt_handler(void);
+void ipfw_destroy_sopt_handler(void);
+void ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count);
+int ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count);
+caddr_t ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed);
+caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed);
+#define IPFW_ADD_SOPT_HANDLER(f, c) do { \
+ if ((f) != 0) \
+ ipfw_add_sopt_handler(c, \
+ sizeof(c) / sizeof(c[0])); \
+ } while(0)
+#define IPFW_DEL_SOPT_HANDLER(l, c) do { \
+ if ((l) != 0) \
+ ipfw_del_sopt_handler(c, \
+ sizeof(c) / sizeof(c[0])); \
+ } while(0)
+
+typedef void (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *,
+ void *arg);
+typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, void *key,
+ uint32_t kopt);
+typedef int (objhash_cmp_f)(struct named_object *no, void *key, uint32_t kopt);
+struct namedobj_instance *ipfw_objhash_create(uint32_t items);
+void ipfw_objhash_destroy(struct namedobj_instance *);
+void ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks);
+void ipfw_objhash_bitmap_merge(struct namedobj_instance *ni,
+ void **idx, int *blocks);
+void ipfw_objhash_bitmap_swap(struct namedobj_instance *ni,
+ void **idx, int *blocks);
+void ipfw_objhash_bitmap_free(void *idx, int blocks);
+void ipfw_objhash_set_hashf(struct namedobj_instance *ni, objhash_hash_f *f);
+struct named_object *ipfw_objhash_lookup_name(struct namedobj_instance *ni,
+ uint32_t set, char *name);
+struct named_object *ipfw_objhash_lookup_kidx(struct namedobj_instance *ni,
+ uint16_t idx);
+int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a,
+ struct named_object *b);
+void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no);
+void ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no);
+uint32_t ipfw_objhash_count(struct namedobj_instance *ni);
+void ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f,
+ void *arg);
+int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx);
+int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx);
+void ipfw_objhash_set_funcs(struct namedobj_instance *ni,
+ objhash_hash_f *hash_f, objhash_cmp_f *cmp_f);
/* In ip_fw_table.c */
-struct radix_node;
+struct table_info;
+
+typedef int (table_lookup_t)(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val);
+
int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
uint32_t *val);
-int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
- uint32_t *val, int type);
-int ipfw_init_tables(struct ip_fw_chain *ch);
-void ipfw_destroy_tables(struct ip_fw_chain *ch);
-int ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl);
-int ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
- uint8_t plen, uint8_t mlen, uint8_t type, uint32_t value);
-int ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
- uint8_t plen, uint8_t mlen, uint8_t type);
-int ipfw_count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
-int ipfw_dump_table_entry(struct radix_node *rn, void *arg);
-int ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl);
-int ipfw_count_xtable(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
-int ipfw_dump_xtable(struct ip_fw_chain *ch, ipfw_xtable *tbl);
+int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
+ void *paddr, uint32_t *val);
+int ipfw_init_tables(struct ip_fw_chain *ch, int first);
int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables);
+int ipfw_switch_tables_namespace(struct ip_fw_chain *ch, unsigned int nsets);
+void ipfw_destroy_tables(struct ip_fw_chain *ch, int last);
/* In ip_fw_nat.c -- XXX to be moved to ip_var.h */
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
index f5fbd15..bde8508 100644
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1,5 +1,7 @@
/*-
* Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
+ * Copyright (c) 2014 Yandex LLC
+ * Copyright (c) 2014 Alexander V. Chernikov
*
* Supported by: Valeria Paoli
*
@@ -29,8 +31,8 @@
__FBSDID("$FreeBSD$");
/*
- * Sockopt support for ipfw. The routines here implement
- * the upper half of the ipfw code.
+ * Control socket and rule management routines for ipfw.
+ * Control is currently implemented via IP_FW3 setsockopt() code.
*/
#include "opt_ipfw.h"
@@ -49,30 +51,177 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/rwlock.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
+#include <sys/fnv_hash.h>
#include <net/if.h>
#include <net/route.h>
#include <net/vnet.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
#include <netinet/in.h>
#include <netinet/ip_var.h> /* hooks */
#include <netinet/ip_fw.h>
#include <netpfil/ipfw/ip_fw_private.h>
+#include <netpfil/ipfw/ip_fw_table.h>
#ifdef MAC
#include <security/mac/mac_framework.h>
#endif
+static int ipfw_ctl(struct sockopt *sopt);
+static int check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len,
+ struct rule_check_info *ci);
+static int check_ipfw_rule1(struct ip_fw_rule *rule, int size,
+ struct rule_check_info *ci);
+static int check_ipfw_rule0(struct ip_fw_rule0 *rule, int size,
+ struct rule_check_info *ci);
+
+#define NAMEDOBJ_HASH_SIZE 32
+
+struct namedobj_instance {
+ struct namedobjects_head *names;
+ struct namedobjects_head *values;
+ uint32_t nn_size; /* names hash size */
+ uint32_t nv_size; /* number hash size */
+ u_long *idx_mask; /* used items bitmask */
+ uint32_t max_blocks; /* number of "long" blocks in bitmask */
+ uint32_t count; /* number of items */
+ uint16_t free_off[IPFW_MAX_SETS]; /* first possible free offset */
+ objhash_hash_f *hash_f;
+ objhash_cmp_f *cmp_f;
+};
+#define BLOCK_ITEMS (8 * sizeof(u_long)) /* Number of items for ffsl() */
+
+static uint32_t objhash_hash_name(struct namedobj_instance *ni, void *key,
+ uint32_t kopt);
+static uint32_t objhash_hash_idx(struct namedobj_instance *ni, uint32_t val);
+static int objhash_cmp_name(struct named_object *no, void *name, uint32_t set);
+
MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
+static int dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+static int add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+static int del_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+static int clear_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+static int move_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+static int manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+static int dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+
+/* ctl3 handler data */
+struct mtx ctl3_lock;
+#define CTL3_LOCK_INIT() mtx_init(&ctl3_lock, "ctl3_lock", NULL, MTX_DEF)
+#define CTL3_LOCK_DESTROY() mtx_destroy(&ctl3_lock)
+#define CTL3_LOCK() mtx_lock(&ctl3_lock)
+#define CTL3_UNLOCK() mtx_unlock(&ctl3_lock)
+
+static struct ipfw_sopt_handler *ctl3_handlers;
+static size_t ctl3_hsize;
+static uint64_t ctl3_refct, ctl3_gencnt;
+#define CTL3_SMALLBUF 4096 /* small page-size write buffer */
+#define CTL3_LARGEBUF 16 * 1024 * 1024 /* handle large rulesets */
+
+static int ipfw_flush_sopt_data(struct sockopt_data *sd);
+
+static struct ipfw_sopt_handler scodes[] = {
+ { IP_FW_XGET, 0, HDIR_GET, dump_config },
+ { IP_FW_XADD, 0, HDIR_BOTH, add_rules },
+ { IP_FW_XDEL, 0, HDIR_BOTH, del_rules },
+ { IP_FW_XZERO, 0, HDIR_SET, clear_rules },
+ { IP_FW_XRESETLOG, 0, HDIR_SET, clear_rules },
+ { IP_FW_XMOVE, 0, HDIR_SET, move_rules },
+ { IP_FW_SET_SWAP, 0, HDIR_SET, manage_sets },
+ { IP_FW_SET_MOVE, 0, HDIR_SET, manage_sets },
+ { IP_FW_SET_ENABLE, 0, HDIR_SET, manage_sets },
+ { IP_FW_DUMP_SOPTCODES, 0, HDIR_GET, dump_soptcodes },
+};
+
/*
- * static variables followed by global ones (none in this file)
+ * static variables followed by global ones
*/
+#ifndef USERSPACE
+
+static VNET_DEFINE(uma_zone_t, ipfw_cntr_zone);
+#define V_ipfw_cntr_zone VNET(ipfw_cntr_zone)
+
+void
+ipfw_init_counters()
+{
+
+ V_ipfw_cntr_zone = uma_zcreate("IPFW counters",
+ sizeof(ip_fw_cntr), NULL, NULL, NULL, NULL,
+ UMA_ALIGN_PTR, UMA_ZONE_PCPU);
+}
+
+void
+ipfw_destroy_counters()
+{
+
+ uma_zdestroy(V_ipfw_cntr_zone);
+}
+
+struct ip_fw *
+ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize)
+{
+ struct ip_fw *rule;
+
+ rule = malloc(rulesize, M_IPFW, M_WAITOK | M_ZERO);
+ rule->cntr = uma_zalloc(V_ipfw_cntr_zone, M_WAITOK | M_ZERO);
+
+ return (rule);
+}
+
+static void
+free_rule(struct ip_fw *rule)
+{
+
+ uma_zfree(V_ipfw_cntr_zone, rule->cntr);
+ free(rule, M_IPFW);
+}
+#else
+void
+ipfw_init_counters()
+{
+}
+
+void
+ipfw_destroy_counters()
+{
+}
+
+struct ip_fw *
+ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize)
+{
+ struct ip_fw *rule;
+
+ rule = malloc(rulesize, M_IPFW, M_WAITOK | M_ZERO);
+
+ return (rule);
+}
+
+static void
+free_rule(struct ip_fw *rule)
+{
+
+ free(rule, M_IPFW);
+}
+
+#endif
+
+
/*
* Find the smallest rule >= key, id.
* We could use bsearch but it is so simple that we code it directly
@@ -99,6 +248,104 @@ ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id)
}
/*
+ * Builds skipto cache on rule set @map.
+ */
+static void
+update_skipto_cache(struct ip_fw_chain *chain, struct ip_fw **map)
+{
+ int *smap, rulenum;
+ int i, mi;
+
+ IPFW_UH_WLOCK_ASSERT(chain);
+
+ mi = 0;
+ rulenum = map[mi]->rulenum;
+ smap = chain->idxmap_back;
+
+ if (smap == NULL)
+ return;
+
+ for (i = 0; i < 65536; i++) {
+ smap[i] = mi;
+ /* Use the same rule index until i < rulenum */
+ if (i != rulenum || i == 65535)
+ continue;
+ /* Find next rule with num > i */
+ rulenum = map[++mi]->rulenum;
+ while (rulenum == i)
+ rulenum = map[++mi]->rulenum;
+ }
+}
+
+/*
+ * Swaps prepared (backup) index with current one.
+ */
+static void
+swap_skipto_cache(struct ip_fw_chain *chain)
+{
+ int *map;
+
+ IPFW_UH_WLOCK_ASSERT(chain);
+ IPFW_WLOCK_ASSERT(chain);
+
+ map = chain->idxmap;
+ chain->idxmap = chain->idxmap_back;
+ chain->idxmap_back = map;
+}
+
+/*
+ * Allocate and initialize skipto cache.
+ */
+void
+ipfw_init_skipto_cache(struct ip_fw_chain *chain)
+{
+ int *idxmap, *idxmap_back;
+
+ idxmap = malloc(65536 * sizeof(uint32_t *), M_IPFW,
+ M_WAITOK | M_ZERO);
+ idxmap_back = malloc(65536 * sizeof(uint32_t *), M_IPFW,
+ M_WAITOK | M_ZERO);
+
+ /*
+ * Note we may be called at any time after initialization,
+ * for example, on first skipto rule, so we need to
+ * provide valid chain->idxmap on return
+ */
+
+ IPFW_UH_WLOCK(chain);
+ if (chain->idxmap != NULL) {
+ IPFW_UH_WUNLOCK(chain);
+ free(idxmap, M_IPFW);
+ free(idxmap_back, M_IPFW);
+ return;
+ }
+
+ /* Set backup pointer first to permit building cache */
+ chain->idxmap_back = idxmap_back;
+ update_skipto_cache(chain, chain->map);
+ IPFW_WLOCK(chain);
+ /* It is now safe to set chain->idxmap ptr */
+ chain->idxmap = idxmap;
+ swap_skipto_cache(chain);
+ IPFW_WUNLOCK(chain);
+ IPFW_UH_WUNLOCK(chain);
+}
+
+/*
+ * Destroys skipto cache.
+ */
+void
+ipfw_destroy_skipto_cache(struct ip_fw_chain *chain)
+{
+
+ if (chain->idxmap != NULL)
+ free(chain->idxmap, M_IPFW);
+ if (chain->idxmap != NULL)
+ free(chain->idxmap_back, M_IPFW);
+}
+
+
+/*
* allocate a new map, returns the chain locked. extra is the number
* of entries to add or delete.
*/
@@ -108,11 +355,12 @@ get_map(struct ip_fw_chain *chain, int extra, int locked)
for (;;) {
struct ip_fw **map;
- int i;
+ int i, mflags;
+
+ mflags = M_ZERO | ((locked != 0) ? M_NOWAIT : M_WAITOK);
i = chain->n_rules + extra;
- map = malloc(i * sizeof(struct ip_fw *), M_IPFW,
- locked ? M_NOWAIT : M_WAITOK);
+ map = malloc(i * sizeof(struct ip_fw *), M_IPFW, mflags);
if (map == NULL) {
printf("%s: cannot allocate map\n", __FUNCTION__);
return NULL;
@@ -141,67 +389,390 @@ swap_map(struct ip_fw_chain *chain, struct ip_fw **new_map, int new_len)
chain->n_rules = new_len;
old_map = chain->map;
chain->map = new_map;
+ swap_skipto_cache(chain);
IPFW_WUNLOCK(chain);
return old_map;
}
+
+static void
+export_cntr1_base(struct ip_fw *krule, struct ip_fw_bcounter *cntr)
+{
+
+ cntr->size = sizeof(*cntr);
+
+ if (krule->cntr != NULL) {
+ cntr->pcnt = counter_u64_fetch(krule->cntr);
+ cntr->bcnt = counter_u64_fetch(krule->cntr + 1);
+ cntr->timestamp = krule->timestamp;
+ }
+ if (cntr->timestamp > 0)
+ cntr->timestamp += boottime.tv_sec;
+}
+
+static void
+export_cntr0_base(struct ip_fw *krule, struct ip_fw_bcounter0 *cntr)
+{
+
+ if (krule->cntr != NULL) {
+ cntr->pcnt = counter_u64_fetch(krule->cntr);
+ cntr->bcnt = counter_u64_fetch(krule->cntr + 1);
+ cntr->timestamp = krule->timestamp;
+ }
+ if (cntr->timestamp > 0)
+ cntr->timestamp += boottime.tv_sec;
+}
+
+/*
+ * Copies rule @urule from v1 userland format (current).
+ * to kernel @krule.
+ * Assume @krule is zeroed.
+ */
+static void
+import_rule1(struct rule_check_info *ci)
+{
+ struct ip_fw_rule *urule;
+ struct ip_fw *krule;
+
+ urule = (struct ip_fw_rule *)ci->urule;
+ krule = (struct ip_fw *)ci->krule;
+
+ /* copy header */
+ krule->act_ofs = urule->act_ofs;
+ krule->cmd_len = urule->cmd_len;
+ krule->rulenum = urule->rulenum;
+ krule->set = urule->set;
+ krule->flags = urule->flags;
+
+ /* Save rulenum offset */
+ ci->urule_numoff = offsetof(struct ip_fw_rule, rulenum);
+
+ /* Copy opcodes */
+ memcpy(krule->cmd, urule->cmd, krule->cmd_len * sizeof(uint32_t));
+}
+
+/*
+ * Export rule into v1 format (Current).
+ * Layout:
+ * [ ipfw_obj_tlv(IPFW_TLV_RULE_ENT)
+ * [ ip_fw_rule ] OR
+ * [ ip_fw_bcounter ip_fw_rule] (depends on rcntrs).
+ * ]
+ * Assume @data is zeroed.
+ */
+static void
+export_rule1(struct ip_fw *krule, caddr_t data, int len, int rcntrs)
+{
+ struct ip_fw_bcounter *cntr;
+ struct ip_fw_rule *urule;
+ ipfw_obj_tlv *tlv;
+
+ /* Fill in TLV header */
+ tlv = (ipfw_obj_tlv *)data;
+ tlv->type = IPFW_TLV_RULE_ENT;
+ tlv->length = len;
+
+ if (rcntrs != 0) {
+ /* Copy counters */
+ cntr = (struct ip_fw_bcounter *)(tlv + 1);
+ urule = (struct ip_fw_rule *)(cntr + 1);
+ export_cntr1_base(krule, cntr);
+ } else
+ urule = (struct ip_fw_rule *)(tlv + 1);
+
+ /* copy header */
+ urule->act_ofs = krule->act_ofs;
+ urule->cmd_len = krule->cmd_len;
+ urule->rulenum = krule->rulenum;
+ urule->set = krule->set;
+ urule->flags = krule->flags;
+ urule->id = krule->id;
+
+ /* Copy opcodes */
+ memcpy(urule->cmd, krule->cmd, krule->cmd_len * sizeof(uint32_t));
+}
+
+
+/*
+ * Copies rule @urule from FreeBSD8 userland format (v0)
+ * to kernel @krule.
+ * Assume @krule is zeroed.
+ */
+static void
+import_rule0(struct rule_check_info *ci)
+{
+ struct ip_fw_rule0 *urule;
+ struct ip_fw *krule;
+ int cmdlen, l;
+ ipfw_insn *cmd;
+ ipfw_insn_limit *lcmd;
+ ipfw_insn_if *cmdif;
+
+ urule = (struct ip_fw_rule0 *)ci->urule;
+ krule = (struct ip_fw *)ci->krule;
+
+ /* copy header */
+ krule->act_ofs = urule->act_ofs;
+ krule->cmd_len = urule->cmd_len;
+ krule->rulenum = urule->rulenum;
+ krule->set = urule->set;
+ if ((urule->_pad & 1) != 0)
+ krule->flags |= IPFW_RULE_NOOPT;
+
+ /* Save rulenum offset */
+ ci->urule_numoff = offsetof(struct ip_fw_rule0, rulenum);
+
+ /* Copy opcodes */
+ memcpy(krule->cmd, urule->cmd, krule->cmd_len * sizeof(uint32_t));
+
+ /*
+ * Alter opcodes:
+ * 1) convert tablearg value from 65335 to 0
+ * 2) Add high bit to O_SETFIB/O_SETDSCP values (to make room for targ).
+ * 3) convert table number in iface opcodes to u16
+ */
+ l = krule->cmd_len;
+ cmd = krule->cmd;
+ cmdlen = 0;
+
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ switch (cmd->opcode) {
+ /* Opcodes supporting tablearg */
+ case O_TAG:
+ case O_TAGGED:
+ case O_PIPE:
+ case O_QUEUE:
+ case O_DIVERT:
+ case O_TEE:
+ case O_SKIPTO:
+ case O_CALLRETURN:
+ case O_NETGRAPH:
+ case O_NGTEE:
+ case O_NAT:
+ if (cmd->arg1 == 65535)
+ cmd->arg1 = IP_FW_TARG;
+ break;
+ case O_SETFIB:
+ case O_SETDSCP:
+ if (cmd->arg1 == 65535)
+ cmd->arg1 = IP_FW_TARG;
+ else
+ cmd->arg1 |= 0x8000;
+ break;
+ case O_LIMIT:
+ lcmd = (ipfw_insn_limit *)cmd;
+ if (lcmd->conn_limit == 65535)
+ lcmd->conn_limit = IP_FW_TARG;
+ break;
+ /* Interface tables */
+ case O_XMIT:
+ case O_RECV:
+ case O_VIA:
+ /* Interface table, possibly */
+ cmdif = (ipfw_insn_if *)cmd;
+ if (cmdif->name[0] != '\1')
+ break;
+
+ cmdif->p.kidx = (uint16_t)cmdif->p.glob;
+ break;
+ }
+ }
+}
+
/*
- * Add a new rule to the list. Copy the rule into a malloc'ed area, then
- * possibly create a rule number and add the rule to the list.
+ * Copies rule @krule from kernel to FreeBSD8 userland format (v0)
+ */
+static void
+export_rule0(struct ip_fw *krule, struct ip_fw_rule0 *urule, int len)
+{
+ int cmdlen, l;
+ ipfw_insn *cmd;
+ ipfw_insn_limit *lcmd;
+ ipfw_insn_if *cmdif;
+
+ /* copy header */
+ memset(urule, 0, len);
+ urule->act_ofs = krule->act_ofs;
+ urule->cmd_len = krule->cmd_len;
+ urule->rulenum = krule->rulenum;
+ urule->set = krule->set;
+ if ((krule->flags & IPFW_RULE_NOOPT) != 0)
+ urule->_pad |= 1;
+
+ /* Copy opcodes */
+ memcpy(urule->cmd, krule->cmd, krule->cmd_len * sizeof(uint32_t));
+
+ /* Export counters */
+ export_cntr0_base(krule, (struct ip_fw_bcounter0 *)&urule->pcnt);
+
+ /*
+ * Alter opcodes:
+ * 1) convert tablearg value from 0 to 65335
+ * 2) Remove highest bit from O_SETFIB/O_SETDSCP values.
+ * 3) convert table number in iface opcodes to int
+ */
+ l = urule->cmd_len;
+ cmd = urule->cmd;
+ cmdlen = 0;
+
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ switch (cmd->opcode) {
+ /* Opcodes supporting tablearg */
+ case O_TAG:
+ case O_TAGGED:
+ case O_PIPE:
+ case O_QUEUE:
+ case O_DIVERT:
+ case O_TEE:
+ case O_SKIPTO:
+ case O_CALLRETURN:
+ case O_NETGRAPH:
+ case O_NGTEE:
+ case O_NAT:
+ if (cmd->arg1 == IP_FW_TARG)
+ cmd->arg1 = 65535;
+ break;
+ case O_SETFIB:
+ case O_SETDSCP:
+ if (cmd->arg1 == IP_FW_TARG)
+ cmd->arg1 = 65535;
+ else
+ cmd->arg1 &= ~0x8000;
+ break;
+ case O_LIMIT:
+ lcmd = (ipfw_insn_limit *)cmd;
+ if (lcmd->conn_limit == IP_FW_TARG)
+ lcmd->conn_limit = 65535;
+ break;
+ /* Interface tables */
+ case O_XMIT:
+ case O_RECV:
+ case O_VIA:
+ /* Interface table, possibly */
+ cmdif = (ipfw_insn_if *)cmd;
+ if (cmdif->name[0] != '\1')
+ break;
+
+ cmdif->p.glob = cmdif->p.kidx;
+ break;
+ }
+ }
+}
+
+/*
+ * Add new rule(s) to the list possibly creating rule number for each.
* Update the rule_number in the input struct so the caller knows it as well.
- * XXX DO NOT USE FOR THE DEFAULT RULE.
* Must be called without IPFW_UH held
*/
-int
-ipfw_add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule)
+static int
+commit_rules(struct ip_fw_chain *chain, struct rule_check_info *rci, int count)
{
- struct ip_fw *rule;
- int i, l, insert_before;
+ int error, i, insert_before, tcount;
+ uint16_t rulenum, *pnum;
+ struct rule_check_info *ci;
+ struct ip_fw *krule;
struct ip_fw **map; /* the new array of pointers */
- if (chain->map == NULL || input_rule->rulenum > IPFW_DEFAULT_RULE - 1)
- return (EINVAL);
+ /* Check if we need to do table remap */
+ tcount = 0;
+ for (ci = rci, i = 0; i < count; ci++, i++) {
+ if (ci->table_opcodes == 0)
+ continue;
+
+ /*
+ * Rule has some table opcodes.
+ * Reference & allocate needed tables/
+ */
+ error = ipfw_rewrite_table_uidx(chain, ci);
+ if (error != 0) {
+
+ /*
+ * rewrite failed, state for current rule
+ * has been reverted. Check if we need to
+ * revert more.
+ */
+ if (tcount > 0) {
+
+ /*
+ * We have some more table rules
+ * we need to rollback.
+ */
+
+ IPFW_UH_WLOCK(chain);
+ while (ci != rci) {
+ ci--;
+ if (ci->table_opcodes == 0)
+ continue;
+ ipfw_unref_rule_tables(chain,ci->krule);
+
+ }
+ IPFW_UH_WUNLOCK(chain);
+
+ }
+
+ return (error);
+ }
+
+ tcount++;
+ }
- l = RULESIZE(input_rule);
- rule = malloc(l, M_IPFW, M_WAITOK | M_ZERO);
/* get_map returns with IPFW_UH_WLOCK if successful */
- map = get_map(chain, 1, 0 /* not locked */);
+ map = get_map(chain, count, 0 /* not locked */);
if (map == NULL) {
- free(rule, M_IPFW);
- return ENOSPC;
- }
+ if (tcount > 0) {
+ /* Unbind tables */
+ IPFW_UH_WLOCK(chain);
+ for (ci = rci, i = 0; i < count; ci++, i++) {
+ if (ci->table_opcodes == 0)
+ continue;
- bcopy(input_rule, rule, l);
- /* clear fields not settable from userland */
- rule->x_next = NULL;
- rule->next_rule = NULL;
- IPFW_ZERO_RULE_COUNTER(rule);
+ ipfw_unref_rule_tables(chain, ci->krule);
+ }
+ IPFW_UH_WUNLOCK(chain);
+ }
+
+ return (ENOSPC);
+ }
if (V_autoinc_step < 1)
V_autoinc_step = 1;
else if (V_autoinc_step > 1000)
V_autoinc_step = 1000;
+
+ /* FIXME: Handle count > 1 */
+ ci = rci;
+ krule = ci->krule;
+ rulenum = krule->rulenum;
+
/* find the insertion point, we will insert before */
- insert_before = rule->rulenum ? rule->rulenum + 1 : IPFW_DEFAULT_RULE;
+ insert_before = rulenum ? rulenum + 1 : IPFW_DEFAULT_RULE;
i = ipfw_find_rule(chain, insert_before, 0);
/* duplicate first part */
if (i > 0)
bcopy(chain->map, map, i * sizeof(struct ip_fw *));
- map[i] = rule;
+ map[i] = krule;
/* duplicate remaining part, we always have the default rule */
bcopy(chain->map + i, map + i + 1,
sizeof(struct ip_fw *) *(chain->n_rules - i));
- if (rule->rulenum == 0) {
- /* write back the number */
- rule->rulenum = i > 0 ? map[i-1]->rulenum : 0;
- if (rule->rulenum < IPFW_DEFAULT_RULE - V_autoinc_step)
- rule->rulenum += V_autoinc_step;
- input_rule->rulenum = rule->rulenum;
+ if (rulenum == 0) {
+ /* Compute rule number and write it back */
+ rulenum = i > 0 ? map[i-1]->rulenum : 0;
+ if (rulenum < IPFW_DEFAULT_RULE - V_autoinc_step)
+ rulenum += V_autoinc_step;
+ krule->rulenum = rulenum;
+ /* Save number to userland rule */
+ pnum = (uint16_t *)((caddr_t)ci->urule + ci->urule_numoff);
+ *pnum = rulenum;
}
- rule->id = chain->id + 1;
+ krule->id = chain->id + 1;
+ update_skipto_cache(chain, map);
map = swap_map(chain, map, chain->n_rules + 1);
- chain->static_len += l;
+ chain->static_len += RULEUSIZE0(krule);
IPFW_UH_WUNLOCK(chain);
if (map)
free(map, M_IPFW);
@@ -209,6 +780,23 @@ ipfw_add_rule(struct ip_fw_chain *chain, struct ip_fw *input_rule)
}
/*
+ * Adds @rule to the list of rules to reap
+ */
+void
+ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head,
+ struct ip_fw *rule)
+{
+
+ IPFW_UH_WLOCK_ASSERT(chain);
+
+ /* Unlink rule from everywhere */
+ ipfw_unref_rule_tables(chain, rule);
+
+ *((struct ip_fw **)rule) = *head;
+ *head = rule;
+}
+
+/*
* Reclaim storage associated with a list of rules. This is
* typically the list created using remove_rule.
* A NULL pointer on input is handled correctly.
@@ -219,22 +807,12 @@ ipfw_reap_rules(struct ip_fw *head)
struct ip_fw *rule;
while ((rule = head) != NULL) {
- head = head->x_next;
- free(rule, M_IPFW);
+ head = *((struct ip_fw **)head);
+ free_rule(rule);
}
}
/*
- * Used by del_entry() to check if a rule should be kept.
- * Returns 1 if the rule must be kept, 0 otherwise.
- *
- * Called with cmd = {0,1,5}.
- * cmd == 0 matches on rule numbers, excludes rules in RESVD_SET if n == 0 ;
- * cmd == 1 matches on set numbers only, rule numbers are ignored;
- * cmd == 5 matches on rule and set numbers.
- *
- * n == 0 is a wildcard for rule numbers, there is no wildcard for sets.
- *
* Rules to keep are
* (default || reserved || !match_set || !match_number)
* where
@@ -251,14 +829,384 @@ ipfw_reap_rules(struct ip_fw *head)
* // number is ignored for cmd == 1 or n == 0
*
*/
+int
+ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt)
+{
+
+ /* Don't match default rule regardless of query */
+ if (rule->rulenum == IPFW_DEFAULT_RULE)
+ return (0);
+
+ /* Don't match rules in reserved set for flush requests */
+ if ((rt->flags & IPFW_RCFLAG_ALL) != 0 && rule->set == RESVD_SET)
+ return (0);
+
+ /* If we're filtering by set, don't match other sets */
+ if ((rt->flags & IPFW_RCFLAG_SET) != 0 && rule->set != rt->set)
+ return (0);
+
+ if ((rt->flags & IPFW_RCFLAG_RANGE) != 0 &&
+ (rule->rulenum < rt->start_rule || rule->rulenum > rt->end_rule))
+ return (0);
+
+ return (1);
+}
+
+/*
+ * Delete rules matching range @rt.
+ * Saves number of deleted rules in @ndel.
+ *
+ * Returns 0 on success.
+ */
static int
-keep_rule(struct ip_fw *rule, uint8_t cmd, uint8_t set, uint32_t n)
+delete_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int *ndel)
{
- return
- (rule->rulenum == IPFW_DEFAULT_RULE) ||
- (cmd == 0 && n == 0 && rule->set == RESVD_SET) ||
- !(cmd == 0 || rule->set == set) ||
- !(cmd == 1 || n == 0 || n == rule->rulenum);
+ struct ip_fw *reap, *rule, **map;
+ int end, start;
+ int i, n, ndyn, ofs;
+
+ reap = NULL;
+ IPFW_UH_WLOCK(chain); /* arbitrate writers */
+
+ /*
+ * Stage 1: Determine range to inspect.
+ * Range is half-inclusive, e.g [start, end).
+ */
+ start = 0;
+ end = chain->n_rules - 1;
+
+ if ((rt->flags & IPFW_RCFLAG_RANGE) != 0) {
+ start = ipfw_find_rule(chain, rt->start_rule, 0);
+
+ end = ipfw_find_rule(chain, rt->end_rule, 0);
+ if (rt->end_rule != IPFW_DEFAULT_RULE)
+ while (chain->map[end]->rulenum == rt->end_rule)
+ end++;
+ }
+
+ /* Allocate new map of the same size */
+ map = get_map(chain, 0, 1 /* locked */);
+ if (map == NULL) {
+ IPFW_UH_WUNLOCK(chain);
+ return (ENOMEM);
+ }
+
+ n = 0;
+ ndyn = 0;
+ ofs = start;
+ /* 1. bcopy the initial part of the map */
+ if (start > 0)
+ bcopy(chain->map, map, start * sizeof(struct ip_fw *));
+ /* 2. copy active rules between start and end */
+ for (i = start; i < end; i++) {
+ rule = chain->map[i];
+ if (ipfw_match_range(rule, rt) == 0) {
+ map[ofs++] = rule;
+ continue;
+ }
+
+ n++;
+ if (ipfw_is_dyn_rule(rule) != 0)
+ ndyn++;
+ }
+ /* 3. copy the final part of the map */
+ bcopy(chain->map + end, map + ofs,
+ (chain->n_rules - end) * sizeof(struct ip_fw *));
+ /* 4. recalculate skipto cache */
+ update_skipto_cache(chain, map);
+ /* 5. swap the maps (under UH_WLOCK + WHLOCK) */
+ map = swap_map(chain, map, chain->n_rules - n);
+ /* 6. Remove all dynamic states originated by deleted rules */
+ if (ndyn > 0)
+ ipfw_expire_dyn_rules(chain, rt);
+ /* 7. now remove the rules deleted from the old map */
+ for (i = start; i < end; i++) {
+ rule = map[i];
+ if (ipfw_match_range(rule, rt) == 0)
+ continue;
+ chain->static_len -= RULEUSIZE0(rule);
+ ipfw_reap_add(chain, &reap, rule);
+ }
+ IPFW_UH_WUNLOCK(chain);
+
+ ipfw_reap_rules(reap);
+ if (map != NULL)
+ free(map, M_IPFW);
+ *ndel = n;
+ return (0);
+}
+
+/*
+ * Changes set of given rule rannge @rt
+ * with each other.
+ *
+ * Returns 0 on success.
+ */
+static int
+move_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt)
+{
+ struct ip_fw *rule;
+ int i;
+
+ IPFW_UH_WLOCK(chain);
+
+ /*
+ * Move rules with matching paramenerts to a new set.
+ * This one is much more complex. We have to ensure
+ * that all referenced tables (if any) are referenced
+ * by given rule subset only. Otherwise, we can't move
+ * them to new set and have to return error.
+ */
+ if (V_fw_tables_sets != 0) {
+ if (ipfw_move_tables_sets(chain, rt, rt->new_set) != 0) {
+ IPFW_UH_WUNLOCK(chain);
+ return (EBUSY);
+ }
+ }
+
+ /* XXX: We have to do swap holding WLOCK */
+ for (i = 0; i < chain->n_rules - 1; i++) {
+ rule = chain->map[i];
+ if (ipfw_match_range(rule, rt) == 0)
+ continue;
+ rule->set = rt->new_set;
+ }
+
+ IPFW_UH_WUNLOCK(chain);
+
+ return (0);
+}
+
+/*
+ * Clear counters for a specific rule.
+ * Normally run under IPFW_UH_RLOCK, but these are idempotent ops
+ * so we only care that rules do not disappear.
+ */
+static void
+clear_counters(struct ip_fw *rule, int log_only)
+{
+ ipfw_insn_log *l = (ipfw_insn_log *)ACTION_PTR(rule);
+
+ if (log_only == 0)
+ IPFW_ZERO_RULE_COUNTER(rule);
+ if (l->o.opcode == O_LOG)
+ l->log_left = l->max_log;
+}
+
+/*
+ * Flushes rules counters and/or log values on matching range.
+ *
+ * Returns number of items cleared.
+ */
+static int
+clear_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int log_only)
+{
+ struct ip_fw *rule;
+ int num;
+ int i;
+
+ num = 0;
+
+ IPFW_UH_WLOCK(chain); /* arbitrate writers */
+ for (i = 0; i < chain->n_rules - 1; i++) {
+ rule = chain->map[i];
+ if (ipfw_match_range(rule, rt) == 0)
+ continue;
+ clear_counters(rule, log_only);
+ num++;
+ }
+ IPFW_UH_WUNLOCK(chain);
+
+ return (num);
+}
+
+static int
+check_range_tlv(ipfw_range_tlv *rt)
+{
+
+ if (rt->head.length != sizeof(*rt))
+ return (1);
+ if (rt->start_rule > rt->end_rule)
+ return (1);
+ if (rt->set >= IPFW_MAX_SETS || rt->new_set >= IPFW_MAX_SETS)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Delete rules matching specified parameters
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_range_tlv ]
+ * Reply: [ ipfw_obj_header ipfw_range_tlv ]
+ *
+ * Saves number of deleted rules in ipfw_range_tlv->new_set.
+ *
+ * Returns 0 on success.
+ */
+static int
+del_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_range_header *rh;
+ int error, ndel;
+
+ if (sd->valsize != sizeof(*rh))
+ return (EINVAL);
+
+ rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize);
+
+ if (check_range_tlv(&rh->range) != 0)
+ return (EINVAL);
+
+ ndel = 0;
+ if ((error = delete_range(chain, &rh->range, &ndel)) != 0)
+ return (error);
+
+ /* Save number of rules deleted */
+ rh->range.new_set = ndel;
+ return (0);
+}
+
+/*
+ * Move rules/sets matching specified parameters
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_range_tlv ]
+ *
+ * Returns 0 on success.
+ */
+static int
+move_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_range_header *rh;
+
+ if (sd->valsize != sizeof(*rh))
+ return (EINVAL);
+
+ rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize);
+
+ if (check_range_tlv(&rh->range) != 0)
+ return (EINVAL);
+
+ return (move_range(chain, &rh->range));
+}
+
+/*
+ * Clear rule accounting data matching specified parameters
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_range_tlv ]
+ * Reply: [ ipfw_obj_header ipfw_range_tlv ]
+ *
+ * Saves number of cleared rules in ipfw_range_tlv->new_set.
+ *
+ * Returns 0 on success.
+ */
+static int
+clear_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_range_header *rh;
+ int log_only, num;
+ char *msg;
+
+ if (sd->valsize != sizeof(*rh))
+ return (EINVAL);
+
+ rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize);
+
+ if (check_range_tlv(&rh->range) != 0)
+ return (EINVAL);
+
+ log_only = (op3->opcode == IP_FW_XRESETLOG);
+
+ num = clear_range(chain, &rh->range, log_only);
+
+ if (rh->range.flags & IPFW_RCFLAG_ALL)
+ msg = log_only ? "All logging counts reset" :
+ "Accounting cleared";
+ else
+ msg = log_only ? "logging count reset" : "cleared";
+
+ if (V_fw_verbose) {
+ int lev = LOG_SECURITY | LOG_NOTICE;
+ log(lev, "ipfw: %s.\n", msg);
+ }
+
+ /* Save number of rules cleared */
+ rh->range.new_set = num;
+ return (0);
+}
+
+static void
+enable_sets(struct ip_fw_chain *chain, ipfw_range_tlv *rt)
+{
+ uint32_t v_set;
+
+ IPFW_UH_WLOCK_ASSERT(chain);
+
+ /* Change enabled/disabled sets mask */
+ v_set = (V_set_disable | rt->set) & ~rt->new_set;
+ v_set &= ~(1 << RESVD_SET); /* set RESVD_SET always enabled */
+ IPFW_WLOCK(chain);
+ V_set_disable = v_set;
+ IPFW_WUNLOCK(chain);
+}
+
+static void
+swap_sets(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int mv)
+{
+ struct ip_fw *rule;
+ int i;
+
+ IPFW_UH_WLOCK_ASSERT(chain);
+
+ /* Swap or move two sets */
+ for (i = 0; i < chain->n_rules - 1; i++) {
+ rule = chain->map[i];
+ if (rule->set == rt->set)
+ rule->set = rt->new_set;
+ else if (rule->set == rt->new_set && mv == 0)
+ rule->set = rt->set;
+ }
+ if (V_fw_tables_sets != 0)
+ ipfw_swap_tables_sets(chain, rt->set, rt->new_set, mv);
+}
+
+/*
+ * Swaps or moves set
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_range_tlv ]
+ *
+ * Returns 0 on success.
+ */
+static int
+manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_range_header *rh;
+
+ if (sd->valsize != sizeof(*rh))
+ return (EINVAL);
+
+ rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize);
+
+ if (rh->range.head.length != sizeof(ipfw_range_tlv))
+ return (1);
+
+ IPFW_UH_WLOCK(chain);
+ switch (op3->opcode) {
+ case IP_FW_SET_SWAP:
+ case IP_FW_SET_MOVE:
+ swap_sets(chain, &rh->range, op3->opcode == IP_FW_SET_MOVE);
+ break;
+ case IP_FW_SET_ENABLE:
+ enable_sets(chain, &rh->range);
+ break;
+ }
+ IPFW_UH_WUNLOCK(chain);
+
+ return (0);
}
/**
@@ -278,12 +1226,11 @@ keep_rule(struct ip_fw *rule, uint8_t cmd, uint8_t set, uint32_t n)
static int
del_entry(struct ip_fw_chain *chain, uint32_t arg)
{
- struct ip_fw *rule;
uint32_t num; /* rule number or old_set */
uint8_t cmd, new_set;
- int start, end, i, ofs, n;
- struct ip_fw **map = NULL;
+ int do_del, ndel;
int error = 0;
+ ipfw_range_tlv rt;
num = arg & 0xffff;
cmd = (arg >> 24) & 0xff;
@@ -299,149 +1246,60 @@ del_entry(struct ip_fw_chain *chain, uint32_t arg)
return EINVAL;
}
- IPFW_UH_WLOCK(chain); /* arbitrate writers */
- chain->reap = NULL; /* prepare for deletions */
+ /* Convert old requests into new representation */
+ memset(&rt, 0, sizeof(rt));
+ rt.start_rule = num;
+ rt.end_rule = num;
+ rt.set = num;
+ rt.new_set = new_set;
+ do_del = 0;
switch (cmd) {
- case 0: /* delete rules "num" (num == 0 matches all) */
- case 1: /* delete all rules in set N */
- case 5: /* delete rules with number N and set "new_set". */
-
- /*
- * Locate first rule to delete (start), the rule after
- * the last one to delete (end), and count how many
- * rules to delete (n). Always use keep_rule() to
- * determine which rules to keep.
- */
- n = 0;
- if (cmd == 1) {
- /* look for a specific set including RESVD_SET.
- * Must scan the entire range, ignore num.
- */
- new_set = num;
- for (start = -1, end = i = 0; i < chain->n_rules; i++) {
- if (keep_rule(chain->map[i], cmd, new_set, 0))
- continue;
- if (start < 0)
- start = i;
- end = i;
- n++;
- }
- end++; /* first non-matching */
- } else {
- /* Optimized search on rule numbers */
- start = ipfw_find_rule(chain, num, 0);
- for (end = start; end < chain->n_rules; end++) {
- rule = chain->map[end];
- if (num > 0 && rule->rulenum != num)
- break;
- if (!keep_rule(rule, cmd, new_set, num))
- n++;
- }
- }
-
- if (n == 0) {
- /* A flush request (arg == 0 or cmd == 1) on empty
- * ruleset returns with no error. On the contrary,
- * if there is no match on a specific request,
- * we return EINVAL.
- */
- if (arg != 0 && cmd != 1)
- error = EINVAL;
- break;
- }
-
- /* We have something to delete. Allocate the new map */
- map = get_map(chain, -n, 1 /* locked */);
- if (map == NULL) {
- error = EINVAL;
- break;
- }
-
- /* 1. bcopy the initial part of the map */
- if (start > 0)
- bcopy(chain->map, map, start * sizeof(struct ip_fw *));
- /* 2. copy active rules between start and end */
- for (i = ofs = start; i < end; i++) {
- rule = chain->map[i];
- if (keep_rule(rule, cmd, new_set, num))
- map[ofs++] = rule;
- }
- /* 3. copy the final part of the map */
- bcopy(chain->map + end, map + ofs,
- (chain->n_rules - end) * sizeof(struct ip_fw *));
- /* 4. swap the maps (under BH_LOCK) */
- map = swap_map(chain, map, chain->n_rules - n);
- /* 5. now remove the rules deleted from the old map */
- if (cmd == 1)
- ipfw_expire_dyn_rules(chain, NULL, new_set);
- for (i = start; i < end; i++) {
- rule = map[i];
- if (keep_rule(rule, cmd, new_set, num))
- continue;
- chain->static_len -= RULESIZE(rule);
- if (cmd != 1)
- ipfw_expire_dyn_rules(chain, rule, RESVD_SET);
- rule->x_next = chain->reap;
- chain->reap = rule;
- }
+ case 0: /* delete rules numbered "rulenum" */
+ if (num == 0)
+ rt.flags |= IPFW_RCFLAG_ALL;
+ else
+ rt.flags |= IPFW_RCFLAG_RANGE;
+ do_del = 1;
break;
-
- /*
- * In the next 3 cases the loop stops at (n_rules - 1)
- * because the default rule is never eligible..
- */
-
- case 2: /* move rules with given RULE number to new set */
- for (i = 0; i < chain->n_rules - 1; i++) {
- rule = chain->map[i];
- if (rule->rulenum == num)
- rule->set = new_set;
- }
+ case 1: /* delete rules in set "rulenum" */
+ rt.flags |= IPFW_RCFLAG_SET;
+ do_del = 1;
break;
-
- case 3: /* move rules with given SET number to new set */
- for (i = 0; i < chain->n_rules - 1; i++) {
- rule = chain->map[i];
- if (rule->set == num)
- rule->set = new_set;
- }
+ case 5: /* delete rules "rulenum" and set "new_set" */
+ rt.flags |= IPFW_RCFLAG_RANGE | IPFW_RCFLAG_SET;
+ rt.set = new_set;
+ rt.new_set = 0;
+ do_del = 1;
break;
-
- case 4: /* swap two sets */
- for (i = 0; i < chain->n_rules - 1; i++) {
- rule = chain->map[i];
- if (rule->set == num)
- rule->set = new_set;
- else if (rule->set == new_set)
- rule->set = num;
- }
+ case 2: /* move rules "rulenum" to set "new_set" */
+ rt.flags |= IPFW_RCFLAG_RANGE;
break;
+ case 3: /* move rules from set "rulenum" to set "new_set" */
+ IPFW_UH_WLOCK(chain);
+ swap_sets(chain, &rt, 1);
+ IPFW_UH_WUNLOCK(chain);
+ return (0);
+ case 4: /* swap sets "rulenum" and "new_set" */
+ IPFW_UH_WLOCK(chain);
+ swap_sets(chain, &rt, 0);
+ IPFW_UH_WUNLOCK(chain);
+ return (0);
+ default:
+ return (ENOTSUP);
}
- rule = chain->reap;
- chain->reap = NULL;
- IPFW_UH_WUNLOCK(chain);
- ipfw_reap_rules(rule);
- if (map)
- free(map, M_IPFW);
- return error;
-}
+ if (do_del != 0) {
+ if ((error = delete_range(chain, &rt, &ndel)) != 0)
+ return (error);
-/*
- * Clear counters for a specific rule.
- * Normally run under IPFW_UH_RLOCK, but these are idempotent ops
- * so we only care that rules do not disappear.
- */
-static void
-clear_counters(struct ip_fw *rule, int log_only)
-{
- ipfw_insn_log *l = (ipfw_insn_log *)ACTION_PTR(rule);
+ if (ndel == 0 && (cmd != 1 && num != 0))
+ return (EINVAL);
- if (log_only == 0)
- IPFW_ZERO_RULE_COUNTER(rule);
- if (l->o.opcode == O_LOG)
- l->log_left = l->max_log;
+ return (0);
+ }
+
+ return (move_range(chain, &rt));
}
/**
@@ -512,23 +1370,57 @@ zero_entry(struct ip_fw_chain *chain, u_int32_t arg, int log_only)
return (0);
}
+
/*
- * Check validity of the structure before insert.
- * Rules are simple, so this mostly need to check rule sizes.
+ * Check rule head in FreeBSD11 format
+ *
*/
static int
-check_ipfw_struct(struct ip_fw *rule, int size)
+check_ipfw_rule1(struct ip_fw_rule *rule, int size,
+ struct rule_check_info *ci)
{
- int l, cmdlen = 0;
- int have_action=0;
- ipfw_insn *cmd;
+ int l;
+
+ if (size < sizeof(*rule)) {
+ printf("ipfw: rule too short\n");
+ return (EINVAL);
+ }
+
+ /* Check for valid cmd_len */
+ l = roundup2(RULESIZE(rule), sizeof(uint64_t));
+ if (l != size) {
+ printf("ipfw: size mismatch (have %d want %d)\n", size, l);
+ return (EINVAL);
+ }
+ if (rule->act_ofs >= rule->cmd_len) {
+ printf("ipfw: bogus action offset (%u > %u)\n",
+ rule->act_ofs, rule->cmd_len - 1);
+ return (EINVAL);
+ }
+
+ if (rule->rulenum > IPFW_DEFAULT_RULE - 1)
+ return (EINVAL);
+
+ return (check_ipfw_rule_body(rule->cmd, rule->cmd_len, ci));
+}
+
+/*
+ * Check rule head in FreeBSD8 format
+ *
+ */
+static int
+check_ipfw_rule0(struct ip_fw_rule0 *rule, int size,
+ struct rule_check_info *ci)
+{
+ int l;
if (size < sizeof(*rule)) {
printf("ipfw: rule too short\n");
return (EINVAL);
}
- /* first, check for valid size */
- l = RULESIZE(rule);
+
+ /* Check for valid cmd_len */
+ l = sizeof(*rule) + rule->cmd_len * 4 - 4;
if (l != size) {
printf("ipfw: size mismatch (have %d want %d)\n", size, l);
return (EINVAL);
@@ -538,12 +1430,26 @@ check_ipfw_struct(struct ip_fw *rule, int size)
rule->act_ofs, rule->cmd_len - 1);
return (EINVAL);
}
+
+ if (rule->rulenum > IPFW_DEFAULT_RULE - 1)
+ return (EINVAL);
+
+ return (check_ipfw_rule_body(rule->cmd, rule->cmd_len, ci));
+}
+
+static int
+check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
+{
+ int cmdlen, l;
+ int have_action;
+
+ have_action = 0;
+
/*
* Now go for the individual checks. Very simple ones, basically only
* instruction sizes.
*/
- for (l = rule->cmd_len, cmd = rule->cmd ;
- l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ for (l = cmd_len; l > 0 ; l -= cmdlen, cmd += cmdlen) {
cmdlen = F_LEN(cmd);
if (cmdlen > l) {
printf("ipfw: opcode %d size truncated\n",
@@ -597,10 +1503,10 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_SETFIB:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size;
- if ((cmd->arg1 != IP_FW_TABLEARG) &&
- (cmd->arg1 >= rt_numfibs)) {
+ if ((cmd->arg1 != IP_FW_TARG) &&
+ ((cmd->arg1 & 0x7FFFF) >= rt_numfibs)) {
printf("ipfw: invalid fib number %d\n",
- cmd->arg1);
+ cmd->arg1 & 0x7FFFF);
return EINVAL;
}
goto check_action;
@@ -662,6 +1568,18 @@ check_ipfw_struct(struct ip_fw *rule, int size)
cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1 &&
cmdlen != F_INSN_SIZE(ipfw_insn_u32))
goto bad_size;
+ ci->table_opcodes++;
+ break;
+ case O_IP_FLOW_LOOKUP:
+ if (cmd->arg1 >= V_fw_tables_max) {
+ printf("ipfw: invalid table number %d\n",
+ cmd->arg1);
+ return (EINVAL);
+ }
+ if (cmdlen != F_INSN_SIZE(ipfw_insn) &&
+ cmdlen != F_INSN_SIZE(ipfw_insn_u32))
+ goto bad_size;
+ ci->table_opcodes++;
break;
case O_MACADDR2:
if (cmdlen != F_INSN_SIZE(ipfw_insn_mac))
@@ -694,6 +1612,8 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_RECV:
case O_XMIT:
case O_VIA:
+ if (((ipfw_insn_if *)cmd)->name[0] == '\1')
+ ci->table_opcodes++;
if (cmdlen != F_INSN_SIZE(ipfw_insn_if))
goto bad_size;
break;
@@ -859,8 +1779,8 @@ struct ip_fw7 {
ipfw_insn cmd[1]; /* storage for commands */
};
- int convert_rule_to_7(struct ip_fw *rule);
-int convert_rule_to_8(struct ip_fw *rule);
+static int convert_rule_to_7(struct ip_fw_rule0 *rule);
+static int convert_rule_to_8(struct ip_fw_rule0 *rule);
#ifndef RULESIZE7
#define RULESIZE7(rule) (sizeof(struct ip_fw7) + \
@@ -878,10 +1798,13 @@ ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
{
char *bp = buf;
char *ep = bp + space;
- struct ip_fw *rule, *dst;
- int l, i;
+ struct ip_fw *rule;
+ struct ip_fw_rule0 *dst;
+ int error, i, l, warnflag;
time_t boot_seconds;
+ warnflag = 0;
+
boot_seconds = boottime.tv_sec;
for (i = 0; i < chain->n_rules; i++) {
rule = chain->map[i];
@@ -890,9 +1813,12 @@ ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
/* Convert rule to FreeBSd 7.2 format */
l = RULESIZE7(rule);
if (bp + l + sizeof(uint32_t) <= ep) {
- int error;
bcopy(rule, bp, l + sizeof(uint32_t));
- error = convert_rule_to_7((struct ip_fw *) bp);
+ error = ipfw_rewrite_table_kidx(chain,
+ (struct ip_fw_rule0 *)bp);
+ if (error != 0)
+ return (0);
+ error = convert_rule_to_7((struct ip_fw_rule0 *) bp);
if (error)
return 0; /*XXX correct? */
/*
@@ -910,76 +1836,944 @@ ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space)
continue; /* go to next rule */
}
- /* normal mode, don't touch rules */
- l = RULESIZE(rule);
+ l = RULEUSIZE0(rule);
if (bp + l > ep) { /* should not happen */
printf("overflow dumping static rules\n");
break;
}
- dst = (struct ip_fw *)bp;
- bcopy(rule, dst, l);
+ dst = (struct ip_fw_rule0 *)bp;
+ export_rule0(rule, dst, l);
+ error = ipfw_rewrite_table_kidx(chain, dst);
+
/*
* XXX HACK. Store the disable mask in the "next"
* pointer in a wild attempt to keep the ABI the same.
* Why do we do this on EVERY rule?
+ *
+ * XXX: "ipfw set show" (ab)uses IP_FW_GET to read disabled mask
+ * so we need to fail _after_ saving at least one mask.
*/
bcopy(&V_set_disable, &dst->next_rule, sizeof(V_set_disable));
if (dst->timestamp)
dst->timestamp += boot_seconds;
bp += l;
+
+ if (error != 0) {
+ if (error == 2) {
+ /* Non-fatal table rewrite error. */
+ warnflag = 1;
+ continue;
+ }
+ printf("Stop on rule %d. Fail to convert table\n",
+ rule->rulenum);
+ break;
+ }
}
+ if (warnflag != 0)
+ printf("ipfw: process %s is using legacy interfaces,"
+ " consider rebuilding\n", "");
ipfw_get_dynamic(chain, &bp, ep); /* protected by the dynamic lock */
return (bp - (char *)buf);
}
-#define IP_FW3_OPLENGTH(x) ((x)->sopt_valsize - sizeof(ip_fw3_opheader))
-/**
- * {set|get}sockopt parser.
+struct dump_args {
+ uint32_t b; /* start rule */
+ uint32_t e; /* end rule */
+ uint32_t rcount; /* number of rules */
+ uint32_t rsize; /* rules size */
+ uint32_t tcount; /* number of tables */
+ int rcounters; /* counters */
+};
+
+/*
+ * Dumps static rules with table TLVs in buffer @sd.
+ *
+ * Returns 0 on success.
+ */
+static int
+dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da,
+ uint32_t *bmask, struct sockopt_data *sd)
+{
+ int error;
+ int i, l;
+ uint32_t tcount;
+ ipfw_obj_ctlv *ctlv;
+ struct ip_fw *krule;
+ caddr_t dst;
+
+ /* Dump table names first (if any) */
+ if (da->tcount > 0) {
+ /* Header first */
+ ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv));
+ if (ctlv == NULL)
+ return (ENOMEM);
+ ctlv->head.type = IPFW_TLV_TBLNAME_LIST;
+ ctlv->head.length = da->tcount * sizeof(ipfw_obj_ntlv) +
+ sizeof(*ctlv);
+ ctlv->count = da->tcount;
+ ctlv->objsize = sizeof(ipfw_obj_ntlv);
+ }
+
+ i = 0;
+ tcount = da->tcount;
+ while (tcount > 0) {
+ if ((bmask[i / 32] & (1 << (i % 32))) == 0) {
+ i++;
+ continue;
+ }
+
+ if ((error = ipfw_export_table_ntlv(chain, i, sd)) != 0)
+ return (error);
+
+ i++;
+ tcount--;
+ }
+
+ /* Dump rules */
+ ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv));
+ if (ctlv == NULL)
+ return (ENOMEM);
+ ctlv->head.type = IPFW_TLV_RULE_LIST;
+ ctlv->head.length = da->rsize + sizeof(*ctlv);
+ ctlv->count = da->rcount;
+
+ for (i = da->b; i < da->e; i++) {
+ krule = chain->map[i];
+
+ l = RULEUSIZE1(krule) + sizeof(ipfw_obj_tlv);
+ if (da->rcounters != 0)
+ l += sizeof(struct ip_fw_bcounter);
+ dst = (caddr_t)ipfw_get_sopt_space(sd, l);
+ if (dst == NULL)
+ return (ENOMEM);
+
+ export_rule1(krule, dst, l, da->rcounters);
+ }
+
+ return (0);
+}
+
+/*
+ * Dumps requested objects data
+ * Data layout (version 0)(current):
+ * Request: [ ipfw_cfg_lheader ] + IPFW_CFG_GET_* flags
+ * size = ipfw_cfg_lheader.size
+ * Reply: [ ipfw_cfg_lheader
+ * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional)
+ * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST)
+ * ipfw_obj_tlv(IPFW_TLV_RULE_ENT) [ ip_fw_bcounter (optional) ip_fw_rule ]
+ * ] (optional)
+ * [ ipfw_obj_ctlv(IPFW_TLV_STATE_LIST) ipfw_obj_dyntlv x N ] (optional)
+ * ]
+ * * NOTE IPFW_TLV_STATE_LIST has the single valid field: objsize.
+ * The rest (size, count) are set to zero and needs to be ignored.
+ *
+ * Returns 0 on success.
+ */
+static int
+dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_cfg_lheader *hdr;
+ struct ip_fw *rule;
+ size_t sz, rnum;
+ uint32_t hdr_flags;
+ int error, i;
+ struct dump_args da;
+ uint32_t *bmask;
+
+ hdr = (ipfw_cfg_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr));
+ if (hdr == NULL)
+ return (EINVAL);
+
+ error = 0;
+ bmask = NULL;
+ /* Allocate needed state */
+ if (hdr->flags & IPFW_CFG_GET_STATIC)
+ bmask = malloc(IPFW_TABLES_MAX / 8, M_TEMP, M_WAITOK | M_ZERO);
+
+ IPFW_UH_RLOCK(chain);
+
+ /*
+ * STAGE 1: Determine size/count for objects in range.
+ * Prepare used tables bitmask.
+ */
+ sz = sizeof(ipfw_cfg_lheader);
+ memset(&da, 0, sizeof(da));
+
+ da.b = 0;
+ da.e = chain->n_rules;
+
+ if (hdr->end_rule != 0) {
+ /* Handle custom range */
+ if ((rnum = hdr->start_rule) > IPFW_DEFAULT_RULE)
+ rnum = IPFW_DEFAULT_RULE;
+ da.b = ipfw_find_rule(chain, rnum, 0);
+ rnum = hdr->end_rule;
+ rnum = (rnum < IPFW_DEFAULT_RULE) ? rnum+1 : IPFW_DEFAULT_RULE;
+ da.e = ipfw_find_rule(chain, rnum, 0);
+ }
+
+ if (hdr->flags & IPFW_CFG_GET_STATIC) {
+ for (i = da.b; i < da.e; i++) {
+ rule = chain->map[i];
+ da.rsize += RULEUSIZE1(rule) + sizeof(ipfw_obj_tlv);
+ da.rcount++;
+ da.tcount += ipfw_mark_table_kidx(chain, rule, bmask);
+ }
+ /* Add counters if requested */
+ if (hdr->flags & IPFW_CFG_GET_COUNTERS) {
+ da.rsize += sizeof(struct ip_fw_bcounter) * da.rcount;
+ da.rcounters = 1;
+ }
+
+ if (da.tcount > 0)
+ sz += da.tcount * sizeof(ipfw_obj_ntlv) +
+ sizeof(ipfw_obj_ctlv);
+ sz += da.rsize + sizeof(ipfw_obj_ctlv);
+ }
+
+ if (hdr->flags & IPFW_CFG_GET_STATES)
+ sz += ipfw_dyn_get_count() * sizeof(ipfw_obj_dyntlv) +
+ sizeof(ipfw_obj_ctlv);
+
+
+ /*
+ * Fill header anyway.
+ * Note we have to save header fields to stable storage
+ * buffer inside @sd can be flushed after dumping rules
+ */
+ hdr->size = sz;
+ hdr->set_mask = ~V_set_disable;
+ hdr_flags = hdr->flags;
+ hdr = NULL;
+
+ if (sd->valsize < sz) {
+ error = ENOMEM;
+ goto cleanup;
+ }
+
+ /* STAGE2: Store actual data */
+ if (hdr_flags & IPFW_CFG_GET_STATIC) {
+ error = dump_static_rules(chain, &da, bmask, sd);
+ if (error != 0)
+ goto cleanup;
+ }
+
+ if (hdr_flags & IPFW_CFG_GET_STATES)
+ error = ipfw_dump_states(chain, sd);
+
+cleanup:
+ IPFW_UH_RUNLOCK(chain);
+
+ if (bmask != NULL)
+ free(bmask, M_TEMP);
+
+ return (error);
+}
+
+static int
+check_object_name(ipfw_obj_ntlv *ntlv)
+{
+ int error;
+
+ switch (ntlv->head.type) {
+ case IPFW_TLV_TBL_NAME:
+ error = ipfw_check_table_name(ntlv->name);
+ break;
+ default:
+ error = ENOTSUP;
+ }
+
+ return (0);
+}
+
+/*
+ * Adds one or more rules to ipfw @chain.
+ * Data layout (version 0)(current):
+ * Request:
+ * [
+ * ip_fw3_opheader
+ * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional *1)
+ * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ] (*2) (*3)
+ * ]
+ * Reply:
+ * [
+ * ip_fw3_opheader
+ * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional)
+ * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ]
+ * ]
+ *
+ * Rules in reply are modified to store their actual ruleset number.
+ *
+ * (*1) TLVs inside IPFW_TLV_TBL_LIST needs to be sorted ascending
+ * accoring to their idx field and there has to be no duplicates.
+ * (*2) Numbered rules inside IPFW_TLV_RULE_LIST needs to be sorted ascending.
+ * (*3) Each ip_fw structure needs to be aligned to u64 boundary.
+ *
+ * Returns 0 on success.
+ */
+static int
+add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_ctlv *ctlv, *rtlv, *tstate;
+ ipfw_obj_ntlv *ntlv;
+ int clen, error, idx;
+ uint32_t count, read;
+ struct ip_fw_rule *r;
+ struct rule_check_info rci, *ci, *cbuf;
+ int i, rsize;
+
+ op3 = (ip_fw3_opheader *)ipfw_get_sopt_space(sd, sd->valsize);
+ ctlv = (ipfw_obj_ctlv *)(op3 + 1);
+
+ read = sizeof(ip_fw3_opheader);
+ rtlv = NULL;
+ tstate = NULL;
+ cbuf = NULL;
+ memset(&rci, 0, sizeof(struct rule_check_info));
+
+ if (read + sizeof(*ctlv) > sd->valsize)
+ return (EINVAL);
+
+ if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
+ clen = ctlv->head.length;
+ /* Check size and alignment */
+ if (clen > sd->valsize || clen < sizeof(*ctlv))
+ return (EINVAL);
+ if ((clen % sizeof(uint64_t)) != 0)
+ return (EINVAL);
+
+ /*
+ * Some table names or other named objects.
+ * Check for validness.
+ */
+ count = (ctlv->head.length - sizeof(*ctlv)) / sizeof(*ntlv);
+ if (ctlv->count != count || ctlv->objsize != sizeof(*ntlv))
+ return (EINVAL);
+
+ /*
+ * Check each TLV.
+ * Ensure TLVs are sorted ascending and
+ * there are no duplicates.
+ */
+ idx = -1;
+ ntlv = (ipfw_obj_ntlv *)(ctlv + 1);
+ while (count > 0) {
+ if (ntlv->head.length != sizeof(ipfw_obj_ntlv))
+ return (EINVAL);
+
+ error = check_object_name(ntlv);
+ if (error != 0)
+ return (error);
+
+ if (ntlv->idx <= idx)
+ return (EINVAL);
+
+ idx = ntlv->idx;
+ count--;
+ ntlv++;
+ }
+
+ tstate = ctlv;
+ read += ctlv->head.length;
+ ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length);
+ }
+
+ if (read + sizeof(*ctlv) > sd->valsize)
+ return (EINVAL);
+
+ if (ctlv->head.type == IPFW_TLV_RULE_LIST) {
+ clen = ctlv->head.length;
+ if (clen + read > sd->valsize || clen < sizeof(*ctlv))
+ return (EINVAL);
+ if ((clen % sizeof(uint64_t)) != 0)
+ return (EINVAL);
+
+ /*
+ * TODO: Permit adding multiple rules at once
+ */
+ if (ctlv->count != 1)
+ return (ENOTSUP);
+
+ clen -= sizeof(*ctlv);
+
+ if (ctlv->count > clen / sizeof(struct ip_fw_rule))
+ return (EINVAL);
+
+ /* Allocate state for each rule or use stack */
+ if (ctlv->count == 1) {
+ memset(&rci, 0, sizeof(struct rule_check_info));
+ cbuf = &rci;
+ } else
+ cbuf = malloc(ctlv->count * sizeof(*ci), M_TEMP,
+ M_WAITOK | M_ZERO);
+ ci = cbuf;
+
+ /*
+ * Check each rule for validness.
+ * Ensure numbered rules are sorted ascending
+ * and properly aligned
+ */
+ idx = 0;
+ r = (struct ip_fw_rule *)(ctlv + 1);
+ count = 0;
+ error = 0;
+ while (clen > 0) {
+ rsize = roundup2(RULESIZE(r), sizeof(uint64_t));
+ if (rsize > clen || ctlv->count <= count) {
+ error = EINVAL;
+ break;
+ }
+
+ ci->ctlv = tstate;
+ error = check_ipfw_rule1(r, rsize, ci);
+ if (error != 0)
+ break;
+
+ /* Check sorting */
+ if (r->rulenum != 0 && r->rulenum < idx) {
+ printf("rulenum %d idx %d\n", r->rulenum, idx);
+ error = EINVAL;
+ break;
+ }
+ idx = r->rulenum;
+
+ ci->urule = (caddr_t)r;
+
+ rsize = roundup2(rsize, sizeof(uint64_t));
+ clen -= rsize;
+ r = (struct ip_fw_rule *)((caddr_t)r + rsize);
+ count++;
+ ci++;
+ }
+
+ if (ctlv->count != count || error != 0) {
+ if (cbuf != &rci)
+ free(cbuf, M_TEMP);
+ return (EINVAL);
+ }
+
+ rtlv = ctlv;
+ read += ctlv->head.length;
+ ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length);
+ }
+
+ if (read != sd->valsize || rtlv == NULL || rtlv->count == 0) {
+ if (cbuf != NULL && cbuf != &rci)
+ free(cbuf, M_TEMP);
+ return (EINVAL);
+ }
+
+ /*
+ * Passed rules seems to be valid.
+ * Allocate storage and try to add them to chain.
+ */
+ for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++) {
+ clen = RULEKSIZE1((struct ip_fw_rule *)ci->urule);
+ ci->krule = ipfw_alloc_rule(chain, clen);
+ import_rule1(ci);
+ }
+
+ if ((error = commit_rules(chain, cbuf, rtlv->count)) != 0) {
+ /* Free allocate krules */
+ for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++)
+ free(ci->krule, M_IPFW);
+ }
+
+ if (cbuf != NULL && cbuf != &rci)
+ free(cbuf, M_TEMP);
+
+ return (error);
+}
+
+/*
+ * Lists all sopts currently registered.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_sopt_info x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ struct _ipfw_obj_lheader *olh;
+ ipfw_sopt_info *i;
+ struct ipfw_sopt_handler *sh;
+ uint32_t count, n, size;
+
+ olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
+ if (olh == NULL)
+ return (EINVAL);
+ if (sd->valsize < olh->size)
+ return (EINVAL);
+
+ CTL3_LOCK();
+ count = ctl3_hsize;
+ size = count * sizeof(ipfw_sopt_info) + sizeof(ipfw_obj_lheader);
+
+ /* Fill in header regadless of buffer size */
+ olh->count = count;
+ olh->objsize = sizeof(ipfw_sopt_info);
+
+ if (size > olh->size) {
+ olh->size = size;
+ CTL3_UNLOCK();
+ return (ENOMEM);
+ }
+ olh->size = size;
+
+ for (n = 1; n <= count; n++) {
+ i = (ipfw_sopt_info *)ipfw_get_sopt_space(sd, sizeof(*i));
+ KASSERT(i != 0, ("previously checked buffer is not enough"));
+ sh = &ctl3_handlers[n];
+ i->opcode = sh->opcode;
+ i->version = sh->version;
+ i->refcnt = sh->refcnt;
+ }
+ CTL3_UNLOCK();
+
+ return (0);
+}
+
+/*
+ * Compares two sopt handlers (code, version and handler ptr).
+ * Used both as qsort() and bsearch().
+ * Does not compare handler for latter case.
+ *
+ * Returns 0 if match is found.
+ */
+static int
+compare_sh(const void *_a, const void *_b)
+{
+ const struct ipfw_sopt_handler *a, *b;
+
+ a = (const struct ipfw_sopt_handler *)_a;
+ b = (const struct ipfw_sopt_handler *)_b;
+
+ if (a->opcode < b->opcode)
+ return (-1);
+ else if (a->opcode > b->opcode)
+ return (1);
+
+ if (a->version < b->version)
+ return (-1);
+ else if (a->version > b->version)
+ return (1);
+
+ /* bsearch helper */
+ if (a->handler == NULL)
+ return (0);
+
+ if ((uintptr_t)a->handler < (uintptr_t)b->handler)
+ return (-1);
+ else if ((uintptr_t)b->handler > (uintptr_t)b->handler)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Finds sopt handler based on @code and @version.
+ *
+ * Returns pointer to handler or NULL.
+ */
+static struct ipfw_sopt_handler *
+find_sh(uint16_t code, uint8_t version, void *handler)
+{
+ struct ipfw_sopt_handler *sh, h;
+
+ memset(&h, 0, sizeof(h));
+ h.opcode = code;
+ h.version = version;
+ h.handler = handler;
+
+ sh = (struct ipfw_sopt_handler *)bsearch(&h, ctl3_handlers,
+ ctl3_hsize, sizeof(h), compare_sh);
+
+ return (sh);
+}
+
+static int
+find_ref_sh(uint16_t opcode, uint8_t version, struct ipfw_sopt_handler *psh)
+{
+ struct ipfw_sopt_handler *sh;
+
+ CTL3_LOCK();
+ if ((sh = find_sh(opcode, version, NULL)) == NULL) {
+ CTL3_UNLOCK();
+ printf("ipfw: ipfw_ctl3 invalid option %d""v""%d\n",
+ opcode, version);
+ return (EINVAL);
+ }
+ sh->refcnt++;
+ ctl3_refct++;
+ /* Copy handler data to requested buffer */
+ *psh = *sh;
+ CTL3_UNLOCK();
+
+ return (0);
+}
+
+static void
+find_unref_sh(struct ipfw_sopt_handler *psh)
+{
+ struct ipfw_sopt_handler *sh;
+
+ CTL3_LOCK();
+ sh = find_sh(psh->opcode, psh->version, NULL);
+ KASSERT(sh != NULL, ("ctl3 handler disappeared"));
+ sh->refcnt--;
+ ctl3_refct--;
+ CTL3_UNLOCK();
+}
+
+void
+ipfw_init_sopt_handler()
+{
+
+ CTL3_LOCK_INIT();
+ IPFW_ADD_SOPT_HANDLER(1, scodes);
+}
+
+void
+ipfw_destroy_sopt_handler()
+{
+
+ IPFW_DEL_SOPT_HANDLER(1, scodes);
+ CTL3_LOCK_DESTROY();
+}
+
+/*
+ * Adds one or more sockopt handlers to the global array.
+ * Function may sleep.
+ */
+void
+ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count)
+{
+ size_t sz;
+ struct ipfw_sopt_handler *tmp;
+
+ CTL3_LOCK();
+
+ for (;;) {
+ sz = ctl3_hsize + count;
+ CTL3_UNLOCK();
+ tmp = malloc(sizeof(*sh) * sz, M_IPFW, M_WAITOK | M_ZERO);
+ CTL3_LOCK();
+ if (ctl3_hsize + count <= sz)
+ break;
+
+ /* Retry */
+ free(tmp, M_IPFW);
+ }
+
+ /* Merge old & new arrays */
+ sz = ctl3_hsize + count;
+ memcpy(tmp, ctl3_handlers, ctl3_hsize * sizeof(*sh));
+ memcpy(&tmp[ctl3_hsize], sh, count * sizeof(*sh));
+ qsort(tmp, sz, sizeof(*sh), compare_sh);
+ /* Switch new and free old */
+ if (ctl3_handlers != NULL)
+ free(ctl3_handlers, M_IPFW);
+ ctl3_handlers = tmp;
+ ctl3_hsize = sz;
+ ctl3_gencnt++;
+
+ CTL3_UNLOCK();
+}
+
+/*
+ * Removes one or more sockopt handlers from the global array.
*/
int
-ipfw_ctl(struct sockopt *sopt)
+ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count)
+{
+ size_t sz;
+ struct ipfw_sopt_handler *tmp, *h;
+ int i;
+
+ CTL3_LOCK();
+
+ for (i = 0; i < count; i++) {
+ tmp = &sh[i];
+ h = find_sh(tmp->opcode, tmp->version, tmp->handler);
+ if (h == NULL)
+ continue;
+
+ sz = (ctl3_handlers + ctl3_hsize - (h + 1)) * sizeof(*h);
+ memmove(h, h + 1, sz);
+ ctl3_hsize--;
+ }
+
+ if (ctl3_hsize == 0) {
+ if (ctl3_handlers != NULL)
+ free(ctl3_handlers, M_IPFW);
+ ctl3_handlers = NULL;
+ }
+
+ ctl3_gencnt++;
+
+ CTL3_UNLOCK();
+
+ return (0);
+}
+
+/*
+ * Writes data accumulated in @sd to sockopt buffer.
+ * Zeroes internal @sd buffer.
+ */
+static int
+ipfw_flush_sopt_data(struct sockopt_data *sd)
+{
+#define RULE_MAXSIZE (512*sizeof(u_int32_t))
+ int error;
+ size_t sz;
+
+ if ((sz = sd->koff) == 0)
+ return (0);
+
+ if (sd->sopt->sopt_dir == SOPT_GET) {
+ error = sooptcopyout(sd->sopt, sd->kbuf, sz);
+ if (error != 0)
+ return (error);
+ }
+
+ memset(sd->kbuf, 0, sd->ksize);
+ sd->ktotal += sd->koff;
+ sd->koff = 0;
+ if (sd->ktotal + sd->ksize < sd->valsize)
+ sd->kavail = sd->ksize;
+ else
+ sd->kavail = sd->valsize - sd->ktotal;
+
+ /* Update sopt buffer */
+ sd->sopt->sopt_valsize = sd->ktotal;
+ sd->sopt->sopt_val = sd->sopt_val + sd->ktotal;
+
+ return (0);
+}
+
+/*
+ * Ensures that @sd buffer has contigious @neeeded number of
+ * bytes.
+ *
+ * Returns pointer to requested space or NULL.
+ */
+caddr_t
+ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed)
{
-#define RULE_MAXSIZE (256*sizeof(u_int32_t))
int error;
- size_t size, len, valsize;
- struct ip_fw *buf, *rule;
+ caddr_t addr;
+
+ if (sd->kavail < needed) {
+ /*
+ * Flush data and try another time.
+ */
+ error = ipfw_flush_sopt_data(sd);
+
+ if (sd->kavail < needed || error != 0)
+ return (NULL);
+ }
+
+ addr = sd->kbuf + sd->koff;
+ sd->koff += needed;
+ sd->kavail -= needed;
+ return (addr);
+}
+
+/*
+ * Requests @needed contigious bytes from @sd buffer.
+ * Function is used to notify subsystem that we are
+ * interesed in first @needed bytes (request header)
+ * and the rest buffer can be safely zeroed.
+ *
+ * Returns pointer to requested space or NULL.
+ */
+caddr_t
+ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed)
+{
+ caddr_t addr;
+
+ if ((addr = ipfw_get_sopt_space(sd, needed)) == NULL)
+ return (NULL);
+
+ if (sd->kavail > 0)
+ memset(sd->kbuf + sd->koff, 0, sd->kavail);
+
+ return (addr);
+}
+
+/*
+ * New sockopt handler.
+ */
+int
+ipfw_ctl3(struct sockopt *sopt)
+{
+ int error, locked;
+ size_t size, valsize;
struct ip_fw_chain *chain;
- u_int32_t rulenum[2];
- uint32_t opt;
- char xbuf[128];
+ char xbuf[256];
+ struct sockopt_data sdata;
+ struct ipfw_sopt_handler h;
ip_fw3_opheader *op3 = NULL;
error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
- if (error)
+ if (error != 0)
+ return (error);
+
+ if (sopt->sopt_name != IP_FW3)
+ return (ipfw_ctl(sopt));
+
+ chain = &V_layer3_chain;
+ error = 0;
+
+ /* Save original valsize before it is altered via sooptcopyin() */
+ valsize = sopt->sopt_valsize;
+ memset(&sdata, 0, sizeof(sdata));
+ /* Read op3 header first to determine actual operation */
+ op3 = (ip_fw3_opheader *)xbuf;
+ error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3));
+ if (error != 0)
+ return (error);
+ sopt->sopt_valsize = valsize;
+
+ /*
+ * Find and reference command.
+ */
+ error = find_ref_sh(op3->opcode, op3->version, &h);
+ if (error != 0)
return (error);
/*
* Disallow modifications in really-really secure mode, but still allow
* the logging counters to be reset.
*/
- if (sopt->sopt_name == IP_FW_ADD ||
- (sopt->sopt_dir == SOPT_SET && sopt->sopt_name != IP_FW_RESETLOG)) {
+ if ((h.dir & HDIR_SET) != 0 && h.opcode != IP_FW_XRESETLOG) {
error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
- if (error)
+ if (error != 0) {
+ find_unref_sh(&h);
return (error);
+ }
}
+ /*
+ * Fill in sockopt_data structure that may be useful for
+ * IP_FW3 get requests.
+ */
+ locked = 0;
+ if (valsize <= sizeof(xbuf)) {
+ /* use on-stack buffer */
+ sdata.kbuf = xbuf;
+ sdata.ksize = sizeof(xbuf);
+ sdata.kavail = valsize;
+ } else {
+
+ /*
+ * Determine opcode type/buffer size:
+ * allocate sliding-window buf for data export or
+ * contigious buffer for special ops.
+ */
+ if ((h.dir & HDIR_SET) != 0) {
+ /* Set request. Allocate contigous buffer. */
+ if (valsize > CTL3_LARGEBUF) {
+ find_unref_sh(&h);
+ return (EFBIG);
+ }
+
+ size = valsize;
+ } else {
+ /* Get request. Allocate sliding window buffer */
+ size = (valsize<CTL3_SMALLBUF) ? valsize:CTL3_SMALLBUF;
+
+ if (size < valsize) {
+ /* We have to wire user buffer */
+ error = vslock(sopt->sopt_val, valsize);
+ if (error != 0)
+ return (error);
+ locked = 1;
+ }
+ }
+
+ sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
+ sdata.ksize = size;
+ sdata.kavail = size;
+ }
+
+ sdata.sopt = sopt;
+ sdata.sopt_val = sopt->sopt_val;
+ sdata.valsize = valsize;
+
+ /*
+ * Copy either all request (if valsize < bsize_max)
+ * or first bsize_max bytes to guarantee most consumers
+ * that all necessary data has been copied).
+ * Anyway, copy not less than sizeof(ip_fw3_opheader).
+ */
+ if ((error = sooptcopyin(sopt, sdata.kbuf, sdata.ksize,
+ sizeof(ip_fw3_opheader))) != 0)
+ return (error);
+ op3 = (ip_fw3_opheader *)sdata.kbuf;
+
+ /* Finally, run handler */
+ error = h.handler(chain, op3, &sdata);
+ find_unref_sh(&h);
+
+ /* Flush state and free buffers */
+ if (error == 0)
+ error = ipfw_flush_sopt_data(&sdata);
+ else
+ ipfw_flush_sopt_data(&sdata);
+
+ if (locked != 0)
+ vsunlock(sdata.sopt_val, valsize);
+
+ /* Restore original pointer and set number of bytes written */
+ sopt->sopt_val = sdata.sopt_val;
+ sopt->sopt_valsize = sdata.ktotal;
+ if (sdata.kbuf != xbuf)
+ free(sdata.kbuf, M_TEMP);
+
+ return (error);
+}
+
+/**
+ * {set|get}sockopt parser.
+ */
+int
+ipfw_ctl(struct sockopt *sopt)
+{
+#define RULE_MAXSIZE (512*sizeof(u_int32_t))
+ int error;
+ size_t size, valsize;
+ struct ip_fw *buf;
+ struct ip_fw_rule0 *rule;
+ struct ip_fw_chain *chain;
+ u_int32_t rulenum[2];
+ uint32_t opt;
+ struct rule_check_info ci;
+ IPFW_RLOCK_TRACKER;
+
chain = &V_layer3_chain;
error = 0;
/* Save original valsize before it is altered via sooptcopyin() */
valsize = sopt->sopt_valsize;
- if ((opt = sopt->sopt_name) == IP_FW3) {
- /*
- * Copy not less than sizeof(ip_fw3_opheader).
- * We hope any IP_FW3 command will fit into 128-byte buffer.
- */
- if ((error = sooptcopyin(sopt, xbuf, sizeof(xbuf),
- sizeof(ip_fw3_opheader))) != 0)
+ opt = sopt->sopt_name;
+
+ /*
+ * Disallow modifications in really-really secure mode, but still allow
+ * the logging counters to be reset.
+ */
+ if (opt == IP_FW_ADD ||
+ (sopt->sopt_dir == SOPT_SET && opt != IP_FW_RESETLOG)) {
+ error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
+ if (error != 0)
return (error);
- op3 = (ip_fw3_opheader *)xbuf;
- opt = op3->opcode;
}
switch (opt) {
@@ -1002,7 +2796,7 @@ ipfw_ctl(struct sockopt *sopt)
size += ipfw_dyn_len();
if (size >= sopt->sopt_valsize)
break;
- buf = malloc(size, M_TEMP, M_WAITOK);
+ buf = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
IPFW_UH_RLOCK(chain);
/* check again how much space we need */
want = chain->static_len + ipfw_dyn_len();
@@ -1027,6 +2821,8 @@ ipfw_ctl(struct sockopt *sopt)
error = sooptcopyin(sopt, rule, RULE_MAXSIZE,
sizeof(struct ip_fw7) );
+ memset(&ci, 0, sizeof(struct rule_check_info));
+
/*
* If the size of commands equals RULESIZE7 then we assume
* a FreeBSD7.2 binary is talking to us (set is7=1).
@@ -1036,24 +2832,27 @@ ipfw_ctl(struct sockopt *sopt)
* the first ipfw command is 'ipfw [pipe] list')
* the ipfw binary may crash or loop infinitly...
*/
- if (sopt->sopt_valsize == RULESIZE7(rule)) {
+ size = sopt->sopt_valsize;
+ if (size == RULESIZE7(rule)) {
is7 = 1;
error = convert_rule_to_8(rule);
if (error) {
free(rule, M_TEMP);
return error;
}
- if (error == 0)
- error = check_ipfw_struct(rule, RULESIZE(rule));
- } else {
+ size = RULESIZE(rule);
+ } else
is7 = 0;
if (error == 0)
- error = check_ipfw_struct(rule, sopt->sopt_valsize);
- }
+ error = check_ipfw_rule0(rule, size, &ci);
if (error == 0) {
- /* locking is done within ipfw_add_rule() */
- error = ipfw_add_rule(chain, rule);
- size = RULESIZE(rule);
+ /* locking is done within add_rule() */
+ struct ip_fw *krule;
+ krule = ipfw_alloc_rule(chain, RULEKSIZE0(rule));
+ ci.urule = (caddr_t)rule;
+ ci.krule = krule;
+ import_rule0(&ci);
+ error = commit_rules(chain, &ci, 1);
if (!error && sopt->sopt_dir == SOPT_GET) {
if (is7) {
error = convert_rule_to_7(rule);
@@ -1113,82 +2912,64 @@ ipfw_ctl(struct sockopt *sopt)
sopt->sopt_name == IP_FW_RESETLOG);
break;
- /*--- TABLE manipulations are protected by the IPFW_LOCK ---*/
+ /*--- TABLE opcodes ---*/
case IP_FW_TABLE_ADD:
- {
- ipfw_table_entry ent;
-
- error = sooptcopyin(sopt, &ent,
- sizeof(ent), sizeof(ent));
- if (error)
- break;
- error = ipfw_add_table_entry(chain, ent.tbl,
- &ent.addr, sizeof(ent.addr), ent.masklen,
- IPFW_TABLE_CIDR, ent.value);
- }
- break;
-
case IP_FW_TABLE_DEL:
{
ipfw_table_entry ent;
+ struct tentry_info tei;
+ struct tid_info ti;
+ struct table_value v;
error = sooptcopyin(sopt, &ent,
sizeof(ent), sizeof(ent));
if (error)
break;
- error = ipfw_del_table_entry(chain, ent.tbl,
- &ent.addr, sizeof(ent.addr), ent.masklen, IPFW_TABLE_CIDR);
- }
- break;
- case IP_FW_TABLE_XADD: /* IP_FW3 */
- case IP_FW_TABLE_XDEL: /* IP_FW3 */
- {
- ipfw_table_xentry *xent = (ipfw_table_xentry *)(op3 + 1);
-
- /* Check minimum header size */
- if (IP_FW3_OPLENGTH(sopt) < offsetof(ipfw_table_xentry, k)) {
- error = EINVAL;
- break;
- }
-
- /* Check if len field is valid */
- if (xent->len > sizeof(ipfw_table_xentry)) {
- error = EINVAL;
- break;
- }
-
- len = xent->len - offsetof(ipfw_table_xentry, k);
-
- error = (opt == IP_FW_TABLE_XADD) ?
- ipfw_add_table_entry(chain, xent->tbl, &xent->k,
- len, xent->masklen, xent->type, xent->value) :
- ipfw_del_table_entry(chain, xent->tbl, &xent->k,
- len, xent->masklen, xent->type);
+ memset(&tei, 0, sizeof(tei));
+ tei.paddr = &ent.addr;
+ tei.subtype = AF_INET;
+ tei.masklen = ent.masklen;
+ ipfw_import_table_value_legacy(ent.value, &v);
+ tei.pvalue = &v;
+ memset(&ti, 0, sizeof(ti));
+ ti.uidx = ent.tbl;
+ ti.type = IPFW_TABLE_CIDR;
+
+ error = (opt == IP_FW_TABLE_ADD) ?
+ add_table_entry(chain, &ti, &tei, 0, 1) :
+ del_table_entry(chain, &ti, &tei, 0, 1);
}
break;
+
case IP_FW_TABLE_FLUSH:
{
u_int16_t tbl;
+ struct tid_info ti;
error = sooptcopyin(sopt, &tbl,
sizeof(tbl), sizeof(tbl));
if (error)
break;
- error = ipfw_flush_table(chain, tbl);
+ memset(&ti, 0, sizeof(ti));
+ ti.uidx = tbl;
+ error = flush_table(chain, &ti);
}
break;
case IP_FW_TABLE_GETSIZE:
{
u_int32_t tbl, cnt;
+ struct tid_info ti;
if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl),
sizeof(tbl))))
break;
+ memset(&ti, 0, sizeof(ti));
+ ti.uidx = tbl;
IPFW_RLOCK(chain);
- error = ipfw_count_table(chain, tbl, &cnt);
+ error = ipfw_count_table(chain, &ti, &cnt);
IPFW_RUNLOCK(chain);
if (error)
break;
@@ -1199,6 +2980,7 @@ ipfw_ctl(struct sockopt *sopt)
case IP_FW_TABLE_LIST:
{
ipfw_table *tbl;
+ struct tid_info ti;
if (sopt->sopt_valsize < sizeof(*tbl)) {
error = EINVAL;
@@ -1213,8 +2995,10 @@ ipfw_ctl(struct sockopt *sopt)
}
tbl->size = (size - sizeof(*tbl)) /
sizeof(ipfw_table_entry);
+ memset(&ti, 0, sizeof(ti));
+ ti.uidx = tbl->tbl;
IPFW_RLOCK(chain);
- error = ipfw_dump_table(chain, tbl);
+ error = ipfw_dump_table_legacy(chain, &ti, tbl);
IPFW_RUNLOCK(chain);
if (error) {
free(tbl, M_TEMP);
@@ -1225,62 +3009,6 @@ ipfw_ctl(struct sockopt *sopt)
}
break;
- case IP_FW_TABLE_XGETSIZE: /* IP_FW3 */
- {
- uint32_t *tbl;
-
- if (IP_FW3_OPLENGTH(sopt) < sizeof(uint32_t)) {
- error = EINVAL;
- break;
- }
-
- tbl = (uint32_t *)(op3 + 1);
-
- IPFW_RLOCK(chain);
- error = ipfw_count_xtable(chain, *tbl, tbl);
- IPFW_RUNLOCK(chain);
- if (error)
- break;
- error = sooptcopyout(sopt, op3, sopt->sopt_valsize);
- }
- break;
-
- case IP_FW_TABLE_XLIST: /* IP_FW3 */
- {
- ipfw_xtable *tbl;
-
- if ((size = valsize) < sizeof(ipfw_xtable)) {
- error = EINVAL;
- break;
- }
-
- tbl = malloc(size, M_TEMP, M_ZERO | M_WAITOK);
- memcpy(tbl, op3, sizeof(ipfw_xtable));
-
- /* Get maximum number of entries we can store */
- tbl->size = (size - sizeof(ipfw_xtable)) /
- sizeof(ipfw_table_xentry);
- IPFW_RLOCK(chain);
- error = ipfw_dump_xtable(chain, tbl);
- IPFW_RUNLOCK(chain);
- if (error) {
- free(tbl, M_TEMP);
- break;
- }
-
- /* Revert size field back to bytes */
- tbl->size = tbl->size * sizeof(ipfw_table_xentry) +
- sizeof(ipfw_table);
- /*
- * Since we call sooptcopyin() with small buffer, sopt_valsize is
- * decreased to reflect supplied buffer size. Set it back to original value
- */
- sopt->sopt_valsize = valsize;
- error = sooptcopyout(sopt, tbl, size);
- free(tbl, M_TEMP);
- }
- break;
-
/*--- NAT operations are protected by the IPFW_LOCK ---*/
case IP_FW_NAT_CFG:
if (IPFW_NAT_LOADED)
@@ -1330,18 +3058,16 @@ ipfw_ctl(struct sockopt *sopt)
return (error);
#undef RULE_MAXSIZE
}
-
-
#define RULE_MAXSIZE (256*sizeof(u_int32_t))
/* Functions to convert rules 7.2 <==> 8.0 */
-int
-convert_rule_to_7(struct ip_fw *rule)
+static int
+convert_rule_to_7(struct ip_fw_rule0 *rule)
{
/* Used to modify original rule */
struct ip_fw7 *rule7 = (struct ip_fw7 *)rule;
/* copy of original rule, version 8 */
- struct ip_fw *tmp;
+ struct ip_fw_rule0 *tmp;
/* Used to copy commands */
ipfw_insn *ccmd, *dst;
@@ -1354,13 +3080,12 @@ convert_rule_to_7(struct ip_fw *rule)
bcopy(rule, tmp, RULE_MAXSIZE);
/* Copy fields */
- rule7->_pad = tmp->_pad;
+ //rule7->_pad = tmp->_pad;
rule7->set = tmp->set;
rule7->rulenum = tmp->rulenum;
rule7->cmd_len = tmp->cmd_len;
rule7->act_ofs = tmp->act_ofs;
rule7->next_rule = (struct ip_fw7 *)tmp->next_rule;
- rule7->next = (struct ip_fw7 *)tmp->x_next;
rule7->cmd_len = tmp->cmd_len;
rule7->pcnt = tmp->pcnt;
rule7->bcnt = tmp->bcnt;
@@ -1390,8 +3115,8 @@ convert_rule_to_7(struct ip_fw *rule)
return 0;
}
-int
-convert_rule_to_8(struct ip_fw *rule)
+static int
+convert_rule_to_8(struct ip_fw_rule0 *rule)
{
/* Used to modify original rule */
struct ip_fw7 *rule7 = (struct ip_fw7 *) rule;
@@ -1433,7 +3158,6 @@ convert_rule_to_8(struct ip_fw *rule)
rule->cmd_len = tmp->cmd_len;
rule->act_ofs = tmp->act_ofs;
rule->next_rule = (struct ip_fw *)tmp->next_rule;
- rule->x_next = (struct ip_fw *)tmp->next;
rule->cmd_len = tmp->cmd_len;
rule->id = 0; /* XXX see if is ok = 0 */
rule->pcnt = tmp->pcnt;
@@ -1444,4 +3168,325 @@ convert_rule_to_8(struct ip_fw *rule)
return 0;
}
+/*
+ * Named object api
+ *
+ */
+
+/*
+ * Allocate new bitmask which can be used to enlarge/shrink
+ * named instance index.
+ */
+void
+ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks)
+{
+ size_t size;
+ int max_blocks;
+ u_long *idx_mask;
+
+ KASSERT((items % BLOCK_ITEMS) == 0,
+ ("bitmask size needs to power of 2 and greater or equal to %lu",
+ BLOCK_ITEMS));
+
+ max_blocks = items / BLOCK_ITEMS;
+ size = items / 8;
+ idx_mask = malloc(size * IPFW_MAX_SETS, M_IPFW, M_WAITOK);
+ /* Mark all as free */
+ memset(idx_mask, 0xFF, size * IPFW_MAX_SETS);
+ *idx_mask &= ~(u_long)1; /* Skip index 0 */
+
+ *idx = idx_mask;
+ *pblocks = max_blocks;
+}
+
+/*
+ * Copy current bitmask index to new one.
+ */
+void
+ipfw_objhash_bitmap_merge(struct namedobj_instance *ni, void **idx, int *blocks)
+{
+ int old_blocks, new_blocks;
+ u_long *old_idx, *new_idx;
+ int i;
+
+ old_idx = ni->idx_mask;
+ old_blocks = ni->max_blocks;
+ new_idx = *idx;
+ new_blocks = *blocks;
+
+ for (i = 0; i < IPFW_MAX_SETS; i++) {
+ memcpy(&new_idx[new_blocks * i], &old_idx[old_blocks * i],
+ old_blocks * sizeof(u_long));
+ }
+}
+
+/*
+ * Swaps current @ni index with new one.
+ */
+void
+ipfw_objhash_bitmap_swap(struct namedobj_instance *ni, void **idx, int *blocks)
+{
+ int old_blocks;
+ u_long *old_idx;
+
+ old_idx = ni->idx_mask;
+ old_blocks = ni->max_blocks;
+
+ ni->idx_mask = *idx;
+ ni->max_blocks = *blocks;
+
+ /* Save old values */
+ *idx = old_idx;
+ *blocks = old_blocks;
+}
+
+void
+ipfw_objhash_bitmap_free(void *idx, int blocks)
+{
+
+ free(idx, M_IPFW);
+}
+
+/*
+ * Creates named hash instance.
+ * Must be called without holding any locks.
+ * Return pointer to new instance.
+ */
+struct namedobj_instance *
+ipfw_objhash_create(uint32_t items)
+{
+ struct namedobj_instance *ni;
+ int i;
+ size_t size;
+
+ size = sizeof(struct namedobj_instance) +
+ sizeof(struct namedobjects_head) * NAMEDOBJ_HASH_SIZE +
+ sizeof(struct namedobjects_head) * NAMEDOBJ_HASH_SIZE;
+
+ ni = malloc(size, M_IPFW, M_WAITOK | M_ZERO);
+ ni->nn_size = NAMEDOBJ_HASH_SIZE;
+ ni->nv_size = NAMEDOBJ_HASH_SIZE;
+
+ ni->names = (struct namedobjects_head *)(ni +1);
+ ni->values = &ni->names[ni->nn_size];
+
+ for (i = 0; i < ni->nn_size; i++)
+ TAILQ_INIT(&ni->names[i]);
+
+ for (i = 0; i < ni->nv_size; i++)
+ TAILQ_INIT(&ni->values[i]);
+
+ /* Set default hashing/comparison functions */
+ ni->hash_f = objhash_hash_name;
+ ni->cmp_f = objhash_cmp_name;
+
+ /* Allocate bitmask separately due to possible resize */
+ ipfw_objhash_bitmap_alloc(items, (void*)&ni->idx_mask, &ni->max_blocks);
+
+ return (ni);
+}
+
+void
+ipfw_objhash_destroy(struct namedobj_instance *ni)
+{
+
+ free(ni->idx_mask, M_IPFW);
+ free(ni, M_IPFW);
+}
+
+void
+ipfw_objhash_set_funcs(struct namedobj_instance *ni, objhash_hash_f *hash_f,
+ objhash_cmp_f *cmp_f)
+{
+
+ ni->hash_f = hash_f;
+ ni->cmp_f = cmp_f;
+}
+
+static uint32_t
+objhash_hash_name(struct namedobj_instance *ni, void *name, uint32_t set)
+{
+
+ return (fnv_32_str((char *)name, FNV1_32_INIT));
+}
+
+static int
+objhash_cmp_name(struct named_object *no, void *name, uint32_t set)
+{
+
+ if ((strcmp(no->name, (char *)name) == 0) && (no->set == set))
+ return (0);
+
+ return (1);
+}
+
+static uint32_t
+objhash_hash_idx(struct namedobj_instance *ni, uint32_t val)
+{
+ uint32_t v;
+
+ v = val % (ni->nv_size - 1);
+
+ return (v);
+}
+
+struct named_object *
+ipfw_objhash_lookup_name(struct namedobj_instance *ni, uint32_t set, char *name)
+{
+ struct named_object *no;
+ uint32_t hash;
+
+ hash = ni->hash_f(ni, name, set) % ni->nn_size;
+
+ TAILQ_FOREACH(no, &ni->names[hash], nn_next) {
+ if (ni->cmp_f(no, name, set) == 0)
+ return (no);
+ }
+
+ return (NULL);
+}
+
+struct named_object *
+ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, uint16_t kidx)
+{
+ struct named_object *no;
+ uint32_t hash;
+
+ hash = objhash_hash_idx(ni, kidx);
+
+ TAILQ_FOREACH(no, &ni->values[hash], nv_next) {
+ if (no->kidx == kidx)
+ return (no);
+ }
+
+ return (NULL);
+}
+
+int
+ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a,
+ struct named_object *b)
+{
+
+ if ((strcmp(a->name, b->name) == 0) && a->set == b->set)
+ return (1);
+
+ return (0);
+}
+
+void
+ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no)
+{
+ uint32_t hash;
+
+ hash = ni->hash_f(ni, no->name, no->set) % ni->nn_size;
+ TAILQ_INSERT_HEAD(&ni->names[hash], no, nn_next);
+
+ hash = objhash_hash_idx(ni, no->kidx);
+ TAILQ_INSERT_HEAD(&ni->values[hash], no, nv_next);
+
+ ni->count++;
+}
+
+void
+ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no)
+{
+ uint32_t hash;
+
+ hash = ni->hash_f(ni, no->name, no->set) % ni->nn_size;
+ TAILQ_REMOVE(&ni->names[hash], no, nn_next);
+
+ hash = objhash_hash_idx(ni, no->kidx);
+ TAILQ_REMOVE(&ni->values[hash], no, nv_next);
+
+ ni->count--;
+}
+
+uint32_t
+ipfw_objhash_count(struct namedobj_instance *ni)
+{
+
+ return (ni->count);
+}
+
+/*
+ * Runs @func for each found named object.
+ * It is safe to delete objects from callback
+ */
+void
+ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, void *arg)
+{
+ struct named_object *no, *no_tmp;
+ int i;
+
+ for (i = 0; i < ni->nn_size; i++) {
+ TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp)
+ f(ni, no, arg);
+ }
+}
+
+/*
+ * Removes index from given set.
+ * Returns 0 on success.
+ */
+int
+ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx)
+{
+ u_long *mask;
+ int i, v;
+
+ i = idx / BLOCK_ITEMS;
+ v = idx % BLOCK_ITEMS;
+
+ if (i >= ni->max_blocks)
+ return (1);
+
+ mask = &ni->idx_mask[i];
+
+ if ((*mask & ((u_long)1 << v)) != 0)
+ return (1);
+
+ /* Mark as free */
+ *mask |= (u_long)1 << v;
+
+ /* Update free offset */
+ if (ni->free_off[0] > i)
+ ni->free_off[0] = i;
+
+ return (0);
+}
+
+/*
+ * Allocate new index in given instance and stores in in @pidx.
+ * Returns 0 on success.
+ */
+int
+ipfw_objhash_alloc_idx(void *n, uint16_t *pidx)
+{
+ struct namedobj_instance *ni;
+ u_long *mask;
+ int i, off, v;
+
+ ni = (struct namedobj_instance *)n;
+
+ off = ni->free_off[0];
+ mask = &ni->idx_mask[off];
+
+ for (i = off; i < ni->max_blocks; i++, mask++) {
+ if ((v = ffsl(*mask)) == 0)
+ continue;
+
+ /* Mark as busy */
+ *mask &= ~ ((u_long)1 << (v - 1));
+
+ ni->free_off[0] = i;
+
+ v = BLOCK_ITEMS * i + v - 1;
+
+ *pidx = v;
+ return (0);
+ }
+
+ return (1);
+}
+
/* end of file */
diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c
index 760a10c..fa92b0e 100644
--- a/sys/netpfil/ipfw/ip_fw_table.c
+++ b/sys/netpfil/ipfw/ip_fw_table.c
@@ -1,5 +1,7 @@
/*-
* Copyright (c) 2004 Ruslan Ermilov and Vsevolod Lobko.
+ * Copyright (c) 2014 Yandex LLC
+ * Copyright (c) 2014 Alexander V. Chernikov
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,24 +29,18 @@
__FBSDID("$FreeBSD$");
/*
- * Lookup table support for ipfw
+ * Lookup table support for ipfw.
*
- * Lookup tables are implemented (at the moment) using the radix
- * tree used for routing tables. Tables store key-value entries, where
- * keys are network prefixes (addr/masklen), and values are integers.
- * As a degenerate case we can interpret keys as 32-bit integers
- * (with a /32 mask).
+ * This file contains handlers for all generic tables' operations:
+ * add/del/flush entries, list/dump tables etc..
*
- * The table is protected by the IPFW lock even for manipulation coming
- * from userland, because operations are typically fast.
+ * Table data modification is protected by both UH and runtime lock
+ * while reading configuration/data is protected by UH lock.
+ *
+ * Lookup algorithms for all table types are located in ip_fw_table_algo.c
*/
#include "opt_ipfw.h"
-#include "opt_inet.h"
-#ifndef INET
-#error IPFIREWALL requires INET.
-#endif /* INET */
-#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -52,714 +48,3608 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/rwlock.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/queue.h>
#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */
-#include <net/radix.h>
-#include <net/route.h>
-#include <net/vnet.h>
#include <netinet/in.h>
#include <netinet/ip_var.h> /* struct ipfw_rule_ref */
#include <netinet/ip_fw.h>
#include <netpfil/ipfw/ip_fw_private.h>
+#include <netpfil/ipfw/ip_fw_table.h>
-#ifdef MAC
-#include <security/mac/mac_framework.h>
-#endif
+ /*
+ * Table has the following `type` concepts:
+ *
+ * `no.type` represents lookup key type (addr, ifp, uid, etc..)
+ * vmask represents bitmask of table values which are present at the moment.
+ * Special IPFW_VTYPE_LEGACY ( (uint32_t)-1 ) represents old
+ * single-value-for-all approach.
+ */
+struct table_config {
+ struct named_object no;
+ uint8_t tflags; /* type flags */
+ uint8_t locked; /* 1 if locked from changes */
+ uint8_t linked; /* 1 if already linked */
+ uint8_t ochanged; /* used by set swapping */
+ uint8_t vshared; /* 1 if using shared value array */
+ uint8_t spare[3];
+ uint32_t count; /* Number of records */
+ uint32_t limit; /* Max number of records */
+ uint32_t vmask; /* bitmask with supported values */
+ uint32_t ocount; /* used by set swapping */
+ uint64_t gencnt; /* generation count */
+ char tablename[64]; /* table name */
+ struct table_algo *ta; /* Callbacks for given algo */
+ void *astate; /* algorithm state */
+ struct table_info ti_copy; /* data to put to table_info */
+ struct namedobj_instance *vi;
+};
-static MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");
+static struct table_config *find_table(struct namedobj_instance *ni,
+ struct tid_info *ti);
+static struct table_config *alloc_table_config(struct ip_fw_chain *ch,
+ struct tid_info *ti, struct table_algo *ta, char *adata, uint8_t tflags);
+static void free_table_config(struct namedobj_instance *ni,
+ struct table_config *tc);
+static int create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
+ char *aname, ipfw_xtable_info *i, uint16_t *pkidx, int ref);
+static void link_table(struct ip_fw_chain *ch, struct table_config *tc);
+static void unlink_table(struct ip_fw_chain *ch, struct table_config *tc);
+static int find_ref_table(struct ip_fw_chain *ch, struct tid_info *ti,
+ struct tentry_info *tei, uint32_t count, int op, struct table_config **ptc);
+#define OP_ADD 1
+#define OP_DEL 0
+static int export_tables(struct ip_fw_chain *ch, ipfw_obj_lheader *olh,
+ struct sockopt_data *sd);
+static void export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
+ ipfw_xtable_info *i);
+static int dump_table_tentry(void *e, void *arg);
+static int dump_table_xentry(void *e, void *arg);
+
+static int swap_tables(struct ip_fw_chain *ch, struct tid_info *a,
+ struct tid_info *b);
+
+static int check_table_space(struct ip_fw_chain *ch, struct tableop_state *ts,
+ struct table_config *tc, struct table_info *ti, uint32_t count);
+static int destroy_table(struct ip_fw_chain *ch, struct tid_info *ti);
+
+static struct table_algo *find_table_algo(struct tables_config *tableconf,
+ struct tid_info *ti, char *name);
+
+static void objheader_to_ti(struct _ipfw_obj_header *oh, struct tid_info *ti);
+static void ntlv_to_ti(struct _ipfw_obj_ntlv *ntlv, struct tid_info *ti);
+static int classify_table_opcode(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype);
+
+#define CHAIN_TO_NI(chain) (CHAIN_TO_TCFG(chain)->namehash)
+#define KIDX_TO_TI(ch, k) (&(((struct table_info *)(ch)->tablestate)[k]))
+
+#define TA_BUF_SZ 128 /* On-stack buffer for add/delete state */
-struct table_entry {
- struct radix_node rn[2];
- struct sockaddr_in addr, mask;
- u_int32_t value;
-};
+void
+rollback_toperation_state(struct ip_fw_chain *ch, void *object)
+{
+ struct tables_config *tcfg;
+ struct op_state *os;
-struct xaddr_iface {
- uint8_t if_len; /* length of this struct */
- uint8_t pad[7]; /* Align name */
- char ifname[IF_NAMESIZE]; /* Interface name */
-};
+ tcfg = CHAIN_TO_TCFG(ch);
+ TAILQ_FOREACH(os, &tcfg->state_list, next)
+ os->func(object, os);
+}
+
+void
+add_toperation_state(struct ip_fw_chain *ch, struct tableop_state *ts)
+{
+ struct tables_config *tcfg;
+
+ tcfg = CHAIN_TO_TCFG(ch);
+ TAILQ_INSERT_HEAD(&tcfg->state_list, &ts->opstate, next);
+}
+
+void
+del_toperation_state(struct ip_fw_chain *ch, struct tableop_state *ts)
+{
+ struct tables_config *tcfg;
+
+ tcfg = CHAIN_TO_TCFG(ch);
+ TAILQ_REMOVE(&tcfg->state_list, &ts->opstate, next);
+}
+
+void
+tc_ref(struct table_config *tc)
+{
+
+ tc->no.refcnt++;
+}
+
+void
+tc_unref(struct table_config *tc)
+{
+
+ tc->no.refcnt--;
+}
+
+static struct table_value *
+get_table_value(struct ip_fw_chain *ch, struct table_config *tc, uint32_t kidx)
+{
+ struct table_value *pval;
+
+ pval = (struct table_value *)ch->valuestate;
+
+ return (&pval[kidx]);
+}
-struct table_xentry {
- struct radix_node rn[2];
- union {
-#ifdef INET6
- struct sockaddr_in6 addr6;
-#endif
- struct xaddr_iface iface;
- } a;
- union {
-#ifdef INET6
- struct sockaddr_in6 mask6;
-#endif
- struct xaddr_iface ifmask;
- } m;
- u_int32_t value;
-};
/*
- * The radix code expects addr and mask to be array of bytes,
- * with the first byte being the length of the array. rn_inithead
- * is called with the offset in bits of the lookup key within the
- * array. If we use a sockaddr_in as the underlying type,
- * sin_len is conveniently located at offset 0, sin_addr is at
- * offset 4 and normally aligned.
- * But for portability, let's avoid assumption and make the code explicit
+ * Checks if we're able to insert/update entry @tei into table
+ * w.r.t @tc limits.
+ * May alter @tei to indicate insertion error / insert
+ * options.
+ *
+ * Returns 0 if operation can be performed/
*/
-#define KEY_LEN(v) *((uint8_t *)&(v))
-#define KEY_OFS (8*offsetof(struct sockaddr_in, sin_addr))
+static int
+check_table_limit(struct table_config *tc, struct tentry_info *tei)
+{
+
+ if (tc->limit == 0 || tc->count < tc->limit)
+ return (0);
+
+ if ((tei->flags & TEI_FLAGS_UPDATE) == 0) {
+ /* Notify userland on error cause */
+ tei->flags |= TEI_FLAGS_LIMIT;
+ return (EFBIG);
+ }
+
+ /*
+ * We have UPDATE flag set.
+ * Permit updating record (if found),
+ * but restrict adding new one since we've
+ * already hit the limit.
+ */
+ tei->flags |= TEI_FLAGS_DONTADD;
+
+ return (0);
+}
+
/*
- * Do not require radix to compare more than actual IPv4/IPv6 address
+ * Convert algorithm callback return code into
+ * one of pre-defined states known by userland.
*/
-#define KEY_LEN_INET (offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t))
-#define KEY_LEN_INET6 (offsetof(struct sockaddr_in6, sin6_addr) + sizeof(struct in6_addr))
-#define KEY_LEN_IFACE (offsetof(struct xaddr_iface, ifname))
+static void
+store_tei_result(struct tentry_info *tei, int op, int error, uint32_t num)
+{
+ int flag;
-#define OFF_LEN_INET (8 * offsetof(struct sockaddr_in, sin_addr))
-#define OFF_LEN_INET6 (8 * offsetof(struct sockaddr_in6, sin6_addr))
-#define OFF_LEN_IFACE (8 * offsetof(struct xaddr_iface, ifname))
+ flag = 0;
+ switch (error) {
+ case 0:
+ if (op == OP_ADD && num != 0)
+ flag = TEI_FLAGS_ADDED;
+ if (op == OP_DEL)
+ flag = TEI_FLAGS_DELETED;
+ break;
+ case ENOENT:
+ flag = TEI_FLAGS_NOTFOUND;
+ break;
+ case EEXIST:
+ flag = TEI_FLAGS_EXISTS;
+ break;
+ default:
+ flag = TEI_FLAGS_ERROR;
+ }
-#ifdef INET6
-static inline void
-ipv6_writemask(struct in6_addr *addr6, uint8_t mask)
+ tei->flags |= flag;
+}
+
+/*
+ * Creates and references table with default parameters.
+ * Saves table config, algo and allocated kidx info @ptc, @pta and
+ * @pkidx if non-zero.
+ * Used for table auto-creation to support old binaries.
+ *
+ * Returns 0 on success.
+ */
+static int
+create_table_compat(struct ip_fw_chain *ch, struct tid_info *ti,
+ uint16_t *pkidx)
{
- uint32_t *cp;
+ ipfw_xtable_info xi;
+ int error;
+
+ memset(&xi, 0, sizeof(xi));
+ /* Set default value mask for legacy clients */
+ xi.vmask = IPFW_VTYPE_LEGACY;
+
+ error = create_table_internal(ch, ti, NULL, &xi, pkidx, 1);
+ if (error != 0)
+ return (error);
- for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32)
- *cp++ = 0xFFFFFFFF;
- *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
+ return (0);
}
-#endif
+/*
+ * Find and reference existing table optionally
+ * creating new one.
+ *
+ * Saves found table config into @ptc.
+ * Note function may drop/acquire UH_WLOCK.
+ * Returns 0 if table was found/created and referenced
+ * or non-zero return code.
+ */
+static int
+find_ref_table(struct ip_fw_chain *ch, struct tid_info *ti,
+ struct tentry_info *tei, uint32_t count, int op,
+ struct table_config **ptc)
+{
+ struct namedobj_instance *ni;
+ struct table_config *tc;
+ uint16_t kidx;
+ int error;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ ni = CHAIN_TO_NI(ch);
+ tc = NULL;
+ if ((tc = find_table(ni, ti)) != NULL) {
+ /* check table type */
+ if (tc->no.type != ti->type)
+ return (EINVAL);
+
+ if (tc->locked != 0)
+ return (EACCES);
+
+ /* Try to exit early on limit hit */
+ if (op == OP_ADD && count == 1 &&
+ check_table_limit(tc, tei) != 0)
+ return (EFBIG);
+
+ /* Reference and return */
+ tc->no.refcnt++;
+ *ptc = tc;
+ return (0);
+ }
+
+ if (op == OP_DEL)
+ return (ESRCH);
+
+ /* Compability mode: create new table for old clients */
+ if ((tei->flags & TEI_FLAGS_COMPAT) == 0)
+ return (ESRCH);
+
+ IPFW_UH_WUNLOCK(ch);
+ error = create_table_compat(ch, ti, &kidx);
+ IPFW_UH_WLOCK(ch);
+
+ if (error != 0)
+ return (error);
+
+ tc = (struct table_config *)ipfw_objhash_lookup_kidx(ni, kidx);
+ KASSERT(tc != NULL, ("create_table_compat returned bad idx %d", kidx));
+
+ /* OK, now we've got referenced table. */
+ *ptc = tc;
+ return (0);
+}
+
+/*
+ * Rolls back already @added to @tc entries using state array @ta_buf_m.
+ * Assume the following layout:
+ * 1) ADD state (ta_buf_m[0] ... t_buf_m[added - 1]) for handling update cases
+ * 2) DEL state (ta_buf_m[count[ ... t_buf_m[count + added - 1])
+ * for storing deleted state
+ */
+static void
+rollback_added_entries(struct ip_fw_chain *ch, struct table_config *tc,
+ struct table_info *tinfo, struct tentry_info *tei, caddr_t ta_buf_m,
+ uint32_t count, uint32_t added)
+{
+ struct table_algo *ta;
+ struct tentry_info *ptei;
+ caddr_t v, vv;
+ size_t ta_buf_sz;
+ int error, i;
+ uint32_t num;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ ta = tc->ta;
+ ta_buf_sz = ta->ta_buf_size;
+ v = ta_buf_m;
+ vv = v + count * ta_buf_sz;
+ for (i = 0; i < added; i++, v += ta_buf_sz, vv += ta_buf_sz) {
+ ptei = &tei[i];
+ if ((ptei->flags & TEI_FLAGS_UPDATED) != 0) {
+
+ /*
+ * We have old value stored by previous
+ * call in @ptei->value. Do add once again
+ * to restore it.
+ */
+ error = ta->add(tc->astate, tinfo, ptei, v, &num);
+ KASSERT(error == 0, ("rollback UPDATE fail"));
+ KASSERT(num == 0, ("rollback UPDATE fail2"));
+ continue;
+ }
+
+ error = ta->prepare_del(ch, ptei, vv);
+ KASSERT(error == 0, ("pre-rollback INSERT failed"));
+ error = ta->del(tc->astate, tinfo, ptei, vv, &num);
+ KASSERT(error == 0, ("rollback INSERT failed"));
+ tc->count -= num;
+ }
+}
+
+/*
+ * Prepares add/del state for all @count entries in @tei.
+ * Uses either stack buffer (@ta_buf) or allocates a new one.
+ * Stores pointer to allocated buffer back to @ta_buf.
+ *
+ * Returns 0 on success.
+ */
+static int
+prepare_batch_buffer(struct ip_fw_chain *ch, struct table_algo *ta,
+ struct tentry_info *tei, uint32_t count, int op, caddr_t *ta_buf)
+{
+ caddr_t ta_buf_m, v;
+ size_t ta_buf_sz, sz;
+ struct tentry_info *ptei;
+ int error, i;
+
+ error = 0;
+ ta_buf_sz = ta->ta_buf_size;
+ if (count == 1) {
+ /* Sigle add/delete, use on-stack buffer */
+ memset(*ta_buf, 0, TA_BUF_SZ);
+ ta_buf_m = *ta_buf;
+ } else {
+
+ /*
+ * Multiple adds/deletes, allocate larger buffer
+ *
+ * Note we need 2xcount buffer for add case:
+ * we have hold both ADD state
+ * and DELETE state (this may be needed
+ * if we need to rollback all changes)
+ */
+ sz = count * ta_buf_sz;
+ ta_buf_m = malloc((op == OP_ADD) ? sz * 2 : sz, M_TEMP,
+ M_WAITOK | M_ZERO);
+ }
+
+ v = ta_buf_m;
+ for (i = 0; i < count; i++, v += ta_buf_sz) {
+ ptei = &tei[i];
+ error = (op == OP_ADD) ?
+ ta->prepare_add(ch, ptei, v) : ta->prepare_del(ch, ptei, v);
+
+ /*
+ * Some syntax error (incorrect mask, or address, or
+ * anything). Return error regardless of atomicity
+ * settings.
+ */
+ if (error != 0)
+ break;
+ }
+
+ *ta_buf = ta_buf_m;
+ return (error);
+}
+
+/*
+ * Flushes allocated state for each @count entries in @tei.
+ * Frees @ta_buf_m if differs from stack buffer @ta_buf.
+ */
+static void
+flush_batch_buffer(struct ip_fw_chain *ch, struct table_algo *ta,
+ struct tentry_info *tei, uint32_t count, int rollback,
+ caddr_t ta_buf_m, caddr_t ta_buf)
+{
+ caddr_t v;
+ struct tentry_info *ptei;
+ size_t ta_buf_sz;
+ int i;
+
+ ta_buf_sz = ta->ta_buf_size;
+
+ /* Run cleaning callback anyway */
+ v = ta_buf_m;
+ for (i = 0; i < count; i++, v += ta_buf_sz) {
+ ptei = &tei[i];
+ ta->flush_entry(ch, ptei, v);
+ if (ptei->ptv != NULL) {
+ free(ptei->ptv, M_IPFW);
+ ptei->ptv = NULL;
+ }
+ }
+
+ /* Clean up "deleted" state in case of rollback */
+ if (rollback != 0) {
+ v = ta_buf_m + count * ta_buf_sz;
+ for (i = 0; i < count; i++, v += ta_buf_sz)
+ ta->flush_entry(ch, &tei[i], v);
+ }
+
+ if (ta_buf_m != ta_buf)
+ free(ta_buf_m, M_TEMP);
+}
+
+
+static void
+rollback_add_entry(void *object, struct op_state *_state)
+{
+ struct ip_fw_chain *ch;
+ struct tableop_state *ts;
+
+ ts = (struct tableop_state *)_state;
+
+ if (ts->tc != object && ts->ch != object)
+ return;
+
+ ch = ts->ch;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ /* Call specifid unlockers */
+ rollback_table_values(ts);
+
+ /* Indicate we've called */
+ ts->modified = 1;
+}
+
+/*
+ * Adds/updates one or more entries in table @ti.
+ *
+ * Function may drop/reacquire UH wlock multiple times due to
+ * items alloc, algorithm callbacks (check_space), value linkage
+ * (new values, value storage realloc), etc..
+ * Other processes like other adds (which may involve storage resize),
+ * table swaps (which changes table data and may change algo type),
+ * table modify (which may change value mask) may be executed
+ * simultaneously so we need to deal with it.
+ *
+ * The following approach was implemented:
+ * we have per-chain linked list, protected with UH lock.
+ * add_table_entry prepares special on-stack structure wthich is passed
+ * to its descendants. Users add this structure to this list before unlock.
+ * After performing needed operations and acquiring UH lock back, each user
+ * checks if structure has changed. If true, it rolls local state back and
+ * returns without error to the caller.
+ * add_table_entry() on its own checks if structure has changed and restarts
+ * its operation from the beginning (goto restart).
+ *
+ * Functions which are modifying fields of interest (currently
+ * resize_shared_value_storage() and swap_tables() )
+ * traverses given list while holding UH lock immediately before
+ * performing their operations calling function provided be list entry
+ * ( currently rollback_add_entry ) which performs rollback for all necessary
+ * state and sets appropriate values in structure indicating rollback
+ * has happened.
+ *
+ * Algo interaction:
+ * Function references @ti first to ensure table won't
+ * disappear or change its type.
+ * After that, prepare_add callback is called for each @tei entry.
+ * Next, we try to add each entry under UH+WHLOCK
+ * using add() callback.
+ * Finally, we free all state by calling flush_entry callback
+ * for each @tei.
+ *
+ * Returns 0 on success.
+ */
int
-ipfw_add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
- uint8_t plen, uint8_t mlen, uint8_t type, uint32_t value)
-{
- struct radix_node_head *rnh, **rnh_ptr;
- struct table_entry *ent;
- struct table_xentry *xent;
- struct radix_node *rn;
- in_addr_t addr;
- int offset;
- void *ent_ptr;
- struct sockaddr *addr_ptr, *mask_ptr;
- char c;
-
- if (tbl >= V_fw_tables_max)
- return (EINVAL);
+add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
+ struct tentry_info *tei, uint8_t flags, uint32_t count)
+{
+ struct table_config *tc;
+ struct table_algo *ta;
+ uint16_t kidx;
+ int error, first_error, i, rollback;
+ uint32_t num, numadd;
+ struct tentry_info *ptei;
+ struct tableop_state ts;
+ char ta_buf[TA_BUF_SZ];
+ caddr_t ta_buf_m, v;
+
+ memset(&ts, 0, sizeof(ts));
+ ta = NULL;
+ IPFW_UH_WLOCK(ch);
- switch (type) {
- case IPFW_TABLE_CIDR:
- if (plen == sizeof(in_addr_t)) {
-#ifdef INET
- /* IPv4 case */
- if (mlen > 32)
- return (EINVAL);
- ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
- ent->value = value;
- /* Set 'total' structure length */
- KEY_LEN(ent->addr) = KEY_LEN_INET;
- KEY_LEN(ent->mask) = KEY_LEN_INET;
- /* Set offset of IPv4 address in bits */
- offset = OFF_LEN_INET;
- ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
- addr = *((in_addr_t *)paddr);
- ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
- /* Set pointers */
- rnh_ptr = &ch->tables[tbl];
- ent_ptr = ent;
- addr_ptr = (struct sockaddr *)&ent->addr;
- mask_ptr = (struct sockaddr *)&ent->mask;
-#endif
-#ifdef INET6
- } else if (plen == sizeof(struct in6_addr)) {
- /* IPv6 case */
- if (mlen > 128)
- return (EINVAL);
- xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
- xent->value = value;
- /* Set 'total' structure length */
- KEY_LEN(xent->a.addr6) = KEY_LEN_INET6;
- KEY_LEN(xent->m.mask6) = KEY_LEN_INET6;
- /* Set offset of IPv6 address in bits */
- offset = OFF_LEN_INET6;
- ipv6_writemask(&xent->m.mask6.sin6_addr, mlen);
- memcpy(&xent->a.addr6.sin6_addr, paddr, sizeof(struct in6_addr));
- APPLY_MASK(&xent->a.addr6.sin6_addr, &xent->m.mask6.sin6_addr);
- /* Set pointers */
- rnh_ptr = &ch->xtables[tbl];
- ent_ptr = xent;
- addr_ptr = (struct sockaddr *)&xent->a.addr6;
- mask_ptr = (struct sockaddr *)&xent->m.mask6;
-#endif
- } else {
- /* Unknown CIDR type */
- return (EINVAL);
+ /*
+ * Find and reference existing table.
+ */
+restart:
+ if (ts.modified != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ flush_batch_buffer(ch, ta, tei, count, rollback,
+ ta_buf_m, ta_buf);
+ memset(&ts, 0, sizeof(ts));
+ ta = NULL;
+ IPFW_UH_WLOCK(ch);
+ }
+
+ error = find_ref_table(ch, ti, tei, count, OP_ADD, &tc);
+ if (error != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (error);
+ }
+ ta = tc->ta;
+
+ /* Fill in tablestate */
+ ts.ch = ch;
+ ts.opstate.func = rollback_add_entry;
+ ts.tc = tc;
+ ts.vshared = tc->vshared;
+ ts.vmask = tc->vmask;
+ ts.ta = ta;
+ ts.tei = tei;
+ ts.count = count;
+ rollback = 0;
+ add_toperation_state(ch, &ts);
+ IPFW_UH_WUNLOCK(ch);
+
+ /* Allocate memory and prepare record(s) */
+ /* Pass stack buffer by default */
+ ta_buf_m = ta_buf;
+ error = prepare_batch_buffer(ch, ta, tei, count, OP_ADD, &ta_buf_m);
+ if (error != 0)
+ goto cleanup;
+
+ IPFW_UH_WLOCK(ch);
+ /* Drop reference we've used in first search */
+ tc->no.refcnt--;
+
+ /*
+ * Check if table swap has happened.
+ * (so table algo might be changed).
+ * Restart operation to achieve consistent behavior.
+ */
+ del_toperation_state(ch, &ts);
+ if (ts.modified != 0)
+ goto restart;
+
+ /*
+ * Link all values values to shared/per-table value array.
+ *
+ * May release/reacquire UH_WLOCK.
+ */
+ error = ipfw_link_table_values(ch, &ts);
+ if (error != 0)
+ goto cleanup;
+ if (ts.modified != 0)
+ goto restart;
+
+ /*
+ * Ensure we are able to add all entries without additional
+ * memory allocations. May release/reacquire UH_WLOCK.
+ */
+ kidx = tc->no.kidx;
+ error = check_table_space(ch, &ts, tc, KIDX_TO_TI(ch, kidx), count);
+ if (error != 0)
+ goto cleanup;
+ if (ts.modified != 0)
+ goto restart;
+
+ /* We've got valid table in @tc. Let's try to add data */
+ kidx = tc->no.kidx;
+ ta = tc->ta;
+ numadd = 0;
+ first_error = 0;
+
+ IPFW_WLOCK(ch);
+
+ v = ta_buf_m;
+ for (i = 0; i < count; i++, v += ta->ta_buf_size) {
+ ptei = &tei[i];
+ num = 0;
+ /* check limit before adding */
+ if ((error = check_table_limit(tc, ptei)) == 0) {
+ error = ta->add(tc->astate, KIDX_TO_TI(ch, kidx),
+ ptei, v, &num);
+ /* Set status flag to inform userland */
+ store_tei_result(ptei, OP_ADD, error, num);
+ }
+ if (error == 0) {
+ /* Update number of records to ease limit checking */
+ tc->count += num;
+ numadd += num;
+ continue;
}
+
+ if (first_error == 0)
+ first_error = error;
+
+ /*
+ * Some error have happened. Check our atomicity
+ * settings: continue if atomicity is not required,
+ * rollback changes otherwise.
+ */
+ if ((flags & IPFW_CTF_ATOMIC) == 0)
+ continue;
+
+ rollback_added_entries(ch, tc, KIDX_TO_TI(ch, kidx),
+ tei, ta_buf_m, count, i);
+
+ rollback = 1;
break;
+ }
+
+ IPFW_WUNLOCK(ch);
+
+ ipfw_garbage_table_values(ch, tc, tei, count, rollback);
+
+ /* Permit post-add algorithm grow/rehash. */
+ if (numadd != 0)
+ check_table_space(ch, NULL, tc, KIDX_TO_TI(ch, kidx), 0);
+
+ /* Return first error to user, if any */
+ error = first_error;
+
+cleanup:
+ IPFW_UH_WUNLOCK(ch);
+
+ flush_batch_buffer(ch, ta, tei, count, rollback, ta_buf_m, ta_buf);
- case IPFW_TABLE_INTERFACE:
- /* Check if string is terminated */
- c = ((char *)paddr)[IF_NAMESIZE - 1];
- ((char *)paddr)[IF_NAMESIZE - 1] = '\0';
- if (((mlen = strlen((char *)paddr)) == IF_NAMESIZE - 1) && (c != '\0'))
- return (EINVAL);
+ return (error);
+}
- /* Include last \0 into comparison */
- mlen++;
-
- xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
- xent->value = value;
- /* Set 'total' structure length */
- KEY_LEN(xent->a.iface) = KEY_LEN_IFACE + mlen;
- KEY_LEN(xent->m.ifmask) = KEY_LEN_IFACE + mlen;
- /* Set offset of interface name in bits */
- offset = OFF_LEN_IFACE;
- memcpy(xent->a.iface.ifname, paddr, mlen);
- /* Assume direct match */
- /* TODO: Add interface pattern matching */
-#if 0
- memset(xent->m.ifmask.ifname, 0xFF, IF_NAMESIZE);
- mask_ptr = (struct sockaddr *)&xent->m.ifmask;
-#endif
- /* Set pointers */
- rnh_ptr = &ch->xtables[tbl];
- ent_ptr = xent;
- addr_ptr = (struct sockaddr *)&xent->a.iface;
- mask_ptr = NULL;
- break;
+/*
+ * Deletes one or more entries in table @ti.
+ *
+ * Returns 0 on success.
+ */
+int
+del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
+ struct tentry_info *tei, uint8_t flags, uint32_t count)
+{
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct tentry_info *ptei;
+ uint16_t kidx;
+ int error, first_error, i;
+ uint32_t num, numdel;
+ char ta_buf[TA_BUF_SZ];
+ caddr_t ta_buf_m, v;
- default:
- return (EINVAL);
+ /*
+ * Find and reference existing table.
+ */
+ IPFW_UH_WLOCK(ch);
+ error = find_ref_table(ch, ti, tei, count, OP_DEL, &tc);
+ if (error != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (error);
}
+ ta = tc->ta;
+ IPFW_UH_WUNLOCK(ch);
+
+ /* Allocate memory and prepare record(s) */
+ /* Pass stack buffer by default */
+ ta_buf_m = ta_buf;
+ error = prepare_batch_buffer(ch, ta, tei, count, OP_DEL, &ta_buf_m);
+ if (error != 0)
+ goto cleanup;
+
+ IPFW_UH_WLOCK(ch);
+
+ /* Drop reference we've used in first search */
+ tc->no.refcnt--;
+
+ /*
+ * Check if table algo is still the same.
+ * (changed ta may be the result of table swap).
+ */
+ if (ta != tc->ta) {
+ IPFW_UH_WUNLOCK(ch);
+ error = EINVAL;
+ goto cleanup;
+ }
+
+ kidx = tc->no.kidx;
+ numdel = 0;
+ first_error = 0;
IPFW_WLOCK(ch);
+ v = ta_buf_m;
+ for (i = 0; i < count; i++, v += ta->ta_buf_size) {
+ ptei = &tei[i];
+ num = 0;
+ error = ta->del(tc->astate, KIDX_TO_TI(ch, kidx), ptei, v,
+ &num);
+ /* Save state for userland */
+ store_tei_result(ptei, OP_DEL, error, num);
+ if (error != 0 && first_error == 0)
+ first_error = error;
+ tc->count -= num;
+ numdel += num;
+ }
+ IPFW_WUNLOCK(ch);
- /* Check if tabletype is valid */
- if ((ch->tabletype[tbl] != 0) && (ch->tabletype[tbl] != type)) {
- IPFW_WUNLOCK(ch);
- free(ent_ptr, M_IPFW_TBL);
- return (EINVAL);
+ /* Unlink non-used values */
+ ipfw_garbage_table_values(ch, tc, tei, count, 0);
+
+ if (numdel != 0) {
+ /* Run post-del hook to permit shrinking */
+ check_table_space(ch, NULL, tc, KIDX_TO_TI(ch, kidx), 0);
}
- /* Check if radix tree exists */
- if ((rnh = *rnh_ptr) == NULL) {
- IPFW_WUNLOCK(ch);
- /* Create radix for a new table */
- if (!rn_inithead((void **)&rnh, offset)) {
- free(ent_ptr, M_IPFW_TBL);
- return (ENOMEM);
+ IPFW_UH_WUNLOCK(ch);
+
+ /* Return first error to user, if any */
+ error = first_error;
+
+cleanup:
+ flush_batch_buffer(ch, ta, tei, count, 0, ta_buf_m, ta_buf);
+
+ return (error);
+}
+
+/*
+ * Ensure that table @tc has enough space to add @count entries without
+ * need for reallocation.
+ *
+ * Callbacks order:
+ * 0) need_modify() (UH_WLOCK) - checks if @count items can be added w/o resize.
+ *
+ * 1) alloc_modify (no locks, M_WAITOK) - alloc new state based on @pflags.
+ * 2) prepare_modifyt (UH_WLOCK) - copy old data into new storage
+ * 3) modify (UH_WLOCK + WLOCK) - switch pointers
+ * 4) flush_modify (UH_WLOCK) - free state, if needed
+ *
+ * Returns 0 on success.
+ */
+static int
+check_table_space(struct ip_fw_chain *ch, struct tableop_state *ts,
+ struct table_config *tc, struct table_info *ti, uint32_t count)
+{
+ struct table_algo *ta;
+ uint64_t pflags;
+ char ta_buf[TA_BUF_SZ];
+ int error;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ error = 0;
+ ta = tc->ta;
+ if (ta->need_modify == NULL)
+ return (0);
+
+ /* Acquire reference not to loose @tc between locks/unlocks */
+ tc->no.refcnt++;
+
+ /*
+ * TODO: think about avoiding race between large add/large delete
+ * operation on algorithm which implements shrinking along with
+ * growing.
+ */
+ while (true) {
+ pflags = 0;
+ if (ta->need_modify(tc->astate, ti, count, &pflags) == 0) {
+ error = 0;
+ break;
}
- IPFW_WLOCK(ch);
- if (*rnh_ptr != NULL) {
- /* Tree is already attached by other thread */
- rn_detachhead((void **)&rnh);
- rnh = *rnh_ptr;
- /* Check table type another time */
- if (ch->tabletype[tbl] != type) {
- IPFW_WUNLOCK(ch);
- free(ent_ptr, M_IPFW_TBL);
- return (EINVAL);
- }
- } else {
- *rnh_ptr = rnh;
- /*
- * Set table type. It can be set already
- * (if we have IPv6-only table) but setting
- * it another time does not hurt
+ /* We have to shrink/grow table */
+ if (ts != NULL)
+ add_toperation_state(ch, ts);
+ IPFW_UH_WUNLOCK(ch);
+
+ memset(&ta_buf, 0, sizeof(ta_buf));
+ error = ta->prepare_mod(ta_buf, &pflags);
+
+ IPFW_UH_WLOCK(ch);
+ if (ts != NULL)
+ del_toperation_state(ch, ts);
+
+ if (error != 0)
+ break;
+
+ if (ts != NULL && ts->modified != 0) {
+
+ /*
+ * Swap operation has happened
+ * so we're currently operating on other
+ * table data. Stop doing this.
+ */
+ ta->flush_mod(ta_buf);
+ break;
+ }
+
+ /* Check if we still need to alter table */
+ ti = KIDX_TO_TI(ch, tc->no.kidx);
+ if (ta->need_modify(tc->astate, ti, count, &pflags) == 0) {
+ IPFW_UH_WUNLOCK(ch);
+
+ /*
+ * Other thread has already performed resize.
+ * Flush our state and return.
*/
- ch->tabletype[tbl] = type;
+ ta->flush_mod(ta_buf);
+ break;
}
+
+ error = ta->fill_mod(tc->astate, ti, ta_buf, &pflags);
+ if (error == 0) {
+ /* Do actual modification */
+ IPFW_WLOCK(ch);
+ ta->modify(tc->astate, ti, ta_buf, pflags);
+ IPFW_WUNLOCK(ch);
+ }
+
+ /* Anyway, flush data and retry */
+ ta->flush_mod(ta_buf);
}
- rn = rnh->rnh_addaddr(addr_ptr, mask_ptr, rnh, ent_ptr);
- IPFW_WUNLOCK(ch);
+ tc->no.refcnt--;
+ return (error);
+}
- if (rn == NULL) {
- free(ent_ptr, M_IPFW_TBL);
- return (EEXIST);
+/*
+ * Adds or deletes record in table.
+ * Data layout (v0):
+ * Request: [ ip_fw3_opheader ipfw_table_xentry ]
+ *
+ * Returns 0 on success
+ */
+static int
+manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_table_xentry *xent;
+ struct tentry_info tei;
+ struct tid_info ti;
+ struct table_value v;
+ int error, hdrlen, read;
+
+ hdrlen = offsetof(ipfw_table_xentry, k);
+
+ /* Check minimum header size */
+ if (sd->valsize < (sizeof(*op3) + hdrlen))
+ return (EINVAL);
+
+ read = sizeof(ip_fw3_opheader);
+
+ /* Check if xentry len field is valid */
+ xent = (ipfw_table_xentry *)(op3 + 1);
+ if (xent->len < hdrlen || xent->len + read > sd->valsize)
+ return (EINVAL);
+
+ memset(&tei, 0, sizeof(tei));
+ tei.paddr = &xent->k;
+ tei.masklen = xent->masklen;
+ ipfw_import_table_value_legacy(xent->value, &v);
+ tei.pvalue = &v;
+ /* Old requests compability */
+ tei.flags = TEI_FLAGS_COMPAT;
+ if (xent->type == IPFW_TABLE_ADDR) {
+ if (xent->len - hdrlen == sizeof(in_addr_t))
+ tei.subtype = AF_INET;
+ else
+ tei.subtype = AF_INET6;
}
- return (0);
+
+ memset(&ti, 0, sizeof(ti));
+ ti.uidx = xent->tbl;
+ ti.type = xent->type;
+
+ error = (op3->opcode == IP_FW_TABLE_XADD) ?
+ add_table_entry(ch, &ti, &tei, 0, 1) :
+ del_table_entry(ch, &ti, &tei, 0, 1);
+
+ return (error);
}
-int
-ipfw_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
- uint8_t plen, uint8_t mlen, uint8_t type)
+/*
+ * Adds or deletes record in table.
+ * Data layout (v1)(current):
+ * Request: [ ipfw_obj_header
+ * ipfw_obj_ctlv(IPFW_TLV_TBLENT_LIST) [ ipfw_obj_tentry x N ]
+ * ]
+ *
+ * Returns 0 on success
+ */
+static int
+manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
{
- struct radix_node_head *rnh, **rnh_ptr;
- struct table_entry *ent;
- in_addr_t addr;
- struct sockaddr_in sa, mask;
- struct sockaddr *sa_ptr, *mask_ptr;
- char c;
+ ipfw_obj_tentry *tent, *ptent;
+ ipfw_obj_ctlv *ctlv;
+ ipfw_obj_header *oh;
+ struct tentry_info *ptei, tei, *tei_buf;
+ struct tid_info ti;
+ int error, i, kidx, read;
+
+ /* Check minimum header size */
+ if (sd->valsize < (sizeof(*oh) + sizeof(*ctlv)))
+ return (EINVAL);
- if (tbl >= V_fw_tables_max)
+ /* Check if passed data is too long */
+ if (sd->valsize != sd->kavail)
return (EINVAL);
- switch (type) {
- case IPFW_TABLE_CIDR:
- if (plen == sizeof(in_addr_t)) {
- /* Set 'total' structure length */
- KEY_LEN(sa) = KEY_LEN_INET;
- KEY_LEN(mask) = KEY_LEN_INET;
- mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
- addr = *((in_addr_t *)paddr);
- sa.sin_addr.s_addr = addr & mask.sin_addr.s_addr;
- rnh_ptr = &ch->tables[tbl];
- sa_ptr = (struct sockaddr *)&sa;
- mask_ptr = (struct sockaddr *)&mask;
-#ifdef INET6
- } else if (plen == sizeof(struct in6_addr)) {
- /* IPv6 case */
- if (mlen > 128)
- return (EINVAL);
- struct sockaddr_in6 sa6, mask6;
- memset(&sa6, 0, sizeof(struct sockaddr_in6));
- memset(&mask6, 0, sizeof(struct sockaddr_in6));
- /* Set 'total' structure length */
- KEY_LEN(sa6) = KEY_LEN_INET6;
- KEY_LEN(mask6) = KEY_LEN_INET6;
- ipv6_writemask(&mask6.sin6_addr, mlen);
- memcpy(&sa6.sin6_addr, paddr, sizeof(struct in6_addr));
- APPLY_MASK(&sa6.sin6_addr, &mask6.sin6_addr);
- rnh_ptr = &ch->xtables[tbl];
- sa_ptr = (struct sockaddr *)&sa6;
- mask_ptr = (struct sockaddr *)&mask6;
-#endif
- } else {
- /* Unknown CIDR type */
- return (EINVAL);
- }
- break;
+ oh = (ipfw_obj_header *)sd->kbuf;
- case IPFW_TABLE_INTERFACE:
- /* Check if string is terminated */
- c = ((char *)paddr)[IF_NAMESIZE - 1];
- ((char *)paddr)[IF_NAMESIZE - 1] = '\0';
- if (((mlen = strlen((char *)paddr)) == IF_NAMESIZE - 1) && (c != '\0'))
- return (EINVAL);
+ /* Basic length checks for TLVs */
+ if (oh->ntlv.head.length != sizeof(oh->ntlv))
+ return (EINVAL);
- struct xaddr_iface ifname, ifmask;
- memset(&ifname, 0, sizeof(ifname));
-
- /* Include last \0 into comparison */
- mlen++;
-
- /* Set 'total' structure length */
- KEY_LEN(ifname) = KEY_LEN_IFACE + mlen;
- KEY_LEN(ifmask) = KEY_LEN_IFACE + mlen;
- /* Assume direct match */
- /* FIXME: Add interface pattern matching */
-#if 0
- memset(ifmask.ifname, 0xFF, IF_NAMESIZE);
- mask_ptr = (struct sockaddr *)&ifmask;
-#endif
- mask_ptr = NULL;
- memcpy(ifname.ifname, paddr, mlen);
- /* Set pointers */
- rnh_ptr = &ch->xtables[tbl];
- sa_ptr = (struct sockaddr *)&ifname;
+ read = sizeof(*oh);
- break;
+ ctlv = (ipfw_obj_ctlv *)(oh + 1);
+ if (ctlv->head.length + read != sd->valsize)
+ return (EINVAL);
- default:
+ read += sizeof(*ctlv);
+ tent = (ipfw_obj_tentry *)(ctlv + 1);
+ if (ctlv->count * sizeof(*tent) + read != sd->valsize)
return (EINVAL);
+
+ if (ctlv->count == 0)
+ return (0);
+
+ /*
+ * Mark entire buffer as "read".
+ * This instructs sopt api write it back
+ * after function return.
+ */
+ ipfw_get_sopt_header(sd, sd->valsize);
+
+ /* Perform basic checks for each entry */
+ ptent = tent;
+ kidx = tent->idx;
+ for (i = 0; i < ctlv->count; i++, ptent++) {
+ if (ptent->head.length != sizeof(*ptent))
+ return (EINVAL);
+ if (ptent->idx != kidx)
+ return (ENOTSUP);
}
- IPFW_WLOCK(ch);
- if ((rnh = *rnh_ptr) == NULL) {
- IPFW_WUNLOCK(ch);
+ /* Convert data into kernel request objects */
+ objheader_to_ti(oh, &ti);
+ ti.type = oh->ntlv.type;
+ ti.uidx = kidx;
+
+ /* Use on-stack buffer for single add/del */
+ if (ctlv->count == 1) {
+ memset(&tei, 0, sizeof(tei));
+ tei_buf = &tei;
+ } else
+ tei_buf = malloc(ctlv->count * sizeof(tei), M_TEMP,
+ M_WAITOK | M_ZERO);
+
+ ptei = tei_buf;
+ ptent = tent;
+ for (i = 0; i < ctlv->count; i++, ptent++, ptei++) {
+ ptei->paddr = &ptent->k;
+ ptei->subtype = ptent->subtype;
+ ptei->masklen = ptent->masklen;
+ if (ptent->head.flags & IPFW_TF_UPDATE)
+ ptei->flags |= TEI_FLAGS_UPDATE;
+
+ ipfw_import_table_value_v1(&ptent->v.value);
+ ptei->pvalue = (struct table_value *)&ptent->v.value;
+ }
+
+ error = (oh->opheader.opcode == IP_FW_TABLE_XADD) ?
+ add_table_entry(ch, &ti, tei_buf, ctlv->flags, ctlv->count) :
+ del_table_entry(ch, &ti, tei_buf, ctlv->flags, ctlv->count);
+
+ /* Translate result back to userland */
+ ptei = tei_buf;
+ ptent = tent;
+ for (i = 0; i < ctlv->count; i++, ptent++, ptei++) {
+ if (ptei->flags & TEI_FLAGS_ADDED)
+ ptent->result = IPFW_TR_ADDED;
+ else if (ptei->flags & TEI_FLAGS_DELETED)
+ ptent->result = IPFW_TR_DELETED;
+ else if (ptei->flags & TEI_FLAGS_UPDATED)
+ ptent->result = IPFW_TR_UPDATED;
+ else if (ptei->flags & TEI_FLAGS_LIMIT)
+ ptent->result = IPFW_TR_LIMIT;
+ else if (ptei->flags & TEI_FLAGS_ERROR)
+ ptent->result = IPFW_TR_ERROR;
+ else if (ptei->flags & TEI_FLAGS_NOTFOUND)
+ ptent->result = IPFW_TR_NOTFOUND;
+ else if (ptei->flags & TEI_FLAGS_EXISTS)
+ ptent->result = IPFW_TR_EXISTS;
+ ipfw_export_table_value_v1(ptei->pvalue, &ptent->v.value);
+ }
+
+ if (tei_buf != &tei)
+ free(tei_buf, M_TEMP);
+
+ return (error);
+}
+
+/*
+ * Looks up an entry in given table.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_obj_tentry ]
+ * Reply: [ ipfw_obj_header ipfw_obj_tentry ]
+ *
+ * Returns 0 on success
+ */
+static int
+find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_tentry *tent;
+ ipfw_obj_header *oh;
+ struct tid_info ti;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct table_info *kti;
+ struct namedobj_instance *ni;
+ int error;
+ size_t sz;
+
+ /* Check minimum header size */
+ sz = sizeof(*oh) + sizeof(*tent);
+ if (sd->valsize != sz)
+ return (EINVAL);
+
+ oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
+ tent = (ipfw_obj_tentry *)(oh + 1);
+
+ /* Basic length checks for TLVs */
+ if (oh->ntlv.head.length != sizeof(oh->ntlv))
+ return (EINVAL);
+
+ objheader_to_ti(oh, &ti);
+ ti.type = oh->ntlv.type;
+ ti.uidx = tent->idx;
+
+ IPFW_UH_RLOCK(ch);
+ ni = CHAIN_TO_NI(ch);
+
+ /*
+ * Find existing table and check its type .
+ */
+ ta = NULL;
+ if ((tc = find_table(ni, &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
return (ESRCH);
}
- if (ch->tabletype[tbl] != type) {
- IPFW_WUNLOCK(ch);
+ /* check table type */
+ if (tc->no.type != ti.type) {
+ IPFW_UH_RUNLOCK(ch);
return (EINVAL);
}
- ent = (struct table_entry *)rnh->rnh_deladdr(sa_ptr, mask_ptr, rnh);
- IPFW_WUNLOCK(ch);
+ kti = KIDX_TO_TI(ch, tc->no.kidx);
+ ta = tc->ta;
- if (ent == NULL)
- return (ESRCH);
+ if (ta->find_tentry == NULL)
+ return (ENOTSUP);
- free(ent, M_IPFW_TBL);
- return (0);
+ error = ta->find_tentry(tc->astate, kti, tent);
+
+ IPFW_UH_RUNLOCK(ch);
+
+ return (error);
}
+/*
+ * Flushes all entries or destroys given table.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ]
+ *
+ * Returns 0 on success
+ */
static int
-flush_table_entry(struct radix_node *rn, void *arg)
+flush_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
{
- struct radix_node_head * const rnh = arg;
- struct table_entry *ent;
+ int error;
+ struct _ipfw_obj_header *oh;
+ struct tid_info ti;
- ent = (struct table_entry *)
- rnh->rnh_deladdr(rn->rn_key, rn->rn_mask, rnh);
- if (ent != NULL)
- free(ent, M_IPFW_TBL);
- return (0);
+ if (sd->valsize != sizeof(*oh))
+ return (EINVAL);
+
+ oh = (struct _ipfw_obj_header *)op3;
+ objheader_to_ti(oh, &ti);
+
+ if (op3->opcode == IP_FW_TABLE_XDESTROY)
+ error = destroy_table(ch, &ti);
+ else if (op3->opcode == IP_FW_TABLE_XFLUSH)
+ error = flush_table(ch, &ti);
+ else
+ return (ENOTSUP);
+
+ return (error);
}
+static void
+restart_flush(void *object, struct op_state *_state)
+{
+ struct tableop_state *ts;
+
+ ts = (struct tableop_state *)_state;
+
+ if (ts->tc != object)
+ return;
+
+ /* Indicate we've called */
+ ts->modified = 1;
+}
+
+/*
+ * Flushes given table.
+ *
+ * Function create new table instance with the same
+ * parameters, swaps it with old one and
+ * flushes state without holding runtime WLOCK.
+ *
+ * Returns 0 on success.
+ */
int
-ipfw_flush_table(struct ip_fw_chain *ch, uint16_t tbl)
+flush_table(struct ip_fw_chain *ch, struct tid_info *ti)
{
- struct radix_node_head *rnh, *xrnh;
+ struct namedobj_instance *ni;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct table_info ti_old, ti_new, *tablestate;
+ void *astate_old, *astate_new;
+ char algostate[64], *pstate;
+ struct tableop_state ts;
+ int error;
+ uint16_t kidx;
+ uint8_t tflags;
- if (tbl >= V_fw_tables_max)
- return (EINVAL);
+ /*
+ * Stage 1: save table algoritm.
+ * Reference found table to ensure it won't disappear.
+ */
+ IPFW_UH_WLOCK(ch);
+ ni = CHAIN_TO_NI(ch);
+ if ((tc = find_table(ni, ti)) == NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ return (ESRCH);
+ }
+restart:
+ /* Set up swap handler */
+ memset(&ts, 0, sizeof(ts));
+ ts.opstate.func = restart_flush;
+ ts.tc = tc;
+
+ ta = tc->ta;
+ /* Do not flush readonly tables */
+ if ((ta->flags & TA_FLAG_READONLY) != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EACCES);
+ }
+ /* Save startup algo parameters */
+ if (ta->print_config != NULL) {
+ ta->print_config(tc->astate, KIDX_TO_TI(ch, tc->no.kidx),
+ algostate, sizeof(algostate));
+ pstate = algostate;
+ } else
+ pstate = NULL;
+ tflags = tc->tflags;
+ tc->no.refcnt++;
+ add_toperation_state(ch, &ts);
+ IPFW_UH_WUNLOCK(ch);
/*
- * We free both (IPv4 and extended) radix trees and
- * clear table type here to permit table to be reused
- * for different type without module reload
+ * Stage 2: allocate new table instance using same algo.
*/
+ memset(&ti_new, 0, sizeof(struct table_info));
+ error = ta->init(ch, &astate_new, &ti_new, pstate, tflags);
- IPFW_WLOCK(ch);
- /* Set IPv4 table pointer to zero */
- if ((rnh = ch->tables[tbl]) != NULL)
- ch->tables[tbl] = NULL;
- /* Set extended table pointer to zero */
- if ((xrnh = ch->xtables[tbl]) != NULL)
- ch->xtables[tbl] = NULL;
- /* Zero table type */
- ch->tabletype[tbl] = 0;
- IPFW_WUNLOCK(ch);
+ /*
+ * Stage 3: swap old state pointers with newly-allocated ones.
+ * Decrease refcount.
+ */
+ IPFW_UH_WLOCK(ch);
+ tc->no.refcnt--;
+ del_toperation_state(ch, &ts);
- if (rnh != NULL) {
- rnh->rnh_walktree(rnh, flush_table_entry, rnh);
- rn_detachhead((void **)&rnh);
+ if (error != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (error);
}
- if (xrnh != NULL) {
- xrnh->rnh_walktree(xrnh, flush_table_entry, xrnh);
- rn_detachhead((void **)&xrnh);
+ /*
+ * Restart operation if table swap has happened:
+ * even if algo may be the same, algo init parameters
+ * may change. Restart operation instead of doing
+ * complex checks.
+ */
+ if (ts.modified != 0) {
+ ta->destroy(astate_new, &ti_new);
+ goto restart;
}
+ ni = CHAIN_TO_NI(ch);
+ kidx = tc->no.kidx;
+ tablestate = (struct table_info *)ch->tablestate;
+
+ IPFW_WLOCK(ch);
+ ti_old = tablestate[kidx];
+ tablestate[kidx] = ti_new;
+ IPFW_WUNLOCK(ch);
+
+ astate_old = tc->astate;
+ tc->astate = astate_new;
+ tc->ti_copy = ti_new;
+ tc->count = 0;
+
+ /* Notify algo on real @ti address */
+ if (ta->change_ti != NULL)
+ ta->change_ti(tc->astate, &tablestate[kidx]);
+
+ /*
+ * Stage 4: unref values.
+ */
+ ipfw_unref_table_values(ch, tc, ta, astate_old, &ti_old);
+ IPFW_UH_WUNLOCK(ch);
+
+ /*
+ * Stage 5: perform real flush/destroy.
+ */
+ ta->destroy(astate_old, &ti_old);
+
return (0);
}
-void
-ipfw_destroy_tables(struct ip_fw_chain *ch)
+/*
+ * Swaps two tables.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_obj_ntlv ]
+ *
+ * Returns 0 on success
+ */
+static int
+swap_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
{
- uint16_t tbl;
+ int error;
+ struct _ipfw_obj_header *oh;
+ struct tid_info ti_a, ti_b;
- /* Flush all tables */
- for (tbl = 0; tbl < V_fw_tables_max; tbl++)
- ipfw_flush_table(ch, tbl);
+ if (sd->valsize != sizeof(*oh) + sizeof(ipfw_obj_ntlv))
+ return (EINVAL);
- /* Free pointers itself */
- free(ch->tables, M_IPFW);
- free(ch->xtables, M_IPFW);
- free(ch->tabletype, M_IPFW);
+ oh = (struct _ipfw_obj_header *)op3;
+ ntlv_to_ti(&oh->ntlv, &ti_a);
+ ntlv_to_ti((ipfw_obj_ntlv *)(oh + 1), &ti_b);
+
+ error = swap_tables(ch, &ti_a, &ti_b);
+
+ return (error);
}
-int
-ipfw_init_tables(struct ip_fw_chain *ch)
+/*
+ * Swaps two tables of the same type/valtype.
+ *
+ * Checks if tables are compatible and limits
+ * permits swap, than actually perform swap.
+ *
+ * Each table consists of 2 different parts:
+ * config:
+ * @tc (with name, set, kidx) and rule bindings, which is "stable".
+ * number of items
+ * table algo
+ * runtime:
+ * runtime data @ti (ch->tablestate)
+ * runtime cache in @tc
+ * algo-specific data (@tc->astate)
+ *
+ * So we switch:
+ * all runtime data
+ * number of items
+ * table algo
+ *
+ * After that we call @ti change handler for each table.
+ *
+ * Note that referencing @tc won't protect tc->ta from change.
+ * XXX: Do we need to restrict swap between locked tables?
+ * XXX: Do we need to exchange ftype?
+ *
+ * Returns 0 on success.
+ */
+static int
+swap_tables(struct ip_fw_chain *ch, struct tid_info *a,
+ struct tid_info *b)
{
- /* Allocate pointers */
- ch->tables = malloc(V_fw_tables_max * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
- ch->xtables = malloc(V_fw_tables_max * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
- ch->tabletype = malloc(V_fw_tables_max * sizeof(uint8_t), M_IPFW, M_WAITOK | M_ZERO);
+ struct namedobj_instance *ni;
+ struct table_config *tc_a, *tc_b;
+ struct table_algo *ta;
+ struct table_info ti, *tablestate;
+ void *astate;
+ uint32_t count;
+
+ /*
+ * Stage 1: find both tables and ensure they are of
+ * the same type.
+ */
+ IPFW_UH_WLOCK(ch);
+ ni = CHAIN_TO_NI(ch);
+ if ((tc_a = find_table(ni, a)) == NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ return (ESRCH);
+ }
+ if ((tc_b = find_table(ni, b)) == NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ return (ESRCH);
+ }
+
+ /* It is very easy to swap between the same table */
+ if (tc_a == tc_b) {
+ IPFW_UH_WUNLOCK(ch);
+ return (0);
+ }
+
+ /* Check type and value are the same */
+ if (tc_a->no.type != tc_b->no.type || tc_a->tflags != tc_b->tflags) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EINVAL);
+ }
+
+ /* Check limits before swap */
+ if ((tc_a->limit != 0 && tc_b->count > tc_a->limit) ||
+ (tc_b->limit != 0 && tc_a->count > tc_b->limit)) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EFBIG);
+ }
+
+ /* Check if one of the tables is readonly */
+ if (((tc_a->ta->flags | tc_b->ta->flags) & TA_FLAG_READONLY) != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EACCES);
+ }
+
+ /* Notify we're going to swap */
+ rollback_toperation_state(ch, tc_a);
+ rollback_toperation_state(ch, tc_b);
+
+ /* Everything is fine, prepare to swap */
+ tablestate = (struct table_info *)ch->tablestate;
+ ti = tablestate[tc_a->no.kidx];
+ ta = tc_a->ta;
+ astate = tc_a->astate;
+ count = tc_a->count;
+
+ IPFW_WLOCK(ch);
+ /* a <- b */
+ tablestate[tc_a->no.kidx] = tablestate[tc_b->no.kidx];
+ tc_a->ta = tc_b->ta;
+ tc_a->astate = tc_b->astate;
+ tc_a->count = tc_b->count;
+ /* b <- a */
+ tablestate[tc_b->no.kidx] = ti;
+ tc_b->ta = ta;
+ tc_b->astate = astate;
+ tc_b->count = count;
+ IPFW_WUNLOCK(ch);
+
+ /* Ensure tc.ti copies are in sync */
+ tc_a->ti_copy = tablestate[tc_a->no.kidx];
+ tc_b->ti_copy = tablestate[tc_b->no.kidx];
+
+ /* Notify both tables on @ti change */
+ if (tc_a->ta->change_ti != NULL)
+ tc_a->ta->change_ti(tc_a->astate, &tablestate[tc_a->no.kidx]);
+ if (tc_b->ta->change_ti != NULL)
+ tc_b->ta->change_ti(tc_b->astate, &tablestate[tc_b->no.kidx]);
+
+ IPFW_UH_WUNLOCK(ch);
+
+ return (0);
+}
+
+/*
+ * Destroys table specified by @ti.
+ * Data layout (v0)(current):
+ * Request: [ ip_fw3_opheader ]
+ *
+ * Returns 0 on success
+ */
+static int
+destroy_table(struct ip_fw_chain *ch, struct tid_info *ti)
+{
+ struct namedobj_instance *ni;
+ struct table_config *tc;
+
+ IPFW_UH_WLOCK(ch);
+
+ ni = CHAIN_TO_NI(ch);
+ if ((tc = find_table(ni, ti)) == NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ return (ESRCH);
+ }
+
+ /* Do not permit destroying referenced tables */
+ if (tc->no.refcnt > 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EBUSY);
+ }
+
+ IPFW_WLOCK(ch);
+ unlink_table(ch, tc);
+ IPFW_WUNLOCK(ch);
+
+ /* Free obj index */
+ if (ipfw_objhash_free_idx(ni, tc->no.kidx) != 0)
+ printf("Error unlinking kidx %d from table %s\n",
+ tc->no.kidx, tc->tablename);
+
+ /* Unref values used in tables while holding UH lock */
+ ipfw_unref_table_values(ch, tc, tc->ta, tc->astate, &tc->ti_copy);
+ IPFW_UH_WUNLOCK(ch);
+
+ free_table_config(ni, tc);
+
return (0);
}
+/*
+ * Grow tables index.
+ *
+ * Returns 0 on success.
+ */
int
ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables)
{
- struct radix_node_head **tables, **xtables, *rnh;
- struct radix_node_head **tables_old, **xtables_old;
- uint8_t *tabletype, *tabletype_old;
unsigned int ntables_old, tbl;
+ struct namedobj_instance *ni;
+ void *new_idx, *old_tablestate, *tablestate;
+ struct table_info *ti;
+ struct table_config *tc;
+ int i, new_blocks;
/* Check new value for validity */
if (ntables > IPFW_TABLES_MAX)
ntables = IPFW_TABLES_MAX;
/* Allocate new pointers */
- tables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
- xtables = malloc(ntables * sizeof(void *), M_IPFW, M_WAITOK | M_ZERO);
- tabletype = malloc(ntables * sizeof(uint8_t), M_IPFW, M_WAITOK | M_ZERO);
+ tablestate = malloc(ntables * sizeof(struct table_info),
+ M_IPFW, M_WAITOK | M_ZERO);
- IPFW_WLOCK(ch);
+ ipfw_objhash_bitmap_alloc(ntables, (void *)&new_idx, &new_blocks);
+
+ IPFW_UH_WLOCK(ch);
tbl = (ntables >= V_fw_tables_max) ? V_fw_tables_max : ntables;
+ ni = CHAIN_TO_NI(ch);
+
+ /* Temporary restrict decreasing max_tables */
+ if (ntables < V_fw_tables_max) {
+
+ /*
+ * FIXME: Check if we really can shrink
+ */
+ IPFW_UH_WUNLOCK(ch);
+ return (EINVAL);
+ }
+
+ /* Copy table info/indices */
+ memcpy(tablestate, ch->tablestate, sizeof(struct table_info) * tbl);
+ ipfw_objhash_bitmap_merge(ni, &new_idx, &new_blocks);
- /* Copy old table pointers */
- memcpy(tables, ch->tables, sizeof(void *) * tbl);
- memcpy(xtables, ch->xtables, sizeof(void *) * tbl);
- memcpy(tabletype, ch->tabletype, sizeof(uint8_t) * tbl);
+ IPFW_WLOCK(ch);
- /* Change pointers and number of tables */
- tables_old = ch->tables;
- xtables_old = ch->xtables;
- tabletype_old = ch->tabletype;
- ch->tables = tables;
- ch->xtables = xtables;
- ch->tabletype = tabletype;
+ /* Change pointers */
+ old_tablestate = ch->tablestate;
+ ch->tablestate = tablestate;
+ ipfw_objhash_bitmap_swap(ni, &new_idx, &new_blocks);
ntables_old = V_fw_tables_max;
V_fw_tables_max = ntables;
IPFW_WUNLOCK(ch);
- /* Check if we need to destroy radix trees */
- if (ntables < ntables_old) {
- for (tbl = ntables; tbl < ntables_old; tbl++) {
- if ((rnh = tables_old[tbl]) != NULL) {
- rnh->rnh_walktree(rnh, flush_table_entry, rnh);
- rn_detachhead((void **)&rnh);
- }
+ /* Notify all consumers that their @ti pointer has changed */
+ ti = (struct table_info *)ch->tablestate;
+ for (i = 0; i < tbl; i++, ti++) {
+ if (ti->lookup == NULL)
+ continue;
+ tc = (struct table_config *)ipfw_objhash_lookup_kidx(ni, i);
+ if (tc == NULL || tc->ta->change_ti == NULL)
+ continue;
+
+ tc->ta->change_ti(tc->astate, ti);
+ }
+
+ IPFW_UH_WUNLOCK(ch);
+
+ /* Free old pointers */
+ free(old_tablestate, M_IPFW);
+ ipfw_objhash_bitmap_free(new_idx, new_blocks);
- if ((rnh = xtables_old[tbl]) != NULL) {
- rnh->rnh_walktree(rnh, flush_table_entry, rnh);
- rn_detachhead((void **)&rnh);
+ return (0);
+}
+
+/*
+ * Switch between "set 0" and "rule's set" table binding,
+ * Check all ruleset bindings and permits changing
+ * IFF each binding has both rule AND table in default set (set 0).
+ *
+ * Returns 0 on success.
+ */
+int
+ipfw_switch_tables_namespace(struct ip_fw_chain *ch, unsigned int sets)
+{
+ struct namedobj_instance *ni;
+ struct named_object *no;
+ struct ip_fw *rule;
+ ipfw_insn *cmd;
+ int cmdlen, i, l;
+ uint16_t kidx;
+ uint8_t type;
+
+ IPFW_UH_WLOCK(ch);
+
+ if (V_fw_tables_sets == sets) {
+ IPFW_UH_WUNLOCK(ch);
+ return (0);
+ }
+
+ ni = CHAIN_TO_NI(ch);
+
+ /*
+ * Scan all rules and examine tables opcodes.
+ */
+ for (i = 0; i < ch->n_rules; i++) {
+ rule = ch->map[i];
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+
+ no = ipfw_objhash_lookup_kidx(ni, kidx);
+
+ /* Check if both table object and rule has the set 0 */
+ if (no->set != 0 || rule->set != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EBUSY);
}
+
}
}
+ V_fw_tables_sets = sets;
- /* Free old pointers */
- free(tables_old, M_IPFW);
- free(xtables_old, M_IPFW);
- free(tabletype_old, M_IPFW);
+ IPFW_UH_WUNLOCK(ch);
return (0);
}
+/*
+ * Lookup an IP @addr in table @tbl.
+ * Stores found value in @val.
+ *
+ * Returns 1 if @addr was found.
+ */
int
ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
uint32_t *val)
{
- struct radix_node_head *rnh;
- struct table_entry *ent;
- struct sockaddr_in sa;
+ struct table_info *ti;
- if (tbl >= V_fw_tables_max)
- return (0);
- if ((rnh = ch->tables[tbl]) == NULL)
- return (0);
- KEY_LEN(sa) = KEY_LEN_INET;
- sa.sin_addr.s_addr = addr;
- ent = (struct table_entry *)(rnh->rnh_matchaddr(&sa, rnh));
- if (ent != NULL) {
- *val = ent->value;
- return (1);
+ ti = KIDX_TO_TI(ch, tbl);
+
+ return (ti->lookup(ti, &addr, sizeof(in_addr_t), val));
+}
+
+/*
+ * Lookup an arbtrary key @paddr of legth @plen in table @tbl.
+ * Stores found value in @val.
+ *
+ * Returns 1 if key was found.
+ */
+int
+ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
+ void *paddr, uint32_t *val)
+{
+ struct table_info *ti;
+
+ ti = KIDX_TO_TI(ch, tbl);
+
+ return (ti->lookup(ti, paddr, plen, val));
+}
+
+/*
+ * Info/List/dump support for tables.
+ *
+ */
+
+/*
+ * High-level 'get' cmds sysctl handlers
+ */
+
+/*
+ * Lists all tables currently available in kernel.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_xtable_info x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+list_tables(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ struct _ipfw_obj_lheader *olh;
+ int error;
+
+ olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
+ if (olh == NULL)
+ return (EINVAL);
+ if (sd->valsize < olh->size)
+ return (EINVAL);
+
+ IPFW_UH_RLOCK(ch);
+ error = export_tables(ch, olh, sd);
+ IPFW_UH_RUNLOCK(ch);
+
+ return (error);
+}
+
+/*
+ * Store table info to buffer provided by @sd.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_xtable_info(empty)]
+ * Reply: [ ipfw_obj_header ipfw_xtable_info ]
+ *
+ * Returns 0 on success.
+ */
+static int
+describe_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ struct _ipfw_obj_header *oh;
+ struct table_config *tc;
+ struct tid_info ti;
+ size_t sz;
+
+ sz = sizeof(*oh) + sizeof(ipfw_xtable_info);
+ oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
+ if (oh == NULL)
+ return (EINVAL);
+
+ objheader_to_ti(oh, &ti);
+
+ IPFW_UH_RLOCK(ch);
+ if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
+ return (ESRCH);
}
+
+ export_table_info(ch, tc, (ipfw_xtable_info *)(oh + 1));
+ IPFW_UH_RUNLOCK(ch);
+
return (0);
}
-int
-ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, void *paddr,
- uint32_t *val, int type)
+/*
+ * Modifies existing table.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_xtable_info ]
+ *
+ * Returns 0 on success
+ */
+static int
+modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
{
- struct radix_node_head *rnh;
- struct table_xentry *xent;
- struct sockaddr_in6 sa6;
- struct xaddr_iface iface;
+ struct _ipfw_obj_header *oh;
+ ipfw_xtable_info *i;
+ char *tname;
+ struct tid_info ti;
+ struct namedobj_instance *ni;
+ struct table_config *tc;
+
+ if (sd->valsize != sizeof(*oh) + sizeof(ipfw_xtable_info))
+ return (EINVAL);
- if (tbl >= V_fw_tables_max)
- return (0);
- if ((rnh = ch->xtables[tbl]) == NULL)
- return (0);
+ oh = (struct _ipfw_obj_header *)sd->kbuf;
+ i = (ipfw_xtable_info *)(oh + 1);
- switch (type) {
- case IPFW_TABLE_CIDR:
- KEY_LEN(sa6) = KEY_LEN_INET6;
- memcpy(&sa6.sin6_addr, paddr, sizeof(struct in6_addr));
- xent = (struct table_xentry *)(rnh->rnh_matchaddr(&sa6, rnh));
- break;
+ /*
+ * Verify user-supplied strings.
+ * Check for null-terminated/zero-length strings/
+ */
+ tname = oh->ntlv.name;
+ if (ipfw_check_table_name(tname) != 0)
+ return (EINVAL);
- case IPFW_TABLE_INTERFACE:
- KEY_LEN(iface) = KEY_LEN_IFACE +
- strlcpy(iface.ifname, (char *)paddr, IF_NAMESIZE) + 1;
- /* Assume direct match */
- /* FIXME: Add interface pattern matching */
- xent = (struct table_xentry *)(rnh->rnh_matchaddr(&iface, rnh));
- break;
+ objheader_to_ti(oh, &ti);
+ ti.type = i->type;
- default:
- return (0);
+ IPFW_UH_WLOCK(ch);
+ ni = CHAIN_TO_NI(ch);
+ if ((tc = find_table(ni, &ti)) == NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ return (ESRCH);
}
- if (xent != NULL) {
- *val = xent->value;
- return (1);
+ /* Do not support any modifications for readonly tables */
+ if ((tc->ta->flags & TA_FLAG_READONLY) != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EACCES);
}
+
+ if ((i->mflags & IPFW_TMFLAGS_LIMIT) != 0)
+ tc->limit = i->limit;
+ if ((i->mflags & IPFW_TMFLAGS_LOCK) != 0)
+ tc->locked = ((i->flags & IPFW_TGFLAGS_LOCKED) != 0);
+ IPFW_UH_WUNLOCK(ch);
+
return (0);
}
+/*
+ * Creates new table.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_xtable_info ]
+ *
+ * Returns 0 on success
+ */
static int
-count_table_entry(struct radix_node *rn, void *arg)
+create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
{
- u_int32_t * const cnt = arg;
+ struct _ipfw_obj_header *oh;
+ ipfw_xtable_info *i;
+ char *tname, *aname;
+ struct tid_info ti;
+ struct namedobj_instance *ni;
+ struct table_config *tc;
+
+ if (sd->valsize != sizeof(*oh) + sizeof(ipfw_xtable_info))
+ return (EINVAL);
+
+ oh = (struct _ipfw_obj_header *)sd->kbuf;
+ i = (ipfw_xtable_info *)(oh + 1);
+
+ /*
+ * Verify user-supplied strings.
+ * Check for null-terminated/zero-length strings/
+ */
+ tname = oh->ntlv.name;
+ aname = i->algoname;
+ if (ipfw_check_table_name(tname) != 0 ||
+ strnlen(aname, sizeof(i->algoname)) == sizeof(i->algoname))
+ return (EINVAL);
+
+ if (aname[0] == '\0') {
+ /* Use default algorithm */
+ aname = NULL;
+ }
+
+ objheader_to_ti(oh, &ti);
+ ti.type = i->type;
+
+ ni = CHAIN_TO_NI(ch);
+
+ IPFW_UH_RLOCK(ch);
+ if ((tc = find_table(ni, &ti)) != NULL) {
+ IPFW_UH_RUNLOCK(ch);
+ return (EEXIST);
+ }
+ IPFW_UH_RUNLOCK(ch);
+
+ return (create_table_internal(ch, &ti, aname, i, NULL, 0));
+}
+
+/*
+ * Creates new table based on @ti and @aname.
+ *
+ * Relies on table name checking inside find_name_tlv()
+ * Assume @aname to be checked and valid.
+ * Stores allocated table kidx inside @pkidx (if non-NULL).
+ * Reference created table if @compat is non-zero.
+ *
+ * Returns 0 on success.
+ */
+static int
+create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
+ char *aname, ipfw_xtable_info *i, uint16_t *pkidx, int compat)
+{
+ struct namedobj_instance *ni;
+ struct table_config *tc, *tc_new, *tmp;
+ struct table_algo *ta;
+ uint16_t kidx;
+
+ ni = CHAIN_TO_NI(ch);
+
+ ta = find_table_algo(CHAIN_TO_TCFG(ch), ti, aname);
+ if (ta == NULL)
+ return (ENOTSUP);
+
+ tc = alloc_table_config(ch, ti, ta, aname, i->tflags);
+ if (tc == NULL)
+ return (ENOMEM);
+
+ tc->vmask = i->vmask;
+ tc->limit = i->limit;
+ if (ta->flags & TA_FLAG_READONLY)
+ tc->locked = 1;
+ else
+ tc->locked = (i->flags & IPFW_TGFLAGS_LOCKED) != 0;
+
+ IPFW_UH_WLOCK(ch);
+
+ /* Check if table has been already created */
+ tc_new = find_table(ni, ti);
+ if (tc_new != NULL) {
+
+ /*
+ * Compat: do not fail if we're
+ * requesting to create existing table
+ * which has the same type
+ */
+ if (compat == 0 || tc_new->no.type != tc->no.type) {
+ IPFW_UH_WUNLOCK(ch);
+ free_table_config(ni, tc);
+ return (EEXIST);
+ }
+
+ /* Exchange tc and tc_new for proper refcounting & freeing */
+ tmp = tc;
+ tc = tc_new;
+ tc_new = tmp;
+ } else {
+ /* New table */
+ if (ipfw_objhash_alloc_idx(ni, &kidx) != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ printf("Unable to allocate table index."
+ " Consider increasing net.inet.ip.fw.tables_max");
+ free_table_config(ni, tc);
+ return (EBUSY);
+ }
+ tc->no.kidx = kidx;
+
+ IPFW_WLOCK(ch);
+ link_table(ch, tc);
+ IPFW_WUNLOCK(ch);
+ }
+
+ if (compat != 0)
+ tc->no.refcnt++;
+ if (pkidx != NULL)
+ *pkidx = tc->no.kidx;
+
+ IPFW_UH_WUNLOCK(ch);
+
+ if (tc_new != NULL)
+ free_table_config(ni, tc_new);
- (*cnt)++;
return (0);
}
+static void
+ntlv_to_ti(ipfw_obj_ntlv *ntlv, struct tid_info *ti)
+{
+
+ memset(ti, 0, sizeof(struct tid_info));
+ ti->set = ntlv->set;
+ ti->uidx = ntlv->idx;
+ ti->tlvs = ntlv;
+ ti->tlen = ntlv->head.length;
+}
+
+static void
+objheader_to_ti(struct _ipfw_obj_header *oh, struct tid_info *ti)
+{
+
+ ntlv_to_ti(&oh->ntlv, ti);
+}
+
+/*
+ * Exports basic table info as name TLV.
+ * Used inside dump_static_rules() to provide info
+ * about all tables referenced by current ruleset.
+ *
+ * Returns 0 on success.
+ */
int
-ipfw_count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt)
+ipfw_export_table_ntlv(struct ip_fw_chain *ch, uint16_t kidx,
+ struct sockopt_data *sd)
{
- struct radix_node_head *rnh;
+ struct namedobj_instance *ni;
+ struct named_object *no;
+ ipfw_obj_ntlv *ntlv;
+
+ ni = CHAIN_TO_NI(ch);
+
+ no = ipfw_objhash_lookup_kidx(ni, kidx);
+ KASSERT(no != NULL, ("invalid table kidx passed"));
+
+ ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv));
+ if (ntlv == NULL)
+ return (ENOMEM);
+
+ ntlv->head.type = IPFW_TLV_TBL_NAME;
+ ntlv->head.length = sizeof(*ntlv);
+ ntlv->idx = no->kidx;
+ strlcpy(ntlv->name, no->name, sizeof(ntlv->name));
- if (tbl >= V_fw_tables_max)
- return (EINVAL);
- *cnt = 0;
- if ((rnh = ch->tables[tbl]) == NULL)
- return (0);
- rnh->rnh_walktree(rnh, count_table_entry, cnt);
return (0);
}
-static int
-dump_table_entry(struct radix_node *rn, void *arg)
+/*
+ * Marks every table kidx used in @rule with bit in @bmask.
+ * Used to generate bitmask of referenced tables for given ruleset.
+ *
+ * Returns number of newly-referenced tables.
+ */
+int
+ipfw_mark_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule,
+ uint32_t *bmask)
{
- struct table_entry * const n = (struct table_entry *)rn;
- ipfw_table * const tbl = arg;
+ int cmdlen, l, count;
+ ipfw_insn *cmd;
+ uint16_t kidx;
+ uint8_t type;
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ count = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+
+ if ((bmask[kidx / 32] & (1 << (kidx % 32))) == 0)
+ count++;
+
+ bmask[kidx / 32] |= 1 << (kidx % 32);
+ }
+
+ return (count);
+}
+
+struct dump_args {
+ struct ip_fw_chain *ch;
+ struct table_info *ti;
+ struct table_config *tc;
+ struct sockopt_data *sd;
+ uint32_t cnt;
+ uint16_t uidx;
+ int error;
+ uint32_t size;
ipfw_table_entry *ent;
+ ta_foreach_f *f;
+ void *farg;
+ ipfw_obj_tentry tent;
+};
+
+static int
+count_ext_entries(void *e, void *arg)
+{
+ struct dump_args *da;
+
+ da = (struct dump_args *)arg;
+ da->cnt++;
- if (tbl->cnt == tbl->size)
- return (1);
- ent = &tbl->ent[tbl->cnt];
- ent->tbl = tbl->tbl;
- if (in_nullhost(n->mask.sin_addr))
- ent->masklen = 0;
- else
- ent->masklen = 33 - ffs(ntohl(n->mask.sin_addr.s_addr));
- ent->addr = n->addr.sin_addr.s_addr;
- ent->value = n->value;
- tbl->cnt++;
return (0);
}
-int
-ipfw_dump_table(struct ip_fw_chain *ch, ipfw_table *tbl)
+/*
+ * Gets number of items from table either using
+ * internal counter or calling algo callback for
+ * externally-managed tables.
+ *
+ * Returns number of records.
+ */
+static uint32_t
+table_get_count(struct ip_fw_chain *ch, struct table_config *tc)
{
- struct radix_node_head *rnh;
+ struct table_info *ti;
+ struct table_algo *ta;
+ struct dump_args da;
+
+ ti = KIDX_TO_TI(ch, tc->no.kidx);
+ ta = tc->ta;
+
+ /* Use internal counter for self-managed tables */
+ if ((ta->flags & TA_FLAG_READONLY) == 0)
+ return (tc->count);
+
+ /* Use callback to quickly get number of items */
+ if ((ta->flags & TA_FLAG_EXTCOUNTER) != 0)
+ return (ta->get_count(tc->astate, ti));
- if (tbl->tbl >= V_fw_tables_max)
+ /* Count number of iterms ourselves */
+ memset(&da, 0, sizeof(da));
+ ta->foreach(tc->astate, ti, count_ext_entries, &da);
+
+ return (da.cnt);
+}
+
+/*
+ * Exports table @tc info into standard ipfw_xtable_info format.
+ */
+static void
+export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
+ ipfw_xtable_info *i)
+{
+ struct table_info *ti;
+ struct table_algo *ta;
+
+ i->type = tc->no.type;
+ i->tflags = tc->tflags;
+ i->vmask = tc->vmask;
+ i->set = tc->no.set;
+ i->kidx = tc->no.kidx;
+ i->refcnt = tc->no.refcnt;
+ i->count = table_get_count(ch, tc);
+ i->limit = tc->limit;
+ i->flags |= (tc->locked != 0) ? IPFW_TGFLAGS_LOCKED : 0;
+ i->size = tc->count * sizeof(ipfw_obj_tentry);
+ i->size += sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
+ strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));
+ ti = KIDX_TO_TI(ch, tc->no.kidx);
+ ta = tc->ta;
+ if (ta->print_config != NULL) {
+ /* Use algo function to print table config to string */
+ ta->print_config(tc->astate, ti, i->algoname,
+ sizeof(i->algoname));
+ } else
+ strlcpy(i->algoname, ta->name, sizeof(i->algoname));
+ /* Dump algo-specific data, if possible */
+ if (ta->dump_tinfo != NULL) {
+ ta->dump_tinfo(tc->astate, ti, &i->ta_info);
+ i->ta_info.flags |= IPFW_TATFLAGS_DATA;
+ }
+}
+
+struct dump_table_args {
+ struct ip_fw_chain *ch;
+ struct sockopt_data *sd;
+};
+
+static void
+export_table_internal(struct namedobj_instance *ni, struct named_object *no,
+ void *arg)
+{
+ ipfw_xtable_info *i;
+ struct dump_table_args *dta;
+
+ dta = (struct dump_table_args *)arg;
+
+ i = (ipfw_xtable_info *)ipfw_get_sopt_space(dta->sd, sizeof(*i));
+ KASSERT(i != 0, ("previously checked buffer is not enough"));
+
+ export_table_info(dta->ch, (struct table_config *)no, i);
+}
+
+/*
+ * Export all tables as ipfw_xtable_info structures to
+ * storage provided by @sd.
+ *
+ * If supplied buffer is too small, fills in required size
+ * and returns ENOMEM.
+ * Returns 0 on success.
+ */
+static int
+export_tables(struct ip_fw_chain *ch, ipfw_obj_lheader *olh,
+ struct sockopt_data *sd)
+{
+ uint32_t size;
+ uint32_t count;
+ struct dump_table_args dta;
+
+ count = ipfw_objhash_count(CHAIN_TO_NI(ch));
+ size = count * sizeof(ipfw_xtable_info) + sizeof(ipfw_obj_lheader);
+
+ /* Fill in header regadless of buffer size */
+ olh->count = count;
+ olh->objsize = sizeof(ipfw_xtable_info);
+
+ if (size > olh->size) {
+ olh->size = size;
+ return (ENOMEM);
+ }
+
+ olh->size = size;
+
+ dta.ch = ch;
+ dta.sd = sd;
+
+ ipfw_objhash_foreach(CHAIN_TO_NI(ch), export_table_internal, &dta);
+
+ return (0);
+}
+
+/*
+ * Dumps all table data
+ * Data layout (v1)(current):
+ * Request: [ ipfw_obj_header ], size = ipfw_xtable_info.size
+ * Reply: [ ipfw_obj_header ipfw_xtable_info ipfw_obj_tentry x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+dump_table_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ struct _ipfw_obj_header *oh;
+ ipfw_xtable_info *i;
+ struct tid_info ti;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct dump_args da;
+ uint32_t sz;
+
+ sz = sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
+ oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
+ if (oh == NULL)
return (EINVAL);
- tbl->cnt = 0;
- if ((rnh = ch->tables[tbl->tbl]) == NULL)
+
+ i = (ipfw_xtable_info *)(oh + 1);
+ objheader_to_ti(oh, &ti);
+
+ IPFW_UH_RLOCK(ch);
+ if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
+ return (ESRCH);
+ }
+ export_table_info(ch, tc, i);
+
+ if (sd->valsize < i->size) {
+
+ /*
+ * Submitted buffer size is not enough.
+ * WE've already filled in @i structure with
+ * relevant table info including size, so we
+ * can return. Buffer will be flushed automatically.
+ */
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOMEM);
+ }
+
+ /*
+ * Do the actual dump in eXtended format
+ */
+ memset(&da, 0, sizeof(da));
+ da.ch = ch;
+ da.ti = KIDX_TO_TI(ch, tc->no.kidx);
+ da.tc = tc;
+ da.sd = sd;
+
+ ta = tc->ta;
+
+ ta->foreach(tc->astate, da.ti, dump_table_tentry, &da);
+ IPFW_UH_RUNLOCK(ch);
+
+ return (da.error);
+}
+
+/*
+ * Dumps all table data
+ * Data layout (version 0)(legacy):
+ * Request: [ ipfw_xtable ], size = IP_FW_TABLE_XGETSIZE()
+ * Reply: [ ipfw_xtable ipfw_table_xentry x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+dump_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_xtable *xtbl;
+ struct tid_info ti;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct dump_args da;
+ size_t sz, count;
+
+ xtbl = (ipfw_xtable *)ipfw_get_sopt_header(sd, sizeof(ipfw_xtable));
+ if (xtbl == NULL)
+ return (EINVAL);
+
+ memset(&ti, 0, sizeof(ti));
+ ti.uidx = xtbl->tbl;
+
+ IPFW_UH_RLOCK(ch);
+ if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
return (0);
- rnh->rnh_walktree(rnh, dump_table_entry, tbl);
+ }
+ count = table_get_count(ch, tc);
+ sz = count * sizeof(ipfw_table_xentry) + sizeof(ipfw_xtable);
+
+ xtbl->cnt = count;
+ xtbl->size = sz;
+ xtbl->type = tc->no.type;
+ xtbl->tbl = ti.uidx;
+
+ if (sd->valsize < sz) {
+
+ /*
+ * Submitted buffer size is not enough.
+ * WE've already filled in @i structure with
+ * relevant table info including size, so we
+ * can return. Buffer will be flushed automatically.
+ */
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOMEM);
+ }
+
+ /* Do the actual dump in eXtended format */
+ memset(&da, 0, sizeof(da));
+ da.ch = ch;
+ da.ti = KIDX_TO_TI(ch, tc->no.kidx);
+ da.tc = tc;
+ da.sd = sd;
+
+ ta = tc->ta;
+
+ ta->foreach(tc->astate, da.ti, dump_table_xentry, &da);
+ IPFW_UH_RUNLOCK(ch);
+
return (0);
}
+/*
+ * Legacy function to retrieve number of items in table.
+ */
static int
-count_table_xentry(struct radix_node *rn, void *arg)
+get_table_size(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ uint32_t *tbl;
+ struct tid_info ti;
+ size_t sz;
+ int error;
+
+ sz = sizeof(*op3) + sizeof(uint32_t);
+ op3 = (ip_fw3_opheader *)ipfw_get_sopt_header(sd, sz);
+ if (op3 == NULL)
+ return (EINVAL);
+
+ tbl = (uint32_t *)(op3 + 1);
+ memset(&ti, 0, sizeof(ti));
+ ti.uidx = *tbl;
+ IPFW_UH_RLOCK(ch);
+ error = ipfw_count_xtable(ch, &ti, tbl);
+ IPFW_UH_RUNLOCK(ch);
+ return (error);
+}
+
+/*
+ * Legacy IP_FW_TABLE_GETSIZE handler
+ */
+int
+ipfw_count_table(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
{
- uint32_t * const cnt = arg;
+ struct table_config *tc;
- (*cnt) += sizeof(ipfw_table_xentry);
+ if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
+ return (ESRCH);
+ *cnt = table_get_count(ch, tc);
return (0);
}
+/*
+ * Legacy IP_FW_TABLE_XGETSIZE handler
+ */
int
-ipfw_count_xtable(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt)
+ipfw_count_xtable(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
{
- struct radix_node_head *rnh;
+ struct table_config *tc;
+ uint32_t count;
+
+ if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL) {
+ *cnt = 0;
+ return (0); /* 'table all list' requires success */
+ }
+
+ count = table_get_count(ch, tc);
+ *cnt = count * sizeof(ipfw_table_xentry);
+ if (count > 0)
+ *cnt += sizeof(ipfw_xtable);
+ return (0);
+}
+
+static int
+dump_table_entry(void *e, void *arg)
+{
+ struct dump_args *da;
+ struct table_config *tc;
+ struct table_algo *ta;
+ ipfw_table_entry *ent;
+ struct table_value *pval;
+ int error;
+
+ da = (struct dump_args *)arg;
+
+ tc = da->tc;
+ ta = tc->ta;
+
+ /* Out of memory, returning */
+ if (da->cnt == da->size)
+ return (1);
+ ent = da->ent++;
+ ent->tbl = da->uidx;
+ da->cnt++;
+
+ error = ta->dump_tentry(tc->astate, da->ti, e, &da->tent);
+ if (error != 0)
+ return (error);
+
+ ent->addr = da->tent.k.addr.s_addr;
+ ent->masklen = da->tent.masklen;
+ pval = get_table_value(da->ch, da->tc, da->tent.v.kidx);
+ ent->value = ipfw_export_table_value_legacy(pval);
- if (tbl >= V_fw_tables_max)
- return (EINVAL);
- *cnt = 0;
- if ((rnh = ch->tables[tbl]) != NULL)
- rnh->rnh_walktree(rnh, count_table_xentry, cnt);
- if ((rnh = ch->xtables[tbl]) != NULL)
- rnh->rnh_walktree(rnh, count_table_xentry, cnt);
- /* Return zero if table is empty */
- if (*cnt > 0)
- (*cnt) += sizeof(ipfw_xtable);
return (0);
}
+/*
+ * Dumps table in pre-8.1 legacy format.
+ */
+int
+ipfw_dump_table_legacy(struct ip_fw_chain *ch, struct tid_info *ti,
+ ipfw_table *tbl)
+{
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct dump_args da;
+
+ tbl->cnt = 0;
+
+ if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
+ return (0); /* XXX: We should return ESRCH */
+ ta = tc->ta;
+
+ /* This dump format supports IPv4 only */
+ if (tc->no.type != IPFW_TABLE_ADDR)
+ return (0);
+
+ memset(&da, 0, sizeof(da));
+ da.ch = ch;
+ da.ti = KIDX_TO_TI(ch, tc->no.kidx);
+ da.tc = tc;
+ da.ent = &tbl->ent[0];
+ da.size = tbl->size;
+
+ tbl->cnt = 0;
+ ta->foreach(tc->astate, da.ti, dump_table_entry, &da);
+ tbl->cnt = da.cnt;
+
+ return (0);
+}
+
+/*
+ * Dumps table entry in eXtended format (v1)(current).
+ */
static int
-dump_table_xentry_base(struct radix_node *rn, void *arg)
+dump_table_tentry(void *e, void *arg)
{
- struct table_entry * const n = (struct table_entry *)rn;
- ipfw_xtable * const tbl = arg;
- ipfw_table_xentry *xent;
+ struct dump_args *da;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct table_value *pval;
+ ipfw_obj_tentry *tent;
+ int error;
+
+ da = (struct dump_args *)arg;
+ tc = da->tc;
+ ta = tc->ta;
+
+ tent = (ipfw_obj_tentry *)ipfw_get_sopt_space(da->sd, sizeof(*tent));
/* Out of memory, returning */
- if (tbl->cnt == tbl->size)
+ if (tent == NULL) {
+ da->error = ENOMEM;
return (1);
- xent = &tbl->xent[tbl->cnt];
- xent->len = sizeof(ipfw_table_xentry);
- xent->tbl = tbl->tbl;
- if (in_nullhost(n->mask.sin_addr))
- xent->masklen = 0;
- else
- xent->masklen = 33 - ffs(ntohl(n->mask.sin_addr.s_addr));
- /* Save IPv4 address as deprecated IPv6 compatible */
- xent->k.addr6.s6_addr32[3] = n->addr.sin_addr.s_addr;
- xent->flags = IPFW_TCF_INET;
- xent->value = n->value;
- tbl->cnt++;
+ }
+ tent->head.length = sizeof(ipfw_obj_tentry);
+ tent->idx = da->uidx;
+
+ error = ta->dump_tentry(tc->astate, da->ti, e, tent);
+ if (error != 0)
+ return (error);
+
+ pval = get_table_value(da->ch, da->tc, tent->v.kidx);
+ ipfw_export_table_value_v1(pval, &tent->v.value);
+
return (0);
}
+/*
+ * Dumps table entry in eXtended format (v0).
+ */
static int
-dump_table_xentry_extended(struct radix_node *rn, void *arg)
+dump_table_xentry(void *e, void *arg)
{
- struct table_xentry * const n = (struct table_xentry *)rn;
- ipfw_xtable * const tbl = arg;
+ struct dump_args *da;
+ struct table_config *tc;
+ struct table_algo *ta;
ipfw_table_xentry *xent;
-#ifdef INET6
- int i;
- uint32_t *v;
-#endif
+ ipfw_obj_tentry *tent;
+ struct table_value *pval;
+ int error;
+
+ da = (struct dump_args *)arg;
+
+ tc = da->tc;
+ ta = tc->ta;
+
+ xent = (ipfw_table_xentry *)ipfw_get_sopt_space(da->sd, sizeof(*xent));
/* Out of memory, returning */
- if (tbl->cnt == tbl->size)
+ if (xent == NULL)
return (1);
- xent = &tbl->xent[tbl->cnt];
xent->len = sizeof(ipfw_table_xentry);
- xent->tbl = tbl->tbl;
-
- switch (tbl->type) {
-#ifdef INET6
- case IPFW_TABLE_CIDR:
- /* Count IPv6 mask */
- v = (uint32_t *)&n->m.mask6.sin6_addr;
- for (i = 0; i < sizeof(struct in6_addr) / 4; i++, v++)
- xent->masklen += bitcount32(*v);
- memcpy(&xent->k, &n->a.addr6.sin6_addr, sizeof(struct in6_addr));
- break;
-#endif
- case IPFW_TABLE_INTERFACE:
- /* Assume exact mask */
- xent->masklen = 8 * IF_NAMESIZE;
- memcpy(&xent->k, &n->a.iface.ifname, IF_NAMESIZE);
- break;
+ xent->tbl = da->uidx;
+
+ memset(&da->tent, 0, sizeof(da->tent));
+ tent = &da->tent;
+ error = ta->dump_tentry(tc->astate, da->ti, e, tent);
+ if (error != 0)
+ return (error);
+
+ /* Convert current format to previous one */
+ xent->masklen = tent->masklen;
+ pval = get_table_value(da->ch, da->tc, da->tent.v.kidx);
+ xent->value = ipfw_export_table_value_legacy(pval);
+ /* Apply some hacks */
+ if (tc->no.type == IPFW_TABLE_ADDR && tent->subtype == AF_INET) {
+ xent->k.addr6.s6_addr32[3] = tent->k.addr.s_addr;
+ xent->flags = IPFW_TCF_INET;
+ } else
+ memcpy(&xent->k, &tent->k, sizeof(xent->k));
+
+ return (0);
+}
+
+/*
+ * Helper function to export table algo data
+ * to tentry format before calling user function.
+ *
+ * Returns 0 on success.
+ */
+static int
+prepare_table_tentry(void *e, void *arg)
+{
+ struct dump_args *da;
+ struct table_config *tc;
+ struct table_algo *ta;
+ int error;
+
+ da = (struct dump_args *)arg;
+
+ tc = da->tc;
+ ta = tc->ta;
+
+ error = ta->dump_tentry(tc->astate, da->ti, e, &da->tent);
+ if (error != 0)
+ return (error);
+
+ da->f(&da->tent, da->farg);
+
+ return (0);
+}
+
+/*
+ * Allow external consumers to read table entries in standard format.
+ */
+int
+ipfw_foreach_table_tentry(struct ip_fw_chain *ch, uint16_t kidx,
+ ta_foreach_f *f, void *arg)
+{
+ struct namedobj_instance *ni;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct dump_args da;
+
+ ni = CHAIN_TO_NI(ch);
+
+ tc = (struct table_config *)ipfw_objhash_lookup_kidx(ni, kidx);
+ if (tc == NULL)
+ return (ESRCH);
+
+ ta = tc->ta;
+
+ memset(&da, 0, sizeof(da));
+ da.ch = ch;
+ da.ti = KIDX_TO_TI(ch, tc->no.kidx);
+ da.tc = tc;
+ da.f = f;
+ da.farg = arg;
+
+ ta->foreach(tc->astate, da.ti, prepare_table_tentry, &da);
+
+ return (0);
+}
+
+/*
+ * Table algorithms
+ */
+
+/*
+ * Finds algoritm by index, table type or supplied name.
+ *
+ * Returns pointer to algo or NULL.
+ */
+static struct table_algo *
+find_table_algo(struct tables_config *tcfg, struct tid_info *ti, char *name)
+{
+ int i, l;
+ struct table_algo *ta;
+
+ if (ti->type > IPFW_TABLE_MAXTYPE)
+ return (NULL);
+
+ /* Search by index */
+ if (ti->atype != 0) {
+ if (ti->atype > tcfg->algo_count)
+ return (NULL);
+ return (tcfg->algo[ti->atype]);
+ }
+
+ if (name == NULL) {
+ /* Return default algorithm for given type if set */
+ return (tcfg->def_algo[ti->type]);
+ }
+
+ /* Search by name */
+ /* TODO: better search */
+ for (i = 1; i <= tcfg->algo_count; i++) {
+ ta = tcfg->algo[i];
+
+ /*
+ * One can supply additional algorithm
+ * parameters so we compare only the first word
+ * of supplied name:
+ * 'addr:chash hsize=32'
+ * '^^^^^^^^^'
+ *
+ */
+ l = strlen(ta->name);
+ if (strncmp(name, ta->name, l) != 0)
+ continue;
+ if (name[l] != '\0' && name[l] != ' ')
+ continue;
+ /* Check if we're requesting proper table type */
+ if (ti->type != 0 && ti->type != ta->type)
+ return (NULL);
+ return (ta);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Register new table algo @ta.
+ * Stores algo id inside @idx.
+ *
+ * Returns 0 on success.
+ */
+int
+ipfw_add_table_algo(struct ip_fw_chain *ch, struct table_algo *ta, size_t size,
+ int *idx)
+{
+ struct tables_config *tcfg;
+ struct table_algo *ta_new;
+ size_t sz;
+
+ if (size > sizeof(struct table_algo))
+ return (EINVAL);
+
+ /* Check for the required on-stack size for add/del */
+ sz = roundup2(ta->ta_buf_size, sizeof(void *));
+ if (sz > TA_BUF_SZ)
+ return (EINVAL);
+
+ KASSERT(ta->type <= IPFW_TABLE_MAXTYPE,("Increase IPFW_TABLE_MAXTYPE"));
+
+ /* Copy algorithm data to stable storage. */
+ ta_new = malloc(sizeof(struct table_algo), M_IPFW, M_WAITOK | M_ZERO);
+ memcpy(ta_new, ta, size);
+
+ tcfg = CHAIN_TO_TCFG(ch);
+
+ KASSERT(tcfg->algo_count < 255, ("Increase algo array size"));
+
+ tcfg->algo[++tcfg->algo_count] = ta_new;
+ ta_new->idx = tcfg->algo_count;
+
+ /* Set algorithm as default one for given type */
+ if ((ta_new->flags & TA_FLAG_DEFAULT) != 0 &&
+ tcfg->def_algo[ta_new->type] == NULL)
+ tcfg->def_algo[ta_new->type] = ta_new;
+
+ *idx = ta_new->idx;
- default:
- /* unknown, skip entry */
- return (0);
+ return (0);
+}
+
+/*
+ * Unregisters table algo using @idx as id.
+ * XXX: It is NOT safe to call this function in any place
+ * other than ipfw instance destroy handler.
+ */
+void
+ipfw_del_table_algo(struct ip_fw_chain *ch, int idx)
+{
+ struct tables_config *tcfg;
+ struct table_algo *ta;
+
+ tcfg = CHAIN_TO_TCFG(ch);
+
+ KASSERT(idx <= tcfg->algo_count, ("algo idx %d out of range 1..%d",
+ idx, tcfg->algo_count));
+
+ ta = tcfg->algo[idx];
+ KASSERT(ta != NULL, ("algo idx %d is NULL", idx));
+
+ if (tcfg->def_algo[ta->type] == ta)
+ tcfg->def_algo[ta->type] = NULL;
+
+ free(ta, M_IPFW);
+}
+
+/*
+ * Lists all table algorithms currently available.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_ta_info x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+list_table_algo(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ struct _ipfw_obj_lheader *olh;
+ struct tables_config *tcfg;
+ ipfw_ta_info *i;
+ struct table_algo *ta;
+ uint32_t count, n, size;
+
+ olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
+ if (olh == NULL)
+ return (EINVAL);
+ if (sd->valsize < olh->size)
+ return (EINVAL);
+
+ IPFW_UH_RLOCK(ch);
+ tcfg = CHAIN_TO_TCFG(ch);
+ count = tcfg->algo_count;
+ size = count * sizeof(ipfw_ta_info) + sizeof(ipfw_obj_lheader);
+
+ /* Fill in header regadless of buffer size */
+ olh->count = count;
+ olh->objsize = sizeof(ipfw_ta_info);
+
+ if (size > olh->size) {
+ olh->size = size;
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOMEM);
+ }
+ olh->size = size;
+
+ for (n = 1; n <= count; n++) {
+ i = (ipfw_ta_info *)ipfw_get_sopt_space(sd, sizeof(*i));
+ KASSERT(i != 0, ("previously checked buffer is not enough"));
+ ta = tcfg->algo[n];
+ strlcpy(i->algoname, ta->name, sizeof(i->algoname));
+ i->type = ta->type;
+ i->refcnt = ta->refcnt;
}
- xent->value = n->value;
- tbl->cnt++;
+ IPFW_UH_RUNLOCK(ch);
+
return (0);
}
+/*
+ * Tables rewriting code
+ */
+
+/*
+ * Determine table number and lookup type for @cmd.
+ * Fill @tbl and @type with appropriate values.
+ * Returns 0 for relevant opcodes, 1 otherwise.
+ */
+static int
+classify_table_opcode(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype)
+{
+ ipfw_insn_if *cmdif;
+ int skip;
+ uint16_t v;
+
+ skip = 1;
+
+ switch (cmd->opcode) {
+ case O_IP_SRC_LOOKUP:
+ case O_IP_DST_LOOKUP:
+ /* Basic IPv4/IPv6 or u32 lookups */
+ *puidx = cmd->arg1;
+ /* Assume ADDR by default */
+ *ptype = IPFW_TABLE_ADDR;
+ skip = 0;
+
+ if (F_LEN(cmd) > F_INSN_SIZE(ipfw_insn_u32)) {
+ /*
+ * generic lookup. The key must be
+ * in 32bit big-endian format.
+ */
+ v = ((ipfw_insn_u32 *)cmd)->d[1];
+ switch (v) {
+ case 0:
+ case 1:
+ /* IPv4 src/dst */
+ break;
+ case 2:
+ case 3:
+ /* src/dst port */
+ *ptype = IPFW_TABLE_NUMBER;
+ break;
+ case 4:
+ /* uid/gid */
+ *ptype = IPFW_TABLE_NUMBER;
+ break;
+ case 5:
+ /* jid */
+ *ptype = IPFW_TABLE_NUMBER;
+ break;
+ case 6:
+ /* dscp */
+ *ptype = IPFW_TABLE_NUMBER;
+ break;
+ }
+ }
+ break;
+ case O_XMIT:
+ case O_RECV:
+ case O_VIA:
+ /* Interface table, possibly */
+ cmdif = (ipfw_insn_if *)cmd;
+ if (cmdif->name[0] != '\1')
+ break;
+
+ *ptype = IPFW_TABLE_INTERFACE;
+ *puidx = cmdif->p.kidx;
+ skip = 0;
+ break;
+ case O_IP_FLOW_LOOKUP:
+ *puidx = cmd->arg1;
+ *ptype = IPFW_TABLE_FLOW;
+ skip = 0;
+ break;
+ }
+
+ return (skip);
+}
+
+/*
+ * Sets new table value for given opcode.
+ * Assume the same opcodes as classify_table_opcode()
+ */
+static void
+update_table_opcode(ipfw_insn *cmd, uint16_t idx)
+{
+ ipfw_insn_if *cmdif;
+
+ switch (cmd->opcode) {
+ case O_IP_SRC_LOOKUP:
+ case O_IP_DST_LOOKUP:
+ /* Basic IPv4/IPv6 or u32 lookups */
+ cmd->arg1 = idx;
+ break;
+ case O_XMIT:
+ case O_RECV:
+ case O_VIA:
+ /* Interface table, possibly */
+ cmdif = (ipfw_insn_if *)cmd;
+ cmdif->p.kidx = idx;
+ break;
+ case O_IP_FLOW_LOOKUP:
+ cmd->arg1 = idx;
+ break;
+ }
+}
+
+/*
+ * Checks table name for validity.
+ * Enforce basic length checks, the rest
+ * should be done in userland.
+ *
+ * Returns 0 if name is considered valid.
+ */
int
-ipfw_dump_xtable(struct ip_fw_chain *ch, ipfw_xtable *tbl)
+ipfw_check_table_name(char *name)
{
- struct radix_node_head *rnh;
+ int nsize;
+ ipfw_obj_ntlv *ntlv = NULL;
+
+ nsize = sizeof(ntlv->name);
- if (tbl->tbl >= V_fw_tables_max)
+ if (strnlen(name, nsize) == nsize)
return (EINVAL);
- tbl->cnt = 0;
- tbl->type = ch->tabletype[tbl->tbl];
- if ((rnh = ch->tables[tbl->tbl]) != NULL)
- rnh->rnh_walktree(rnh, dump_table_xentry_base, tbl);
- if ((rnh = ch->xtables[tbl->tbl]) != NULL)
- rnh->rnh_walktree(rnh, dump_table_xentry_extended, tbl);
+
+ if (name[0] == '\0')
+ return (EINVAL);
+
+ /*
+ * TODO: do some more complicated checks
+ */
+
return (0);
}
-/* end of file */
+/*
+ * Find tablename TLV by @uid.
+ * Check @tlvs for valid data inside.
+ *
+ * Returns pointer to found TLV or NULL.
+ */
+static ipfw_obj_ntlv *
+find_name_tlv(void *tlvs, int len, uint16_t uidx)
+{
+ ipfw_obj_ntlv *ntlv;
+ uintptr_t pa, pe;
+ int l;
+
+ pa = (uintptr_t)tlvs;
+ pe = pa + len;
+ l = 0;
+ for (; pa < pe; pa += l) {
+ ntlv = (ipfw_obj_ntlv *)pa;
+ l = ntlv->head.length;
+
+ if (l != sizeof(*ntlv))
+ return (NULL);
+
+ if (ntlv->head.type != IPFW_TLV_TBL_NAME)
+ continue;
+
+ if (ntlv->idx != uidx)
+ continue;
+
+ if (ipfw_check_table_name(ntlv->name) != 0)
+ return (NULL);
+
+ return (ntlv);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Finds table config based on either legacy index
+ * or name in ntlv.
+ * Note @ti structure contains unchecked data from userland.
+ *
+ * Returns pointer to table_config or NULL.
+ */
+static struct table_config *
+find_table(struct namedobj_instance *ni, struct tid_info *ti)
+{
+ char *name, bname[16];
+ struct named_object *no;
+ ipfw_obj_ntlv *ntlv;
+ uint32_t set;
+
+ if (ti->tlvs != NULL) {
+ ntlv = find_name_tlv(ti->tlvs, ti->tlen, ti->uidx);
+ if (ntlv == NULL)
+ return (NULL);
+ name = ntlv->name;
+
+ /*
+ * Use set provided by @ti instead of @ntlv one.
+ * This is needed due to different sets behavior
+ * controlled by V_fw_tables_sets.
+ */
+ set = ti->set;
+ } else {
+ snprintf(bname, sizeof(bname), "%d", ti->uidx);
+ name = bname;
+ set = 0;
+ }
+
+ no = ipfw_objhash_lookup_name(ni, set, name);
+
+ return ((struct table_config *)no);
+}
+
+/*
+ * Allocate new table config structure using
+ * specified @algo and @aname.
+ *
+ * Returns pointer to config or NULL.
+ */
+static struct table_config *
+alloc_table_config(struct ip_fw_chain *ch, struct tid_info *ti,
+ struct table_algo *ta, char *aname, uint8_t tflags)
+{
+ char *name, bname[16];
+ struct table_config *tc;
+ int error;
+ ipfw_obj_ntlv *ntlv;
+ uint32_t set;
+
+ if (ti->tlvs != NULL) {
+ ntlv = find_name_tlv(ti->tlvs, ti->tlen, ti->uidx);
+ if (ntlv == NULL)
+ return (NULL);
+ name = ntlv->name;
+ set = ntlv->set;
+ } else {
+ snprintf(bname, sizeof(bname), "%d", ti->uidx);
+ name = bname;
+ set = 0;
+ }
+
+ tc = malloc(sizeof(struct table_config), M_IPFW, M_WAITOK | M_ZERO);
+ tc->no.name = tc->tablename;
+ tc->no.type = ta->type;
+ tc->no.set = set;
+ tc->tflags = tflags;
+ tc->ta = ta;
+ strlcpy(tc->tablename, name, sizeof(tc->tablename));
+ /* Set "shared" value type by default */
+ tc->vshared = 1;
+
+ if (ti->tlvs == NULL) {
+ tc->no.compat = 1;
+ tc->no.uidx = ti->uidx;
+ }
+
+ /* Preallocate data structures for new tables */
+ error = ta->init(ch, &tc->astate, &tc->ti_copy, aname, tflags);
+ if (error != 0) {
+ free(tc, M_IPFW);
+ return (NULL);
+ }
+
+ return (tc);
+}
+
+/*
+ * Destroys table state and config.
+ */
+static void
+free_table_config(struct namedobj_instance *ni, struct table_config *tc)
+{
+
+ KASSERT(tc->linked == 0, ("free() on linked config"));
+
+ /*
+ * We're using ta without any locking/referencing.
+ * TODO: fix this if we're going to use unloadable algos.
+ */
+ tc->ta->destroy(tc->astate, &tc->ti_copy);
+ free(tc, M_IPFW);
+}
+
+/*
+ * Links @tc to @chain table named instance.
+ * Sets appropriate type/states in @chain table info.
+ */
+static void
+link_table(struct ip_fw_chain *ch, struct table_config *tc)
+{
+ struct namedobj_instance *ni;
+ struct table_info *ti;
+ uint16_t kidx;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+ IPFW_WLOCK_ASSERT(ch);
+
+ ni = CHAIN_TO_NI(ch);
+ kidx = tc->no.kidx;
+
+ ipfw_objhash_add(ni, &tc->no);
+
+ ti = KIDX_TO_TI(ch, kidx);
+ *ti = tc->ti_copy;
+
+ /* Notify algo on real @ti address */
+ if (tc->ta->change_ti != NULL)
+ tc->ta->change_ti(tc->astate, ti);
+
+ tc->linked = 1;
+ tc->ta->refcnt++;
+}
+
+/*
+ * Unlinks @tc from @chain table named instance.
+ * Zeroes states in @chain and stores them in @tc.
+ */
+static void
+unlink_table(struct ip_fw_chain *ch, struct table_config *tc)
+{
+ struct namedobj_instance *ni;
+ struct table_info *ti;
+ uint16_t kidx;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+ IPFW_WLOCK_ASSERT(ch);
+
+ ni = CHAIN_TO_NI(ch);
+ kidx = tc->no.kidx;
+
+ /* Clear state. @ti copy is already saved inside @tc */
+ ipfw_objhash_del(ni, &tc->no);
+ ti = KIDX_TO_TI(ch, kidx);
+ memset(ti, 0, sizeof(struct table_info));
+ tc->linked = 0;
+ tc->ta->refcnt--;
+
+ /* Notify algo on real @ti address */
+ if (tc->ta->change_ti != NULL)
+ tc->ta->change_ti(tc->astate, NULL);
+}
+
+struct swap_table_args {
+ int set;
+ int new_set;
+ int mv;
+};
+
+/*
+ * Change set for each matching table.
+ *
+ * Ensure we dispatch each table once by setting/checking ochange
+ * fields.
+ */
+static void
+swap_table_set(struct namedobj_instance *ni, struct named_object *no,
+ void *arg)
+{
+ struct table_config *tc;
+ struct swap_table_args *sta;
+
+ tc = (struct table_config *)no;
+ sta = (struct swap_table_args *)arg;
+
+ if (no->set != sta->set && (no->set != sta->new_set || sta->mv != 0))
+ return;
+
+ if (tc->ochanged != 0)
+ return;
+
+ tc->ochanged = 1;
+ ipfw_objhash_del(ni, no);
+ if (no->set == sta->set)
+ no->set = sta->new_set;
+ else
+ no->set = sta->set;
+ ipfw_objhash_add(ni, no);
+}
+
+/*
+ * Cleans up ochange field for all tables.
+ */
+static void
+clean_table_set_data(struct namedobj_instance *ni, struct named_object *no,
+ void *arg)
+{
+ struct table_config *tc;
+ struct swap_table_args *sta;
+
+ tc = (struct table_config *)no;
+ sta = (struct swap_table_args *)arg;
+
+ tc->ochanged = 0;
+}
+
+/*
+ * Swaps tables within two sets.
+ */
+void
+ipfw_swap_tables_sets(struct ip_fw_chain *ch, uint32_t set,
+ uint32_t new_set, int mv)
+{
+ struct swap_table_args sta;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ sta.set = set;
+ sta.new_set = new_set;
+ sta.mv = mv;
+
+ ipfw_objhash_foreach(CHAIN_TO_NI(ch), swap_table_set, &sta);
+ ipfw_objhash_foreach(CHAIN_TO_NI(ch), clean_table_set_data, &sta);
+}
+
+/*
+ * Move all tables which are reference by rules in @rr to set @new_set.
+ * Makes sure that all relevant tables are referenced ONLLY by given rules.
+ *
+ * Retuns 0 on success,
+ */
+int
+ipfw_move_tables_sets(struct ip_fw_chain *ch, ipfw_range_tlv *rt,
+ uint32_t new_set)
+{
+ struct ip_fw *rule;
+ struct table_config *tc;
+ struct named_object *no;
+ struct namedobj_instance *ni;
+ int bad, i, l, cmdlen;
+ uint16_t kidx;
+ uint8_t type;
+ ipfw_insn *cmd;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ ni = CHAIN_TO_NI(ch);
+
+ /* Stage 1: count number of references by given rules */
+ for (i = 0; i < ch->n_rules - 1; i++) {
+ rule = ch->map[i];
+ if (ipfw_match_range(rule, rt) == 0)
+ continue;
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+ no = ipfw_objhash_lookup_kidx(ni, kidx);
+ KASSERT(no != NULL,
+ ("objhash lookup failed on index %d", kidx));
+ tc = (struct table_config *)no;
+ tc->ocount++;
+ }
+
+ }
+
+ /* Stage 2: verify "ownership" */
+ bad = 0;
+ for (i = 0; i < ch->n_rules - 1; i++) {
+ rule = ch->map[i];
+ if (ipfw_match_range(rule, rt) == 0)
+ continue;
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+ no = ipfw_objhash_lookup_kidx(ni, kidx);
+ KASSERT(no != NULL,
+ ("objhash lookup failed on index %d", kidx));
+ tc = (struct table_config *)no;
+ if (tc->no.refcnt != tc->ocount) {
+
+ /*
+ * Number of references differ:
+ * Other rule(s) are holding reference to given
+ * table, so it is not possible to change its set.
+ *
+ * Note that refcnt may account
+ * references to some going-to-be-added rules.
+ * Since we don't know their numbers (and event
+ * if they will be added) it is perfectly OK
+ * to return error here.
+ */
+ bad = 1;
+ break;
+ }
+ }
+
+ if (bad != 0)
+ break;
+ }
+
+ /* Stage 3: change set or cleanup */
+ for (i = 0; i < ch->n_rules - 1; i++) {
+ rule = ch->map[i];
+ if (ipfw_match_range(rule, rt) == 0)
+ continue;
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+ no = ipfw_objhash_lookup_kidx(ni, kidx);
+ KASSERT(no != NULL,
+ ("objhash lookup failed on index %d", kidx));
+ tc = (struct table_config *)no;
+
+ tc->ocount = 0;
+ if (bad != 0)
+ continue;
+
+ /* Actually change set. */
+ ipfw_objhash_del(ni, no);
+ no->set = new_set;
+ ipfw_objhash_add(ni, no);
+ }
+ }
+
+ return (bad);
+}
+
+/*
+ * Finds and bumps refcount for tables referenced by given @rule.
+ * Auto-creates non-existing tables.
+ * Fills in @oib array with userland/kernel indexes.
+ * First free oidx pointer is saved back in @oib.
+ *
+ * Returns 0 on success.
+ */
+static int
+find_ref_rule_tables(struct ip_fw_chain *ch, struct ip_fw *rule,
+ struct rule_check_info *ci, struct obj_idx **oib, struct tid_info *ti)
+{
+ struct table_config *tc;
+ struct namedobj_instance *ni;
+ struct named_object *no;
+ int cmdlen, error, l, numnew;
+ uint16_t kidx;
+ ipfw_insn *cmd;
+ struct obj_idx *pidx, *pidx_first, *p;
+
+ pidx_first = *oib;
+ pidx = pidx_first;
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ error = 0;
+ numnew = 0;
+
+ IPFW_UH_WLOCK(ch);
+ ni = CHAIN_TO_NI(ch);
+
+ /* Increase refcount on each existing referenced table. */
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &ti->uidx, &ti->type) != 0)
+ continue;
+
+ pidx->uidx = ti->uidx;
+ pidx->type = ti->type;
+
+ if ((tc = find_table(ni, ti)) != NULL) {
+ if (tc->no.type != ti->type) {
+ /* Incompatible types */
+ error = EINVAL;
+ break;
+ }
+
+ /* Reference found table and save kidx */
+ tc->no.refcnt++;
+ pidx->kidx = tc->no.kidx;
+ pidx++;
+ continue;
+ }
+
+ /*
+ * Compability stuff for old clients:
+ * prepare to manually create non-existing tables.
+ */
+ pidx++;
+ numnew++;
+ }
+
+ if (error != 0) {
+ /* Unref everything we have already done */
+ for (p = *oib; p < pidx; p++) {
+ if (p->kidx == 0)
+ continue;
+
+ /* Find & unref by existing idx */
+ no = ipfw_objhash_lookup_kidx(ni, p->kidx);
+ KASSERT(no != NULL, ("Ref'd table %d disappeared",
+ p->kidx));
+
+ no->refcnt--;
+ }
+ }
+
+ IPFW_UH_WUNLOCK(ch);
+
+ if (numnew == 0) {
+ *oib = pidx;
+ return (error);
+ }
+
+ /*
+ * Compatibility stuff: do actual creation for non-existing,
+ * but referenced tables.
+ */
+ for (p = pidx_first; p < pidx; p++) {
+ if (p->kidx != 0)
+ continue;
+
+ ti->uidx = p->uidx;
+ ti->type = p->type;
+ ti->atype = 0;
+
+ error = create_table_compat(ch, ti, &kidx);
+ if (error == 0) {
+ p->kidx = kidx;
+ continue;
+ }
+
+ /* Error. We have to drop references */
+ IPFW_UH_WLOCK(ch);
+ for (p = pidx_first; p < pidx; p++) {
+ if (p->kidx == 0)
+ continue;
+
+ /* Find & unref by existing idx */
+ no = ipfw_objhash_lookup_kidx(ni, p->kidx);
+ KASSERT(no != NULL, ("Ref'd table %d disappeared",
+ p->kidx));
+
+ no->refcnt--;
+ }
+ IPFW_UH_WUNLOCK(ch);
+
+ return (error);
+ }
+
+ *oib = pidx;
+
+ return (error);
+}
+
+/*
+ * Remove references from every table used in @rule.
+ */
+void
+ipfw_unref_rule_tables(struct ip_fw_chain *chain, struct ip_fw *rule)
+{
+ int cmdlen, l;
+ ipfw_insn *cmd;
+ struct namedobj_instance *ni;
+ struct named_object *no;
+ uint16_t kidx;
+ uint8_t type;
+
+ IPFW_UH_WLOCK_ASSERT(chain);
+ ni = CHAIN_TO_NI(chain);
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+
+ no = ipfw_objhash_lookup_kidx(ni, kidx);
+
+ KASSERT(no != NULL, ("table id %d not found", kidx));
+ KASSERT(no->type == type, ("wrong type %d (%d) for table id %d",
+ no->type, type, kidx));
+ KASSERT(no->refcnt > 0, ("refcount for table %d is %d",
+ kidx, no->refcnt));
+
+ no->refcnt--;
+ }
+}
+
+/*
+ * Compatibility function for old ipfw(8) binaries.
+ * Rewrites table kernel indices with userland ones.
+ * Convert tables matching '/^\d+$/' to their atoi() value.
+ * Use number 65535 for other tables.
+ *
+ * Returns 0 on success.
+ */
+int
+ipfw_rewrite_table_kidx(struct ip_fw_chain *chain, struct ip_fw_rule0 *rule)
+{
+ int cmdlen, error, l;
+ ipfw_insn *cmd;
+ uint16_t kidx, uidx;
+ uint8_t type;
+ struct named_object *no;
+ struct namedobj_instance *ni;
+
+ ni = CHAIN_TO_NI(chain);
+ error = 0;
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+
+ if ((no = ipfw_objhash_lookup_kidx(ni, kidx)) == NULL)
+ return (1);
+
+ uidx = no->uidx;
+ if (no->compat == 0) {
+
+ /*
+ * We are called via legacy opcode.
+ * Save error and show table as fake number
+ * not to make ipfw(8) hang.
+ */
+ uidx = 65535;
+ error = 2;
+ }
+
+ update_table_opcode(cmd, uidx);
+ }
+
+ return (error);
+}
+
+/*
+ * Checks is opcode is referencing table of appropriate type.
+ * Adds reference count for found table if true.
+ * Rewrites user-supplied opcode values with kernel ones.
+ *
+ * Returns 0 on success and appropriate error code otherwise.
+ */
+int
+ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
+ struct rule_check_info *ci)
+{
+ int cmdlen, error, l;
+ ipfw_insn *cmd;
+ uint16_t uidx;
+ uint8_t type;
+ struct namedobj_instance *ni;
+ struct obj_idx *p, *pidx_first, *pidx_last;
+ struct tid_info ti;
+
+ ni = CHAIN_TO_NI(chain);
+
+ /*
+ * Prepare an array for storing opcode indices.
+ * Use stack allocation by default.
+ */
+ if (ci->table_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) {
+ /* Stack */
+ pidx_first = ci->obuf;
+ } else
+ pidx_first = malloc(ci->table_opcodes * sizeof(struct obj_idx),
+ M_IPFW, M_WAITOK | M_ZERO);
+
+ pidx_last = pidx_first;
+ error = 0;
+ type = 0;
+ memset(&ti, 0, sizeof(ti));
+
+ /*
+ * Use default set for looking up tables (old way) or
+ * use set rule is assigned to (new way).
+ */
+ ti.set = (V_fw_tables_sets != 0) ? ci->krule->set : 0;
+ if (ci->ctlv != NULL) {
+ ti.tlvs = (void *)(ci->ctlv + 1);
+ ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv);
+ }
+
+ /* Reference all used tables */
+ error = find_ref_rule_tables(chain, ci->krule, ci, &pidx_last, &ti);
+ if (error != 0)
+ goto free;
+
+ IPFW_UH_WLOCK(chain);
+
+ /* Perform rule rewrite */
+ l = ci->krule->cmd_len;
+ cmd = ci->krule->cmd;
+ cmdlen = 0;
+ p = pidx_first;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+ if (classify_table_opcode(cmd, &uidx, &type) != 0)
+ continue;
+ update_table_opcode(cmd, p->kidx);
+ p++;
+ }
+
+ IPFW_UH_WUNLOCK(chain);
+
+free:
+ if (pidx_first != ci->obuf)
+ free(pidx_first, M_IPFW);
+
+ return (error);
+}
+
+static struct ipfw_sopt_handler scodes[] = {
+ { IP_FW_TABLE_XCREATE, 0, HDIR_SET, create_table },
+ { IP_FW_TABLE_XDESTROY, 0, HDIR_SET, flush_table_v0 },
+ { IP_FW_TABLE_XFLUSH, 0, HDIR_SET, flush_table_v0 },
+ { IP_FW_TABLE_XMODIFY, 0, HDIR_BOTH, modify_table },
+ { IP_FW_TABLE_XINFO, 0, HDIR_GET, describe_table },
+ { IP_FW_TABLES_XLIST, 0, HDIR_GET, list_tables },
+ { IP_FW_TABLE_XLIST, 0, HDIR_GET, dump_table_v0 },
+ { IP_FW_TABLE_XLIST, 1, HDIR_GET, dump_table_v1 },
+ { IP_FW_TABLE_XADD, 0, HDIR_BOTH, manage_table_ent_v0 },
+ { IP_FW_TABLE_XADD, 1, HDIR_BOTH, manage_table_ent_v1 },
+ { IP_FW_TABLE_XDEL, 0, HDIR_BOTH, manage_table_ent_v0 },
+ { IP_FW_TABLE_XDEL, 1, HDIR_BOTH, manage_table_ent_v1 },
+ { IP_FW_TABLE_XFIND, 0, HDIR_GET, find_table_entry },
+ { IP_FW_TABLE_XSWAP, 0, HDIR_SET, swap_table },
+ { IP_FW_TABLES_ALIST, 0, HDIR_GET, list_table_algo },
+ { IP_FW_TABLE_XGETSIZE, 0, HDIR_GET, get_table_size },
+};
+
+static void
+destroy_table_locked(struct namedobj_instance *ni, struct named_object *no,
+ void *arg)
+{
+
+ unlink_table((struct ip_fw_chain *)arg, (struct table_config *)no);
+ if (ipfw_objhash_free_idx(ni, no->kidx) != 0)
+ printf("Error unlinking kidx %d from table %s\n",
+ no->kidx, no->name);
+ free_table_config(ni, (struct table_config *)no);
+}
+
+/*
+ * Shuts tables module down.
+ */
+void
+ipfw_destroy_tables(struct ip_fw_chain *ch, int last)
+{
+
+ IPFW_DEL_SOPT_HANDLER(last, scodes);
+
+ /* Remove all tables from working set */
+ IPFW_UH_WLOCK(ch);
+ IPFW_WLOCK(ch);
+ ipfw_objhash_foreach(CHAIN_TO_NI(ch), destroy_table_locked, ch);
+ IPFW_WUNLOCK(ch);
+ IPFW_UH_WUNLOCK(ch);
+
+ /* Free pointers itself */
+ free(ch->tablestate, M_IPFW);
+
+ ipfw_table_value_destroy(ch, last);
+ ipfw_table_algo_destroy(ch);
+
+ ipfw_objhash_destroy(CHAIN_TO_NI(ch));
+ free(CHAIN_TO_TCFG(ch), M_IPFW);
+}
+
+/*
+ * Starts tables module.
+ */
+int
+ipfw_init_tables(struct ip_fw_chain *ch, int first)
+{
+ struct tables_config *tcfg;
+
+ /* Allocate pointers */
+ ch->tablestate = malloc(V_fw_tables_max * sizeof(struct table_info),
+ M_IPFW, M_WAITOK | M_ZERO);
+
+ tcfg = malloc(sizeof(struct tables_config), M_IPFW, M_WAITOK | M_ZERO);
+ tcfg->namehash = ipfw_objhash_create(V_fw_tables_max);
+ ch->tblcfg = tcfg;
+
+ ipfw_table_value_init(ch, first);
+ ipfw_table_algo_init(ch);
+
+ IPFW_ADD_SOPT_HANDLER(first, scodes);
+ return (0);
+}
+
+
+
diff --git a/sys/netpfil/ipfw/ip_fw_table.h b/sys/netpfil/ipfw/ip_fw_table.h
new file mode 100644
index 0000000..028e450
--- /dev/null
+++ b/sys/netpfil/ipfw/ip_fw_table.h
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
+ *
+ * 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 _IPFW2_TABLE_H
+#define _IPFW2_TABLE_H
+
+/*
+ * Internal constants and data structures used by ipfw tables
+ * not meant to be exported outside the kernel.
+ */
+#ifdef _KERNEL
+
+struct table_algo;
+struct tables_config {
+ struct namedobj_instance *namehash;
+ struct namedobj_instance *valhash;
+ uint32_t val_size;
+ uint32_t algo_count;
+ struct table_algo *algo[256];
+ struct table_algo *def_algo[IPFW_TABLE_MAXTYPE + 1];
+ TAILQ_HEAD(op_state_l,op_state) state_list;
+};
+#define CHAIN_TO_TCFG(chain) ((struct tables_config *)(chain)->tblcfg)
+
+struct table_info {
+ table_lookup_t *lookup; /* Lookup function */
+ void *state; /* Lookup radix/other structure */
+ void *xstate; /* eXtended state */
+ u_long data; /* Hints for given func */
+};
+
+/* Internal structures for handling sockopt data */
+struct tid_info {
+ uint32_t set; /* table set */
+ uint16_t uidx; /* table index */
+ uint8_t type; /* table type */
+ uint8_t atype;
+ void *tlvs; /* Pointer to first TLV */
+ int tlen; /* Total TLV size block */
+};
+
+struct table_value;
+struct tentry_info {
+ void *paddr;
+ struct table_value *pvalue;
+ void *ptv; /* Temporary field to hold obj */
+ uint8_t masklen; /* mask length */
+ uint8_t subtype;
+ uint16_t flags; /* record flags */
+ uint32_t value; /* value index */
+};
+#define TEI_FLAGS_UPDATE 0x0001 /* Add or update rec if exists */
+#define TEI_FLAGS_UPDATED 0x0002 /* Entry has been updated */
+#define TEI_FLAGS_COMPAT 0x0004 /* Called from old ABI */
+#define TEI_FLAGS_DONTADD 0x0008 /* Do not create new rec */
+#define TEI_FLAGS_ADDED 0x0010 /* Entry was added */
+#define TEI_FLAGS_DELETED 0x0020 /* Entry was deleted */
+#define TEI_FLAGS_LIMIT 0x0040 /* Limit was hit */
+#define TEI_FLAGS_ERROR 0x0080 /* Unknown request error */
+#define TEI_FLAGS_NOTFOUND 0x0100 /* Entry was not found */
+#define TEI_FLAGS_EXISTS 0x0200 /* Entry already exists */
+
+typedef int (ta_init)(struct ip_fw_chain *ch, void **ta_state,
+ struct table_info *ti, char *data, uint8_t tflags);
+typedef void (ta_destroy)(void *ta_state, struct table_info *ti);
+typedef int (ta_prepare_add)(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf);
+typedef int (ta_prepare_del)(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf);
+typedef int (ta_add)(void *ta_state, struct table_info *ti,
+ struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
+typedef int (ta_del)(void *ta_state, struct table_info *ti,
+ struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
+typedef void (ta_flush_entry)(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf);
+
+typedef int (ta_need_modify)(void *ta_state, struct table_info *ti,
+ uint32_t count, uint64_t *pflags);
+typedef int (ta_prepare_mod)(void *ta_buf, uint64_t *pflags);
+typedef int (ta_fill_mod)(void *ta_state, struct table_info *ti,
+ void *ta_buf, uint64_t *pflags);
+typedef void (ta_modify)(void *ta_state, struct table_info *ti,
+ void *ta_buf, uint64_t pflags);
+typedef void (ta_flush_mod)(void *ta_buf);
+
+typedef void (ta_change_ti)(void *ta_state, struct table_info *ti);
+typedef void (ta_print_config)(void *ta_state, struct table_info *ti, char *buf,
+ size_t bufsize);
+
+typedef int ta_foreach_f(void *node, void *arg);
+typedef void ta_foreach(void *ta_state, struct table_info *ti, ta_foreach_f *f,
+ void *arg);
+typedef int ta_dump_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent);
+typedef int ta_find_tentry(void *ta_state, struct table_info *ti,
+ ipfw_obj_tentry *tent);
+typedef void ta_dump_tinfo(void *ta_state, struct table_info *ti,
+ ipfw_ta_tinfo *tinfo);
+typedef uint32_t ta_get_count(void *ta_state, struct table_info *ti);
+
+struct table_algo {
+ char name[16];
+ uint32_t idx;
+ uint32_t type;
+ uint32_t refcnt;
+ uint32_t flags;
+ uint32_t vlimit;
+ size_t ta_buf_size;
+ ta_init *init;
+ ta_destroy *destroy;
+ ta_prepare_add *prepare_add;
+ ta_prepare_del *prepare_del;
+ ta_add *add;
+ ta_del *del;
+ ta_flush_entry *flush_entry;
+ ta_find_tentry *find_tentry;
+ ta_need_modify *need_modify;
+ ta_prepare_mod *prepare_mod;
+ ta_fill_mod *fill_mod;
+ ta_modify *modify;
+ ta_flush_mod *flush_mod;
+ ta_change_ti *change_ti;
+ ta_foreach *foreach;
+ ta_dump_tentry *dump_tentry;
+ ta_print_config *print_config;
+ ta_dump_tinfo *dump_tinfo;
+ ta_get_count *get_count;
+};
+#define TA_FLAG_DEFAULT 0x01 /* Algo is default for given type */
+#define TA_FLAG_READONLY 0x02 /* Algo does not support modifications*/
+#define TA_FLAG_EXTCOUNTER 0x04 /* Algo has external counter available*/
+
+int ipfw_add_table_algo(struct ip_fw_chain *ch, struct table_algo *ta,
+ size_t size, int *idx);
+void ipfw_del_table_algo(struct ip_fw_chain *ch, int idx);
+
+void ipfw_table_algo_init(struct ip_fw_chain *chain);
+void ipfw_table_algo_destroy(struct ip_fw_chain *chain);
+
+MALLOC_DECLARE(M_IPFW_TBL);
+/* Exported to support legacy opcodes */
+int add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
+ struct tentry_info *tei, uint8_t flags, uint32_t count);
+int del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
+ struct tentry_info *tei, uint8_t flags, uint32_t count);
+int flush_table(struct ip_fw_chain *ch, struct tid_info *ti);
+void ipfw_import_table_value_legacy(uint32_t value, struct table_value *v);
+uint32_t ipfw_export_table_value_legacy(struct table_value *v);
+int ipfw_get_table_size(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+
+/* ipfw_table_value.c functions */
+struct table_config;
+struct tableop_state;
+void ipfw_table_value_init(struct ip_fw_chain *ch, int first);
+void ipfw_table_value_destroy(struct ip_fw_chain *ch, int last);
+int ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts);
+void ipfw_garbage_table_values(struct ip_fw_chain *ch, struct table_config *tc,
+ struct tentry_info *tei, uint32_t count, int rollback);
+void ipfw_import_table_value_v1(ipfw_table_value *iv);
+void ipfw_export_table_value_v1(struct table_value *v, ipfw_table_value *iv);
+void ipfw_unref_table_values(struct ip_fw_chain *ch, struct table_config *tc,
+ struct table_algo *ta, void *astate, struct table_info *ti);
+void rollback_table_values(struct tableop_state *ts);
+
+int ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
+ struct rule_check_info *ci);
+int ipfw_rewrite_table_kidx(struct ip_fw_chain *chain,
+ struct ip_fw_rule0 *rule);
+int ipfw_mark_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule,
+ uint32_t *bmask);
+int ipfw_export_table_ntlv(struct ip_fw_chain *ch, uint16_t kidx,
+ struct sockopt_data *sd);
+void ipfw_unref_rule_tables(struct ip_fw_chain *chain, struct ip_fw *rule);
+
+/* utility functions */
+int ipfw_check_table_name(char *name);
+int ipfw_move_tables_sets(struct ip_fw_chain *ch, ipfw_range_tlv *rt,
+ uint32_t new_set);
+void ipfw_swap_tables_sets(struct ip_fw_chain *ch, uint32_t old_set,
+ uint32_t new_set, int mv);
+int ipfw_foreach_table_tentry(struct ip_fw_chain *ch, uint16_t kidx,
+ ta_foreach_f f, void *arg);
+
+/* internal functions */
+void tc_ref(struct table_config *tc);
+void tc_unref(struct table_config *tc);
+
+struct op_state;
+typedef void (op_rollback_f)(void *object, struct op_state *state);
+struct op_state {
+ TAILQ_ENTRY(op_state) next; /* chain link */
+ op_rollback_f *func;
+};
+
+struct tableop_state {
+ struct op_state opstate;
+ struct ip_fw_chain *ch;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct tentry_info *tei;
+ uint32_t count;
+ uint32_t vmask;
+ int vshared;
+ int modified;
+};
+
+void add_toperation_state(struct ip_fw_chain *ch, struct tableop_state *ts);
+void del_toperation_state(struct ip_fw_chain *ch, struct tableop_state *ts);
+void rollback_toperation_state(struct ip_fw_chain *ch, void *object);
+
+/* Legacy interfaces */
+int ipfw_count_table(struct ip_fw_chain *ch, struct tid_info *ti,
+ uint32_t *cnt);
+int ipfw_count_xtable(struct ip_fw_chain *ch, struct tid_info *ti,
+ uint32_t *cnt);
+int ipfw_dump_table_legacy(struct ip_fw_chain *ch, struct tid_info *ti,
+ ipfw_table *tbl);
+
+
+#endif /* _KERNEL */
+#endif /* _IPFW2_TABLE_H */
diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c
new file mode 100644
index 0000000..14fd672
--- /dev/null
+++ b/sys/netpfil/ipfw/ip_fw_table_algo.c
@@ -0,0 +1,3827 @@
+/*-
+ * Copyright (c) 2014 Yandex LLC
+ * Copyright (c) 2014 Alexander V. Chernikov
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Lookup table algorithms.
+ *
+ */
+
+#include "opt_ipfw.h"
+#include "opt_inet.h"
+#ifndef INET
+#error IPFIREWALL requires INET.
+#endif /* INET */
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
+#include <sys/rmlock.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */
+#include <net/radix.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/ip_var.h> /* struct ipfw_rule_ref */
+#include <netinet/ip_fw.h>
+
+#include <netpfil/ipfw/ip_fw_private.h>
+#include <netpfil/ipfw/ip_fw_table.h>
+
+
+/*
+ * IPFW table lookup algorithms.
+ *
+ * What is needed to add another table algo?
+ *
+ * Algo init:
+ * * struct table_algo has to be filled with:
+ * name: "type:algoname" format, e.g. "addr:radix". Currently
+ * there are the following types: "addr", "iface", "number" and "flow".
+ * type: one of IPFW_TABLE_* types
+ * flags: one or more TA_FLAGS_*
+ * ta_buf_size: size of structure used to store add/del item state.
+ * Needs to be less than TA_BUF_SZ.
+ * callbacks: see below for description.
+ * * ipfw_add_table_algo / ipfw_del_table_algo has to be called
+ *
+ * Callbacks description:
+ *
+ * -init: request to initialize new table instance.
+ * typedef int (ta_init)(struct ip_fw_chain *ch, void **ta_state,
+ * struct table_info *ti, char *data, uint8_t tflags);
+ * MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
+ *
+ * Allocate all structures needed for normal operations.
+ * * Caller may want to parse @data for some algo-specific
+ * options provided by userland.
+ * * Caller may want to save configuration state pointer to @ta_state
+ * * Caller needs to save desired runtime structure pointer(s)
+ * inside @ti fields. Note that it is not correct to save
+ * @ti pointer at this moment. Use -change_ti hook for that.
+ * * Caller has to fill in ti->lookup to appropriate function
+ * pointer.
+ *
+ *
+ *
+ * -destroy: request to destroy table instance.
+ * typedef void (ta_destroy)(void *ta_state, struct table_info *ti);
+ * MANDATORY, may be locked (UH+WLOCK). (M_NOWAIT).
+ *
+ * Frees all table entries and all tables structures allocated by -init.
+ *
+ *
+ *
+ * -prepare_add: request to allocate state for adding new entry.
+ * typedef int (ta_prepare_add)(struct ip_fw_chain *ch, struct tentry_info *tei,
+ * void *ta_buf);
+ * MANDATORY, unlocked. (M_WAITOK). Returns 0 on success.
+ *
+ * Allocates state and fills it in with all necessary data (EXCEPT value)
+ * from @tei to minimize operations needed to be done under WLOCK.
+ * "value" field has to be copied to new entry in @add callback.
+ * Buffer ta_buf of size ta->ta_buf_sz may be used to store
+ * allocated state.
+ *
+ *
+ *
+ * -prepare_del: request to set state for deleting existing entry.
+ * typedef int (ta_prepare_del)(struct ip_fw_chain *ch, struct tentry_info *tei,
+ * void *ta_buf);
+ * MANDATORY, locked, UH. (M_NOWAIT). Returns 0 on success.
+ *
+ * Buffer ta_buf of size ta->ta_buf_sz may be used to store
+ * allocated state. Caller should use on-stack ta_buf allocation
+ * instead of doing malloc().
+ *
+ *
+ *
+ * -add: request to insert new entry into runtime/config structures.
+ * typedef int (ta_add)(void *ta_state, struct table_info *ti,
+ * struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
+ * MANDATORY, UH+WLOCK. (M_NOWAIT). Returns 0 on success.
+ *
+ * Insert new entry using previously-allocated state in @ta_buf.
+ * * @tei may have the following flags:
+ * TEI_FLAGS_UPDATE: request to add or update entry.
+ * TEI_FLAGS_DONTADD: request to update (but not add) entry.
+ * * Caller is required to do the following:
+ * copy real entry value from @tei
+ * entry added: return 0, set 1 to @pnum
+ * entry updated: return 0, store 0 to @pnum, store old value in @tei,
+ * add TEI_FLAGS_UPDATED flag to @tei.
+ * entry exists: return EEXIST
+ * entry not found: return ENOENT
+ * other error: return non-zero error code.
+ *
+ *
+ *
+ * -del: request to delete existing entry from runtime/config structures.
+ * typedef int (ta_del)(void *ta_state, struct table_info *ti,
+ * struct tentry_info *tei, void *ta_buf, uint32_t *pnum);
+ * MANDATORY, UH+WLOCK. (M_NOWAIT). Returns 0 on success.
+ *
+ * Delete entry using previously set up in @ta_buf.
+ * * Caller is required to do the following:
+ * entry deleted: return 0, set 1 to @pnum, store old value in @tei.
+ * entry not found: return ENOENT
+ * other error: return non-zero error code.
+ *
+ *
+ *
+ * -flush_entry: flush entry state created by -prepare_add / -del / others
+ * typedef void (ta_flush_entry)(struct ip_fw_chain *ch,
+ * struct tentry_info *tei, void *ta_buf);
+ * MANDATORY, may be locked. (M_NOWAIT).
+ *
+ * Delete state allocated by:
+ * -prepare_add (-add returned EEXIST|UPDATED)
+ * -prepare_del (if any)
+ * -del
+ * * Caller is required to handle empty @ta_buf correctly.
+ *
+ *
+ * -find_tentry: finds entry specified by key @tei
+ * typedef int ta_find_tentry(void *ta_state, struct table_info *ti,
+ * ipfw_obj_tentry *tent);
+ * OPTIONAL, locked (UH). (M_NOWAIT). Returns 0 on success.
+ *
+ * Finds entry specified by given key.
+ * * Caller is requred to do the following:
+ * entry found: returns 0, export entry to @tent
+ * entry not found: returns ENOENT
+ *
+ *
+ * -need_modify: checks if @ti has enough space to hold another @count items.
+ * typedef int (ta_need_modify)(void *ta_state, struct table_info *ti,
+ * uint32_t count, uint64_t *pflags);
+ * OPTIONAL, locked (UH). (M_NOWAIT). Returns 0 if has.
+ *
+ * Checks if given table has enough space to add @count items without
+ * resize. Caller may use @pflags to store desired modification data.
+ *
+ *
+ *
+ * -prepare_mod: allocate structures for table modification.
+ * typedef int (ta_prepare_mod)(void *ta_buf, uint64_t *pflags);
+ * OPTIONAL(need_modify), unlocked. (M_WAITOK). Returns 0 on success.
+ *
+ * Allocate all needed state for table modification. Caller
+ * should use `struct mod_item` to store new state in @ta_buf.
+ * Up to TA_BUF_SZ (128 bytes) can be stored in @ta_buf.
+ *
+ *
+ *
+ * -fill_mod: copy some data to new state/
+ * typedef int (ta_fill_mod)(void *ta_state, struct table_info *ti,
+ * void *ta_buf, uint64_t *pflags);
+ * OPTIONAL(need_modify), locked (UH). (M_NOWAIT). Returns 0 on success.
+ *
+ * Copy as much data as we can to minimize changes under WLOCK.
+ * For example, array can be merged inside this callback.
+ *
+ *
+ *
+ * -modify: perform final modification.
+ * typedef void (ta_modify)(void *ta_state, struct table_info *ti,
+ * void *ta_buf, uint64_t pflags);
+ * OPTIONAL(need_modify), locked (UH+WLOCK). (M_NOWAIT).
+ *
+ * Performs all changes necessary to switch to new structures.
+ * * Caller should save old pointers to @ta_buf storage.
+ *
+ *
+ *
+ * -flush_mod: flush table modification state.
+ * typedef void (ta_flush_mod)(void *ta_buf);
+ * OPTIONAL(need_modify), unlocked. (M_WAITOK).
+ *
+ * Performs flush for the following:
+ * - prepare_mod (modification was not necessary)
+ * - modify (for the old state)
+ *
+ *
+ *
+ * -change_gi: monitor table info pointer changes
+ * typedef void (ta_change_ti)(void *ta_state, struct table_info *ti);
+ * OPTIONAL, locked (UH). (M_NOWAIT).
+ *
+ * Called on @ti pointer changed. Called immediately after -init
+ * to set initial state.
+ *
+ *
+ *
+ * -foreach: calls @f for each table entry
+ * typedef void ta_foreach(void *ta_state, struct table_info *ti,
+ * ta_foreach_f *f, void *arg);
+ * MANDATORY, locked(UH). (M_NOWAIT).
+ *
+ * Runs callback with specified argument for each table entry,
+ * Typically used for dumping table entries.
+ *
+ *
+ *
+ * -dump_tentry: dump table entry in current @tentry format.
+ * typedef int ta_dump_tentry(void *ta_state, struct table_info *ti, void *e,
+ * ipfw_obj_tentry *tent);
+ * MANDATORY, locked(UH). (M_NOWAIT). Returns 0 on success.
+ *
+ * Dumps entry @e to @tent.
+ *
+ *
+ * -print_config: prints custom algoritm options into buffer.
+ * typedef void (ta_print_config)(void *ta_state, struct table_info *ti,
+ * char *buf, size_t bufsize);
+ * OPTIONAL. locked(UH). (M_NOWAIT).
+ *
+ * Prints custom algorithm options in the format suitable to pass
+ * back to -init callback.
+ *
+ *
+ *
+ * -dump_tinfo: dumps algo-specific info.
+ * typedef void ta_dump_tinfo(void *ta_state, struct table_info *ti,
+ * ipfw_ta_tinfo *tinfo);
+ * OPTIONAL. locked(UH). (M_NOWAIT).
+ *
+ * Dumps options like items size/hash size, etc.
+ */
+
+MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");
+
+/*
+ * Utility structures/functions common to more than one algo
+ */
+
+struct mod_item {
+ void *main_ptr;
+ size_t size;
+ void *main_ptr6;
+ size_t size6;
+};
+
+static int badd(const void *key, void *item, void *base, size_t nmemb,
+ size_t size, int (*compar) (const void *, const void *));
+static int bdel(const void *key, void *base, size_t nmemb, size_t size,
+ int (*compar) (const void *, const void *));
+
+
+/*
+ * ADDR implementation using radix
+ *
+ */
+
+/*
+ * The radix code expects addr and mask to be array of bytes,
+ * with the first byte being the length of the array. rn_inithead
+ * is called with the offset in bits of the lookup key within the
+ * array. If we use a sockaddr_in as the underlying type,
+ * sin_len is conveniently located at offset 0, sin_addr is at
+ * offset 4 and normally aligned.
+ * But for portability, let's avoid assumption and make the code explicit
+ */
+#define KEY_LEN(v) *((uint8_t *)&(v))
+/*
+ * Do not require radix to compare more than actual IPv4/IPv6 address
+ */
+#define KEY_LEN_INET (offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t))
+#define KEY_LEN_INET6 (offsetof(struct sa_in6, sin6_addr) + sizeof(struct in6_addr))
+
+#define OFF_LEN_INET (8 * offsetof(struct sockaddr_in, sin_addr))
+#define OFF_LEN_INET6 (8 * offsetof(struct sa_in6, sin6_addr))
+
+struct radix_addr_entry {
+ struct radix_node rn[2];
+ struct sockaddr_in addr;
+ uint32_t value;
+ uint8_t masklen;
+};
+
+struct sa_in6 {
+ uint8_t sin6_len;
+ uint8_t sin6_family;
+ uint8_t pad[2];
+ struct in6_addr sin6_addr;
+};
+
+struct radix_addr_xentry {
+ struct radix_node rn[2];
+ struct sa_in6 addr6;
+ uint32_t value;
+ uint8_t masklen;
+};
+
+struct radix_cfg {
+ struct radix_node_head *head4;
+ struct radix_node_head *head6;
+ size_t count4;
+ size_t count6;
+};
+
+struct ta_buf_radix
+{
+ void *ent_ptr;
+ struct sockaddr *addr_ptr;
+ struct sockaddr *mask_ptr;
+ union {
+ struct {
+ struct sockaddr_in sa;
+ struct sockaddr_in ma;
+ } a4;
+ struct {
+ struct sa_in6 sa;
+ struct sa_in6 ma;
+ } a6;
+ } addr;
+};
+
+static int
+ta_lookup_radix(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct radix_node_head *rnh;
+
+ if (keylen == sizeof(in_addr_t)) {
+ struct radix_addr_entry *ent;
+ struct sockaddr_in sa;
+ KEY_LEN(sa) = KEY_LEN_INET;
+ sa.sin_addr.s_addr = *((in_addr_t *)key);
+ rnh = (struct radix_node_head *)ti->state;
+ ent = (struct radix_addr_entry *)(rnh->rnh_matchaddr(&sa, rnh));
+ if (ent != NULL) {
+ *val = ent->value;
+ return (1);
+ }
+ } else {
+ struct radix_addr_xentry *xent;
+ struct sa_in6 sa6;
+ KEY_LEN(sa6) = KEY_LEN_INET6;
+ memcpy(&sa6.sin6_addr, key, sizeof(struct in6_addr));
+ rnh = (struct radix_node_head *)ti->xstate;
+ xent = (struct radix_addr_xentry *)(rnh->rnh_matchaddr(&sa6, rnh));
+ if (xent != NULL) {
+ *val = xent->value;
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * New table
+ */
+static int
+ta_init_radix(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
+ char *data, uint8_t tflags)
+{
+ struct radix_cfg *cfg;
+
+ if (!rn_inithead(&ti->state, OFF_LEN_INET))
+ return (ENOMEM);
+ if (!rn_inithead(&ti->xstate, OFF_LEN_INET6)) {
+ rn_detachhead(&ti->state);
+ return (ENOMEM);
+ }
+
+ cfg = malloc(sizeof(struct radix_cfg), M_IPFW, M_WAITOK | M_ZERO);
+
+ *ta_state = cfg;
+ ti->lookup = ta_lookup_radix;
+
+ return (0);
+}
+
+static int
+flush_radix_entry(struct radix_node *rn, void *arg)
+{
+ struct radix_node_head * const rnh = arg;
+ struct radix_addr_entry *ent;
+
+ ent = (struct radix_addr_entry *)
+ rnh->rnh_deladdr(rn->rn_key, rn->rn_mask, rnh);
+ if (ent != NULL)
+ free(ent, M_IPFW_TBL);
+ return (0);
+}
+
+static void
+ta_destroy_radix(void *ta_state, struct table_info *ti)
+{
+ struct radix_cfg *cfg;
+ struct radix_node_head *rnh;
+
+ cfg = (struct radix_cfg *)ta_state;
+
+ rnh = (struct radix_node_head *)(ti->state);
+ rnh->rnh_walktree(rnh, flush_radix_entry, rnh);
+ rn_detachhead(&ti->state);
+
+ rnh = (struct radix_node_head *)(ti->xstate);
+ rnh->rnh_walktree(rnh, flush_radix_entry, rnh);
+ rn_detachhead(&ti->xstate);
+
+ free(cfg, M_IPFW);
+}
+
+/*
+ * Provide algo-specific table info
+ */
+static void
+ta_dump_radix_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
+{
+ struct radix_cfg *cfg;
+
+ cfg = (struct radix_cfg *)ta_state;
+
+ tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM;
+ tinfo->taclass4 = IPFW_TACLASS_RADIX;
+ tinfo->count4 = cfg->count4;
+ tinfo->itemsize4 = sizeof(struct radix_addr_entry);
+ tinfo->taclass6 = IPFW_TACLASS_RADIX;
+ tinfo->count6 = cfg->count6;
+ tinfo->itemsize6 = sizeof(struct radix_addr_xentry);
+}
+
+static int
+ta_dump_radix_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
+{
+ struct radix_addr_entry *n;
+ struct radix_addr_xentry *xn;
+
+ n = (struct radix_addr_entry *)e;
+
+ /* Guess IPv4/IPv6 radix by sockaddr family */
+ if (n->addr.sin_family == AF_INET) {
+ tent->k.addr.s_addr = n->addr.sin_addr.s_addr;
+ tent->masklen = n->masklen;
+ tent->subtype = AF_INET;
+ tent->v.kidx = n->value;
+#ifdef INET6
+ } else {
+ xn = (struct radix_addr_xentry *)e;
+ memcpy(&tent->k, &xn->addr6.sin6_addr, sizeof(struct in6_addr));
+ tent->masklen = xn->masklen;
+ tent->subtype = AF_INET6;
+ tent->v.kidx = xn->value;
+#endif
+ }
+
+ return (0);
+}
+
+static int
+ta_find_radix_tentry(void *ta_state, struct table_info *ti,
+ ipfw_obj_tentry *tent)
+{
+ struct radix_node_head *rnh;
+ void *e;
+
+ e = NULL;
+ if (tent->subtype == AF_INET) {
+ struct sockaddr_in sa;
+ KEY_LEN(sa) = KEY_LEN_INET;
+ sa.sin_addr.s_addr = tent->k.addr.s_addr;
+ rnh = (struct radix_node_head *)ti->state;
+ e = rnh->rnh_matchaddr(&sa, rnh);
+ } else {
+ struct sa_in6 sa6;
+ KEY_LEN(sa6) = KEY_LEN_INET6;
+ memcpy(&sa6.sin6_addr, &tent->k.addr6, sizeof(struct in6_addr));
+ rnh = (struct radix_node_head *)ti->xstate;
+ e = rnh->rnh_matchaddr(&sa6, rnh);
+ }
+
+ if (e != NULL) {
+ ta_dump_radix_tentry(ta_state, ti, e, tent);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static void
+ta_foreach_radix(void *ta_state, struct table_info *ti, ta_foreach_f *f,
+ void *arg)
+{
+ struct radix_node_head *rnh;
+
+ rnh = (struct radix_node_head *)(ti->state);
+ rnh->rnh_walktree(rnh, (walktree_f_t *)f, arg);
+
+ rnh = (struct radix_node_head *)(ti->xstate);
+ rnh->rnh_walktree(rnh, (walktree_f_t *)f, arg);
+}
+
+
+#ifdef INET6
+static inline void
+ipv6_writemask(struct in6_addr *addr6, uint8_t mask)
+{
+ uint32_t *cp;
+
+ for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32)
+ *cp++ = 0xFFFFFFFF;
+ *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
+}
+#endif
+
+static void
+tei_to_sockaddr_ent(struct tentry_info *tei, struct sockaddr *sa,
+ struct sockaddr *ma, int *set_mask)
+{
+ int mlen;
+ struct sockaddr_in *addr, *mask;
+ struct sa_in6 *addr6, *mask6;
+ in_addr_t a4;
+
+ mlen = tei->masklen;
+
+ if (tei->subtype == AF_INET) {
+#ifdef INET
+ addr = (struct sockaddr_in *)sa;
+ mask = (struct sockaddr_in *)ma;
+ /* Set 'total' structure length */
+ KEY_LEN(*addr) = KEY_LEN_INET;
+ KEY_LEN(*mask) = KEY_LEN_INET;
+ addr->sin_family = AF_INET;
+ mask->sin_addr.s_addr =
+ htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
+ a4 = *((in_addr_t *)tei->paddr);
+ addr->sin_addr.s_addr = a4 & mask->sin_addr.s_addr;
+ if (mlen != 32)
+ *set_mask = 1;
+ else
+ *set_mask = 0;
+#endif
+#ifdef INET6
+ } else if (tei->subtype == AF_INET6) {
+ /* IPv6 case */
+ addr6 = (struct sa_in6 *)sa;
+ mask6 = (struct sa_in6 *)ma;
+ /* Set 'total' structure length */
+ KEY_LEN(*addr6) = KEY_LEN_INET6;
+ KEY_LEN(*mask6) = KEY_LEN_INET6;
+ addr6->sin6_family = AF_INET6;
+ ipv6_writemask(&mask6->sin6_addr, mlen);
+ memcpy(&addr6->sin6_addr, tei->paddr, sizeof(struct in6_addr));
+ APPLY_MASK(&addr6->sin6_addr, &mask6->sin6_addr);
+ if (mlen != 128)
+ *set_mask = 1;
+ else
+ *set_mask = 0;
+ }
+#endif
+}
+
+static int
+ta_prepare_add_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_radix *tb;
+ struct radix_addr_entry *ent;
+ struct radix_addr_xentry *xent;
+ struct sockaddr *addr, *mask;
+ int mlen, set_mask;
+
+ tb = (struct ta_buf_radix *)ta_buf;
+
+ mlen = tei->masklen;
+ set_mask = 0;
+
+ if (tei->subtype == AF_INET) {
+#ifdef INET
+ if (mlen > 32)
+ return (EINVAL);
+ ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
+ ent->masklen = mlen;
+
+ addr = (struct sockaddr *)&ent->addr;
+ mask = (struct sockaddr *)&tb->addr.a4.ma;
+ tb->ent_ptr = ent;
+#endif
+#ifdef INET6
+ } else if (tei->subtype == AF_INET6) {
+ /* IPv6 case */
+ if (mlen > 128)
+ return (EINVAL);
+ xent = malloc(sizeof(*xent), M_IPFW_TBL, M_WAITOK | M_ZERO);
+ xent->masklen = mlen;
+
+ addr = (struct sockaddr *)&xent->addr6;
+ mask = (struct sockaddr *)&tb->addr.a6.ma;
+ tb->ent_ptr = xent;
+#endif
+ } else {
+ /* Unknown CIDR type */
+ return (EINVAL);
+ }
+
+ tei_to_sockaddr_ent(tei, addr, mask, &set_mask);
+ /* Set pointers */
+ tb->addr_ptr = addr;
+ if (set_mask != 0)
+ tb->mask_ptr = mask;
+
+ return (0);
+}
+
+static int
+ta_add_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct radix_cfg *cfg;
+ struct radix_node_head *rnh;
+ struct radix_node *rn;
+ struct ta_buf_radix *tb;
+ uint32_t *old_value, value;
+
+ cfg = (struct radix_cfg *)ta_state;
+ tb = (struct ta_buf_radix *)ta_buf;
+
+ /* Save current entry value from @tei */
+ if (tei->subtype == AF_INET) {
+ rnh = ti->state;
+ ((struct radix_addr_entry *)tb->ent_ptr)->value = tei->value;
+ } else {
+ rnh = ti->xstate;
+ ((struct radix_addr_xentry *)tb->ent_ptr)->value = tei->value;
+ }
+
+ /* Search for an entry first */
+ rn = rnh->rnh_lookup(tb->addr_ptr, tb->mask_ptr, rnh);
+ if (rn != NULL) {
+ if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
+ return (EEXIST);
+ /* Record already exists. Update value if we're asked to */
+ if (tei->subtype == AF_INET)
+ old_value = &((struct radix_addr_entry *)rn)->value;
+ else
+ old_value = &((struct radix_addr_xentry *)rn)->value;
+
+ value = *old_value;
+ *old_value = tei->value;
+ tei->value = value;
+
+ /* Indicate that update has happened instead of addition */
+ tei->flags |= TEI_FLAGS_UPDATED;
+ *pnum = 0;
+
+ return (0);
+ }
+
+ if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
+ return (EFBIG);
+
+ rn = rnh->rnh_addaddr(tb->addr_ptr, tb->mask_ptr, rnh, tb->ent_ptr);
+ if (rn == NULL) {
+ /* Unknown error */
+ return (EINVAL);
+ }
+
+ if (tei->subtype == AF_INET)
+ cfg->count4++;
+ else
+ cfg->count6++;
+ tb->ent_ptr = NULL;
+ *pnum = 1;
+
+ return (0);
+}
+
+static int
+ta_prepare_del_radix(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_radix *tb;
+ struct sockaddr *addr, *mask;
+ int mlen, set_mask;
+
+ tb = (struct ta_buf_radix *)ta_buf;
+
+ mlen = tei->masklen;
+ set_mask = 0;
+
+ if (tei->subtype == AF_INET) {
+ if (mlen > 32)
+ return (EINVAL);
+
+ addr = (struct sockaddr *)&tb->addr.a4.sa;
+ mask = (struct sockaddr *)&tb->addr.a4.ma;
+#ifdef INET6
+ } else if (tei->subtype == AF_INET6) {
+ if (mlen > 128)
+ return (EINVAL);
+
+ addr = (struct sockaddr *)&tb->addr.a6.sa;
+ mask = (struct sockaddr *)&tb->addr.a6.ma;
+#endif
+ } else
+ return (EINVAL);
+
+ tei_to_sockaddr_ent(tei, addr, mask, &set_mask);
+ tb->addr_ptr = addr;
+ if (set_mask != 0)
+ tb->mask_ptr = mask;
+
+ return (0);
+}
+
+static int
+ta_del_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct radix_cfg *cfg;
+ struct radix_node_head *rnh;
+ struct radix_node *rn;
+ struct ta_buf_radix *tb;
+
+ cfg = (struct radix_cfg *)ta_state;
+ tb = (struct ta_buf_radix *)ta_buf;
+
+ if (tei->subtype == AF_INET)
+ rnh = ti->state;
+ else
+ rnh = ti->xstate;
+
+ rn = rnh->rnh_deladdr(tb->addr_ptr, tb->mask_ptr, rnh);
+
+ if (rn == NULL)
+ return (ENOENT);
+
+ /* Save entry value to @tei */
+ if (tei->subtype == AF_INET)
+ tei->value = ((struct radix_addr_entry *)rn)->value;
+ else
+ tei->value = ((struct radix_addr_xentry *)rn)->value;
+
+ tb->ent_ptr = rn;
+
+ if (tei->subtype == AF_INET)
+ cfg->count4--;
+ else
+ cfg->count6--;
+ *pnum = 1;
+
+ return (0);
+}
+
+static void
+ta_flush_radix_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_radix *tb;
+
+ tb = (struct ta_buf_radix *)ta_buf;
+
+ if (tb->ent_ptr != NULL)
+ free(tb->ent_ptr, M_IPFW_TBL);
+}
+
+static int
+ta_need_modify_radix(void *ta_state, struct table_info *ti, uint32_t count,
+ uint64_t *pflags)
+{
+
+ /*
+ * radix does not require additional memory allocations
+ * other than nodes itself. Adding new masks to the tree do
+ * but we don't have any API to call (and we don't known which
+ * sizes do we need).
+ */
+ return (0);
+}
+
+struct table_algo addr_radix = {
+ .name = "addr:radix",
+ .type = IPFW_TABLE_ADDR,
+ .flags = TA_FLAG_DEFAULT,
+ .ta_buf_size = sizeof(struct ta_buf_radix),
+ .init = ta_init_radix,
+ .destroy = ta_destroy_radix,
+ .prepare_add = ta_prepare_add_radix,
+ .prepare_del = ta_prepare_del_radix,
+ .add = ta_add_radix,
+ .del = ta_del_radix,
+ .flush_entry = ta_flush_radix_entry,
+ .foreach = ta_foreach_radix,
+ .dump_tentry = ta_dump_radix_tentry,
+ .find_tentry = ta_find_radix_tentry,
+ .dump_tinfo = ta_dump_radix_tinfo,
+ .need_modify = ta_need_modify_radix,
+};
+
+
+/*
+ * addr:hash cmds
+ *
+ *
+ * ti->data:
+ * [inv.mask4][inv.mask6][log2hsize4][log2hsize6]
+ * [ 8][ 8[ 8][ 8]
+ *
+ * inv.mask4: 32 - mask
+ * inv.mask6:
+ * 1) _slow lookup: mask
+ * 2) _aligned: (128 - mask) / 8
+ * 3) _64: 8
+ *
+ *
+ * pflags:
+ * [v4=1/v6=0][hsize]
+ * [ 32][ 32]
+ */
+
+struct chashentry;
+
+SLIST_HEAD(chashbhead, chashentry);
+
+struct chash_cfg {
+ struct chashbhead *head4;
+ struct chashbhead *head6;
+ size_t size4;
+ size_t size6;
+ size_t items4;
+ size_t items6;
+ uint8_t mask4;
+ uint8_t mask6;
+};
+
+struct chashentry {
+ SLIST_ENTRY(chashentry) next;
+ uint32_t value;
+ uint32_t type;
+ union {
+ uint32_t a4; /* Host format */
+ struct in6_addr a6; /* Network format */
+ } a;
+};
+
+struct ta_buf_chash
+{
+ void *ent_ptr;
+ struct chashentry ent;
+};
+
+
+static __inline uint32_t
+hash_ip(uint32_t addr, int hsize)
+{
+
+ return (addr % (hsize - 1));
+}
+
+static __inline uint32_t
+hash_ip6(struct in6_addr *addr6, int hsize)
+{
+ uint32_t i;
+
+ i = addr6->s6_addr32[0] ^ addr6->s6_addr32[1] ^
+ addr6->s6_addr32[2] ^ addr6->s6_addr32[3];
+
+ return (i % (hsize - 1));
+}
+
+
+static __inline uint16_t
+hash_ip64(struct in6_addr *addr6, int hsize)
+{
+ uint32_t i;
+
+ i = addr6->s6_addr32[0] ^ addr6->s6_addr32[1];
+
+ return (i % (hsize - 1));
+}
+
+
+static __inline uint32_t
+hash_ip6_slow(struct in6_addr *addr6, void *key, int mask, int hsize)
+{
+ struct in6_addr mask6;
+
+ ipv6_writemask(&mask6, mask);
+ memcpy(addr6, key, sizeof(struct in6_addr));
+ APPLY_MASK(addr6, &mask6);
+ return (hash_ip6(addr6, hsize));
+}
+
+static __inline uint32_t
+hash_ip6_al(struct in6_addr *addr6, void *key, int mask, int hsize)
+{
+ uint64_t *paddr;
+
+ paddr = (uint64_t *)addr6;
+ *paddr = 0;
+ *(paddr + 1) = 0;
+ memcpy(addr6, key, mask);
+ return (hash_ip6(addr6, hsize));
+}
+
+static int
+ta_lookup_chash_slow(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct chashbhead *head;
+ struct chashentry *ent;
+ uint16_t hash, hsize;
+ uint8_t imask;
+
+ if (keylen == sizeof(in_addr_t)) {
+ head = (struct chashbhead *)ti->state;
+ imask = ti->data >> 24;
+ hsize = 1 << ((ti->data & 0xFFFF) >> 8);
+ uint32_t a;
+ a = ntohl(*((in_addr_t *)key));
+ a = a >> imask;
+ hash = hash_ip(a, hsize);
+ SLIST_FOREACH(ent, &head[hash], next) {
+ if (ent->a.a4 == a) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ } else {
+ /* IPv6: worst scenario: non-round mask */
+ struct in6_addr addr6;
+ head = (struct chashbhead *)ti->xstate;
+ imask = (ti->data & 0xFF0000) >> 16;
+ hsize = 1 << (ti->data & 0xFF);
+ hash = hash_ip6_slow(&addr6, key, imask, hsize);
+ SLIST_FOREACH(ent, &head[hash], next) {
+ if (memcmp(&ent->a.a6, &addr6, 16) == 0) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+ta_lookup_chash_aligned(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct chashbhead *head;
+ struct chashentry *ent;
+ uint16_t hash, hsize;
+ uint8_t imask;
+
+ if (keylen == sizeof(in_addr_t)) {
+ head = (struct chashbhead *)ti->state;
+ imask = ti->data >> 24;
+ hsize = 1 << ((ti->data & 0xFFFF) >> 8);
+ uint32_t a;
+ a = ntohl(*((in_addr_t *)key));
+ a = a >> imask;
+ hash = hash_ip(a, hsize);
+ SLIST_FOREACH(ent, &head[hash], next) {
+ if (ent->a.a4 == a) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ } else {
+ /* IPv6: aligned to 8bit mask */
+ struct in6_addr addr6;
+ uint64_t *paddr, *ptmp;
+ head = (struct chashbhead *)ti->xstate;
+ imask = (ti->data & 0xFF0000) >> 16;
+ hsize = 1 << (ti->data & 0xFF);
+
+ hash = hash_ip6_al(&addr6, key, imask, hsize);
+ paddr = (uint64_t *)&addr6;
+ SLIST_FOREACH(ent, &head[hash], next) {
+ ptmp = (uint64_t *)&ent->a.a6;
+ if (paddr[0] == ptmp[0] && paddr[1] == ptmp[1]) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+ta_lookup_chash_64(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct chashbhead *head;
+ struct chashentry *ent;
+ uint16_t hash, hsize;
+ uint8_t imask;
+
+ if (keylen == sizeof(in_addr_t)) {
+ head = (struct chashbhead *)ti->state;
+ imask = ti->data >> 24;
+ hsize = 1 << ((ti->data & 0xFFFF) >> 8);
+ uint32_t a;
+ a = ntohl(*((in_addr_t *)key));
+ a = a >> imask;
+ hash = hash_ip(a, hsize);
+ SLIST_FOREACH(ent, &head[hash], next) {
+ if (ent->a.a4 == a) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ } else {
+ /* IPv6: /64 */
+ uint64_t a6, *paddr;
+ head = (struct chashbhead *)ti->xstate;
+ paddr = (uint64_t *)key;
+ hsize = 1 << (ti->data & 0xFF);
+ a6 = *paddr;
+ hash = hash_ip64((struct in6_addr *)key, hsize);
+ SLIST_FOREACH(ent, &head[hash], next) {
+ paddr = (uint64_t *)&ent->a.a6;
+ if (a6 == *paddr) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+chash_parse_opts(struct chash_cfg *cfg, char *data)
+{
+ char *pdel, *pend, *s;
+ int mask4, mask6;
+
+ mask4 = cfg->mask4;
+ mask6 = cfg->mask6;
+
+ if (data == NULL)
+ return (0);
+ if ((pdel = strchr(data, ' ')) == NULL)
+ return (0);
+ while (*pdel == ' ')
+ pdel++;
+ if (strncmp(pdel, "masks=", 6) != 0)
+ return (EINVAL);
+ if ((s = strchr(pdel, ' ')) != NULL)
+ *s++ = '\0';
+
+ pdel += 6;
+ /* Need /XX[,/YY] */
+ if (*pdel++ != '/')
+ return (EINVAL);
+ mask4 = strtol(pdel, &pend, 10);
+ if (*pend == ',') {
+ /* ,/YY */
+ pdel = pend + 1;
+ if (*pdel++ != '/')
+ return (EINVAL);
+ mask6 = strtol(pdel, &pend, 10);
+ if (*pend != '\0')
+ return (EINVAL);
+ } else if (*pend != '\0')
+ return (EINVAL);
+
+ if (mask4 < 0 || mask4 > 32 || mask6 < 0 || mask6 > 128)
+ return (EINVAL);
+
+ cfg->mask4 = mask4;
+ cfg->mask6 = mask6;
+
+ return (0);
+}
+
+static void
+ta_print_chash_config(void *ta_state, struct table_info *ti, char *buf,
+ size_t bufsize)
+{
+ struct chash_cfg *cfg;
+
+ cfg = (struct chash_cfg *)ta_state;
+
+ if (cfg->mask4 != 32 || cfg->mask6 != 128)
+ snprintf(buf, bufsize, "%s masks=/%d,/%d", "addr:hash",
+ cfg->mask4, cfg->mask6);
+ else
+ snprintf(buf, bufsize, "%s", "addr:hash");
+}
+
+static int
+log2(uint32_t v)
+{
+ uint32_t r;
+
+ r = 0;
+ while (v >>= 1)
+ r++;
+
+ return (r);
+}
+
+/*
+ * New table.
+ * We assume 'data' to be either NULL or the following format:
+ * 'addr:hash [masks=/32[,/128]]'
+ */
+static int
+ta_init_chash(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
+ char *data, uint8_t tflags)
+{
+ int error, i;
+ uint32_t hsize;
+ struct chash_cfg *cfg;
+
+ cfg = malloc(sizeof(struct chash_cfg), M_IPFW, M_WAITOK | M_ZERO);
+
+ cfg->mask4 = 32;
+ cfg->mask6 = 128;
+
+ if ((error = chash_parse_opts(cfg, data)) != 0) {
+ free(cfg, M_IPFW);
+ return (error);
+ }
+
+ cfg->size4 = 128;
+ cfg->size6 = 128;
+
+ cfg->head4 = malloc(sizeof(struct chashbhead) * cfg->size4, M_IPFW,
+ M_WAITOK | M_ZERO);
+ cfg->head6 = malloc(sizeof(struct chashbhead) * cfg->size6, M_IPFW,
+ M_WAITOK | M_ZERO);
+ for (i = 0; i < cfg->size4; i++)
+ SLIST_INIT(&cfg->head4[i]);
+ for (i = 0; i < cfg->size6; i++)
+ SLIST_INIT(&cfg->head6[i]);
+
+
+ *ta_state = cfg;
+ ti->state = cfg->head4;
+ ti->xstate = cfg->head6;
+
+ /* Store data depending on v6 mask length */
+ hsize = log2(cfg->size4) << 8 | log2(cfg->size6);
+ if (cfg->mask6 == 64) {
+ ti->data = (32 - cfg->mask4) << 24 | (128 - cfg->mask6) << 16|
+ hsize;
+ ti->lookup = ta_lookup_chash_64;
+ } else if ((cfg->mask6 % 8) == 0) {
+ ti->data = (32 - cfg->mask4) << 24 |
+ cfg->mask6 << 13 | hsize;
+ ti->lookup = ta_lookup_chash_aligned;
+ } else {
+ /* don't do that! */
+ ti->data = (32 - cfg->mask4) << 24 |
+ cfg->mask6 << 16 | hsize;
+ ti->lookup = ta_lookup_chash_slow;
+ }
+
+ return (0);
+}
+
+static void
+ta_destroy_chash(void *ta_state, struct table_info *ti)
+{
+ struct chash_cfg *cfg;
+ struct chashentry *ent, *ent_next;
+ int i;
+
+ cfg = (struct chash_cfg *)ta_state;
+
+ for (i = 0; i < cfg->size4; i++)
+ SLIST_FOREACH_SAFE(ent, &cfg->head4[i], next, ent_next)
+ free(ent, M_IPFW_TBL);
+
+ for (i = 0; i < cfg->size6; i++)
+ SLIST_FOREACH_SAFE(ent, &cfg->head6[i], next, ent_next)
+ free(ent, M_IPFW_TBL);
+
+ free(cfg->head4, M_IPFW);
+ free(cfg->head6, M_IPFW);
+
+ free(cfg, M_IPFW);
+}
+
+static void
+ta_dump_chash_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
+{
+ struct chash_cfg *cfg;
+
+ cfg = (struct chash_cfg *)ta_state;
+
+ tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM;
+ tinfo->taclass4 = IPFW_TACLASS_HASH;
+ tinfo->size4 = cfg->size4;
+ tinfo->count4 = cfg->items4;
+ tinfo->itemsize4 = sizeof(struct chashentry);
+ tinfo->taclass6 = IPFW_TACLASS_HASH;
+ tinfo->size6 = cfg->size6;
+ tinfo->count6 = cfg->items6;
+ tinfo->itemsize6 = sizeof(struct chashentry);
+}
+
+static int
+ta_dump_chash_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
+{
+ struct chash_cfg *cfg;
+ struct chashentry *ent;
+
+ cfg = (struct chash_cfg *)ta_state;
+ ent = (struct chashentry *)e;
+
+ if (ent->type == AF_INET) {
+ tent->k.addr.s_addr = htonl(ent->a.a4 << (32 - cfg->mask4));
+ tent->masklen = cfg->mask4;
+ tent->subtype = AF_INET;
+ tent->v.kidx = ent->value;
+#ifdef INET6
+ } else {
+ memcpy(&tent->k, &ent->a.a6, sizeof(struct in6_addr));
+ tent->masklen = cfg->mask6;
+ tent->subtype = AF_INET6;
+ tent->v.kidx = ent->value;
+#endif
+ }
+
+ return (0);
+}
+
+static uint32_t
+hash_ent(struct chashentry *ent, int af, int mlen, uint32_t size)
+{
+ uint32_t hash;
+
+ if (af == AF_INET) {
+ hash = hash_ip(ent->a.a4, size);
+ } else {
+ if (mlen == 64)
+ hash = hash_ip64(&ent->a.a6, size);
+ else
+ hash = hash_ip6(&ent->a.a6, size);
+ }
+
+ return (hash);
+}
+
+static int
+tei_to_chash_ent(struct tentry_info *tei, struct chashentry *ent)
+{
+ struct in6_addr mask6;
+ int mlen;
+
+
+ mlen = tei->masklen;
+
+ if (tei->subtype == AF_INET) {
+#ifdef INET
+ if (mlen > 32)
+ return (EINVAL);
+ ent->type = AF_INET;
+
+ /* Calculate masked address */
+ ent->a.a4 = ntohl(*((in_addr_t *)tei->paddr)) >> (32 - mlen);
+#endif
+#ifdef INET6
+ } else if (tei->subtype == AF_INET6) {
+ /* IPv6 case */
+ if (mlen > 128)
+ return (EINVAL);
+ ent->type = AF_INET6;
+
+ ipv6_writemask(&mask6, mlen);
+ memcpy(&ent->a.a6, tei->paddr, sizeof(struct in6_addr));
+ APPLY_MASK(&ent->a.a6, &mask6);
+#endif
+ } else {
+ /* Unknown CIDR type */
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+ta_find_chash_tentry(void *ta_state, struct table_info *ti,
+ ipfw_obj_tentry *tent)
+{
+ struct chash_cfg *cfg;
+ struct chashbhead *head;
+ struct chashentry ent, *tmp;
+ struct tentry_info tei;
+ int error;
+ uint32_t hash;
+
+ cfg = (struct chash_cfg *)ta_state;
+
+ memset(&ent, 0, sizeof(ent));
+ memset(&tei, 0, sizeof(tei));
+
+ if (tent->subtype == AF_INET) {
+ tei.paddr = &tent->k.addr;
+ tei.masklen = cfg->mask4;
+ tei.subtype = AF_INET;
+
+ if ((error = tei_to_chash_ent(&tei, &ent)) != 0)
+ return (error);
+
+ head = cfg->head4;
+ hash = hash_ent(&ent, AF_INET, cfg->mask4, cfg->size4);
+ /* Check for existence */
+ SLIST_FOREACH(tmp, &head[hash], next) {
+ if (tmp->a.a4 != ent.a.a4)
+ continue;
+
+ ta_dump_chash_tentry(ta_state, ti, tmp, tent);
+ return (0);
+ }
+ } else {
+ tei.paddr = &tent->k.addr6;
+ tei.masklen = cfg->mask6;
+ tei.subtype = AF_INET6;
+
+ if ((error = tei_to_chash_ent(&tei, &ent)) != 0)
+ return (error);
+
+ head = cfg->head6;
+ hash = hash_ent(&ent, AF_INET6, cfg->mask6, cfg->size6);
+ /* Check for existence */
+ SLIST_FOREACH(tmp, &head[hash], next) {
+ if (memcmp(&tmp->a.a6, &ent.a.a6, 16) != 0)
+ continue;
+ ta_dump_chash_tentry(ta_state, ti, tmp, tent);
+ return (0);
+ }
+ }
+
+ return (ENOENT);
+}
+
+static void
+ta_foreach_chash(void *ta_state, struct table_info *ti, ta_foreach_f *f,
+ void *arg)
+{
+ struct chash_cfg *cfg;
+ struct chashentry *ent, *ent_next;
+ int i;
+
+ cfg = (struct chash_cfg *)ta_state;
+
+ for (i = 0; i < cfg->size4; i++)
+ SLIST_FOREACH_SAFE(ent, &cfg->head4[i], next, ent_next)
+ f(ent, arg);
+
+ for (i = 0; i < cfg->size6; i++)
+ SLIST_FOREACH_SAFE(ent, &cfg->head6[i], next, ent_next)
+ f(ent, arg);
+}
+
+static int
+ta_prepare_add_chash(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_chash *tb;
+ struct chashentry *ent;
+ int error;
+
+ tb = (struct ta_buf_chash *)ta_buf;
+
+ ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO);
+
+ error = tei_to_chash_ent(tei, ent);
+ if (error != 0) {
+ free(ent, M_IPFW_TBL);
+ return (error);
+ }
+ tb->ent_ptr = ent;
+
+ return (0);
+}
+
+static int
+ta_add_chash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct chash_cfg *cfg;
+ struct chashbhead *head;
+ struct chashentry *ent, *tmp;
+ struct ta_buf_chash *tb;
+ int exists;
+ uint32_t hash, value;
+
+ cfg = (struct chash_cfg *)ta_state;
+ tb = (struct ta_buf_chash *)ta_buf;
+ ent = (struct chashentry *)tb->ent_ptr;
+ hash = 0;
+ exists = 0;
+
+ /* Read current value from @tei */
+ ent->value = tei->value;
+
+ /* Read cuurrent value */
+ if (tei->subtype == AF_INET) {
+ if (tei->masklen != cfg->mask4)
+ return (EINVAL);
+ head = cfg->head4;
+ hash = hash_ent(ent, AF_INET, cfg->mask4, cfg->size4);
+
+ /* Check for existence */
+ SLIST_FOREACH(tmp, &head[hash], next) {
+ if (tmp->a.a4 == ent->a.a4) {
+ exists = 1;
+ break;
+ }
+ }
+ } else {
+ if (tei->masklen != cfg->mask6)
+ return (EINVAL);
+ head = cfg->head6;
+ hash = hash_ent(ent, AF_INET6, cfg->mask6, cfg->size6);
+ /* Check for existence */
+ SLIST_FOREACH(tmp, &head[hash], next) {
+ if (memcmp(&tmp->a.a6, &ent->a.a6, 16) == 0) {
+ exists = 1;
+ break;
+ }
+ }
+ }
+
+ if (exists == 1) {
+ if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
+ return (EEXIST);
+ /* Record already exists. Update value if we're asked to */
+ value = tmp->value;
+ tmp->value = tei->value;
+ tei->value = value;
+ /* Indicate that update has happened instead of addition */
+ tei->flags |= TEI_FLAGS_UPDATED;
+ *pnum = 0;
+ } else {
+ if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
+ return (EFBIG);
+ SLIST_INSERT_HEAD(&head[hash], ent, next);
+ tb->ent_ptr = NULL;
+ *pnum = 1;
+
+ /* Update counters */
+ if (tei->subtype == AF_INET)
+ cfg->items4++;
+ else
+ cfg->items6++;
+ }
+
+ return (0);
+}
+
+static int
+ta_prepare_del_chash(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_chash *tb;
+
+ tb = (struct ta_buf_chash *)ta_buf;
+
+ return (tei_to_chash_ent(tei, &tb->ent));
+}
+
+static int
+ta_del_chash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct chash_cfg *cfg;
+ struct chashbhead *head;
+ struct chashentry *tmp, *tmp_next, *ent;
+ struct ta_buf_chash *tb;
+ uint32_t hash;
+
+ cfg = (struct chash_cfg *)ta_state;
+ tb = (struct ta_buf_chash *)ta_buf;
+ ent = &tb->ent;
+
+ if (tei->subtype == AF_INET) {
+ if (tei->masklen != cfg->mask4)
+ return (EINVAL);
+ head = cfg->head4;
+ hash = hash_ent(ent, AF_INET, cfg->mask4, cfg->size4);
+
+ SLIST_FOREACH_SAFE(tmp, &head[hash], next, tmp_next) {
+ if (tmp->a.a4 != ent->a.a4)
+ continue;
+
+ SLIST_REMOVE(&head[hash], tmp, chashentry, next);
+ cfg->items4--;
+ tb->ent_ptr = tmp;
+ tei->value = tmp->value;
+ *pnum = 1;
+ return (0);
+ }
+ } else {
+ if (tei->masklen != cfg->mask6)
+ return (EINVAL);
+ head = cfg->head6;
+ hash = hash_ent(ent, AF_INET6, cfg->mask6, cfg->size6);
+ SLIST_FOREACH_SAFE(tmp, &head[hash], next, tmp_next) {
+ if (memcmp(&tmp->a.a6, &ent->a.a6, 16) != 0)
+ continue;
+
+ SLIST_REMOVE(&head[hash], tmp, chashentry, next);
+ cfg->items6--;
+ tb->ent_ptr = tmp;
+ tei->value = tmp->value;
+ *pnum = 1;
+ return (0);
+ }
+ }
+
+ return (ENOENT);
+}
+
+static void
+ta_flush_chash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_chash *tb;
+
+ tb = (struct ta_buf_chash *)ta_buf;
+
+ if (tb->ent_ptr != NULL)
+ free(tb->ent_ptr, M_IPFW_TBL);
+}
+
+/*
+ * Hash growing callbacks.
+ */
+
+static int
+ta_need_modify_chash(void *ta_state, struct table_info *ti, uint32_t count,
+ uint64_t *pflags)
+{
+ struct chash_cfg *cfg;
+ uint64_t data;
+
+ /*
+ * Since we don't know exact number of IPv4/IPv6 records in @count,
+ * ignore non-zero @count value at all. Check current hash sizes
+ * and return appropriate data.
+ */
+
+ cfg = (struct chash_cfg *)ta_state;
+
+ data = 0;
+ if (cfg->items4 > cfg->size4 && cfg->size4 < 65536)
+ data |= (cfg->size4 * 2) << 16;
+ if (cfg->items6 > cfg->size6 && cfg->size6 < 65536)
+ data |= cfg->size6 * 2;
+
+ if (data != 0) {
+ *pflags = data;
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Allocate new, larger chash.
+ */
+static int
+ta_prepare_mod_chash(void *ta_buf, uint64_t *pflags)
+{
+ struct mod_item *mi;
+ struct chashbhead *head;
+ int i;
+
+ mi = (struct mod_item *)ta_buf;
+
+ memset(mi, 0, sizeof(struct mod_item));
+ mi->size = (*pflags >> 16) & 0xFFFF;
+ mi->size6 = *pflags & 0xFFFF;
+ if (mi->size > 0) {
+ head = malloc(sizeof(struct chashbhead) * mi->size,
+ M_IPFW, M_WAITOK | M_ZERO);
+ for (i = 0; i < mi->size; i++)
+ SLIST_INIT(&head[i]);
+ mi->main_ptr = head;
+ }
+
+ if (mi->size6 > 0) {
+ head = malloc(sizeof(struct chashbhead) * mi->size6,
+ M_IPFW, M_WAITOK | M_ZERO);
+ for (i = 0; i < mi->size6; i++)
+ SLIST_INIT(&head[i]);
+ mi->main_ptr6 = head;
+ }
+
+ return (0);
+}
+
+/*
+ * Copy data from old runtime array to new one.
+ */
+static int
+ta_fill_mod_chash(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t *pflags)
+{
+
+ /* In is not possible to do rehash if we're not holidng WLOCK. */
+ return (0);
+}
+
+/*
+ * Switch old & new arrays.
+ */
+static void
+ta_modify_chash(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t pflags)
+{
+ struct mod_item *mi;
+ struct chash_cfg *cfg;
+ struct chashbhead *old_head, *new_head;
+ struct chashentry *ent, *ent_next;
+ int af, i, mlen;
+ uint32_t nhash;
+ size_t old_size, new_size;
+
+ mi = (struct mod_item *)ta_buf;
+ cfg = (struct chash_cfg *)ta_state;
+
+ /* Check which hash we need to grow and do we still need that */
+ if (mi->size > 0 && cfg->size4 < mi->size) {
+ new_head = (struct chashbhead *)mi->main_ptr;
+ new_size = mi->size;
+ old_size = cfg->size4;
+ old_head = ti->state;
+ mlen = cfg->mask4;
+ af = AF_INET;
+
+ for (i = 0; i < old_size; i++) {
+ SLIST_FOREACH_SAFE(ent, &old_head[i], next, ent_next) {
+ nhash = hash_ent(ent, af, mlen, new_size);
+ SLIST_INSERT_HEAD(&new_head[nhash], ent, next);
+ }
+ }
+
+ ti->state = new_head;
+ cfg->head4 = new_head;
+ cfg->size4 = mi->size;
+ mi->main_ptr = old_head;
+ }
+
+ if (mi->size6 > 0 && cfg->size6 < mi->size6) {
+ new_head = (struct chashbhead *)mi->main_ptr6;
+ new_size = mi->size6;
+ old_size = cfg->size6;
+ old_head = ti->xstate;
+ mlen = cfg->mask6;
+ af = AF_INET6;
+
+ for (i = 0; i < old_size; i++) {
+ SLIST_FOREACH_SAFE(ent, &old_head[i], next, ent_next) {
+ nhash = hash_ent(ent, af, mlen, new_size);
+ SLIST_INSERT_HEAD(&new_head[nhash], ent, next);
+ }
+ }
+
+ ti->xstate = new_head;
+ cfg->head6 = new_head;
+ cfg->size6 = mi->size6;
+ mi->main_ptr6 = old_head;
+ }
+
+ /* Update lower 32 bits with new values */
+ ti->data &= 0xFFFFFFFF00000000;
+ ti->data |= log2(cfg->size4) << 8 | log2(cfg->size6);
+}
+
+/*
+ * Free unneded array.
+ */
+static void
+ta_flush_mod_chash(void *ta_buf)
+{
+ struct mod_item *mi;
+
+ mi = (struct mod_item *)ta_buf;
+ if (mi->main_ptr != NULL)
+ free(mi->main_ptr, M_IPFW);
+ if (mi->main_ptr6 != NULL)
+ free(mi->main_ptr6, M_IPFW);
+}
+
+struct table_algo addr_hash = {
+ .name = "addr:hash",
+ .type = IPFW_TABLE_ADDR,
+ .ta_buf_size = sizeof(struct ta_buf_chash),
+ .init = ta_init_chash,
+ .destroy = ta_destroy_chash,
+ .prepare_add = ta_prepare_add_chash,
+ .prepare_del = ta_prepare_del_chash,
+ .add = ta_add_chash,
+ .del = ta_del_chash,
+ .flush_entry = ta_flush_chash_entry,
+ .foreach = ta_foreach_chash,
+ .dump_tentry = ta_dump_chash_tentry,
+ .find_tentry = ta_find_chash_tentry,
+ .print_config = ta_print_chash_config,
+ .dump_tinfo = ta_dump_chash_tinfo,
+ .need_modify = ta_need_modify_chash,
+ .prepare_mod = ta_prepare_mod_chash,
+ .fill_mod = ta_fill_mod_chash,
+ .modify = ta_modify_chash,
+ .flush_mod = ta_flush_mod_chash,
+};
+
+
+/*
+ * Iface table cmds.
+ *
+ * Implementation:
+ *
+ * Runtime part:
+ * - sorted array of "struct ifidx" pointed by ti->state.
+ * Array is allocated with rounding up to IFIDX_CHUNK. Only existing
+ * interfaces are stored in array, however its allocated size is
+ * sufficient to hold all table records if needed.
+ * - current array size is stored in ti->data
+ *
+ * Table data:
+ * - "struct iftable_cfg" is allocated to store table state (ta_state).
+ * - All table records are stored inside namedobj instance.
+ *
+ */
+
+struct ifidx {
+ uint16_t kidx;
+ uint16_t spare;
+ uint32_t value;
+};
+#define DEFAULT_IFIDX_SIZE 64
+
+struct iftable_cfg;
+
+struct ifentry {
+ struct named_object no;
+ struct ipfw_ifc ic;
+ struct iftable_cfg *icfg;
+ uint32_t value;
+ int linked;
+};
+
+struct iftable_cfg {
+ struct namedobj_instance *ii;
+ struct ip_fw_chain *ch;
+ struct table_info *ti;
+ void *main_ptr;
+ size_t size; /* Number of items allocated in array */
+ size_t count; /* Number of all items */
+ size_t used; /* Number of items _active_ now */
+};
+
+struct ta_buf_ifidx
+{
+ struct ifentry *ife;
+ uint32_t value;
+};
+
+int compare_ifidx(const void *k, const void *v);
+static void if_notifier(struct ip_fw_chain *ch, void *cbdata, uint16_t ifindex);
+
+int
+compare_ifidx(const void *k, const void *v)
+{
+ const struct ifidx *ifidx;
+ uint16_t key;
+
+ key = *((const uint16_t *)k);
+ ifidx = (const struct ifidx *)v;
+
+ if (key < ifidx->kidx)
+ return (-1);
+ else if (key > ifidx->kidx)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Adds item @item with key @key into ascending-sorted array @base.
+ * Assumes @base has enough additional storage.
+ *
+ * Returns 1 on success, 0 on duplicate key.
+ */
+static int
+badd(const void *key, void *item, void *base, size_t nmemb,
+ size_t size, int (*compar) (const void *, const void *))
+{
+ int min, max, mid, shift, res;
+ caddr_t paddr;
+
+ if (nmemb == 0) {
+ memcpy(base, item, size);
+ return (1);
+ }
+
+ /* Binary search */
+ min = 0;
+ max = nmemb - 1;
+ mid = 0;
+ while (min <= max) {
+ mid = (min + max) / 2;
+ res = compar(key, (const void *)((caddr_t)base + mid * size));
+ if (res == 0)
+ return (0);
+
+ if (res > 0)
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+
+ /* Item not found. */
+ res = compar(key, (const void *)((caddr_t)base + mid * size));
+ if (res > 0)
+ shift = mid + 1;
+ else
+ shift = mid;
+
+ paddr = (caddr_t)base + shift * size;
+ if (nmemb > shift)
+ memmove(paddr + size, paddr, (nmemb - shift) * size);
+
+ memcpy(paddr, item, size);
+
+ return (1);
+}
+
+/*
+ * Deletes item with key @key from ascending-sorted array @base.
+ *
+ * Returns 1 on success, 0 for non-existent key.
+ */
+static int
+bdel(const void *key, void *base, size_t nmemb, size_t size,
+ int (*compar) (const void *, const void *))
+{
+ caddr_t item;
+ size_t sz;
+
+ item = (caddr_t)bsearch(key, base, nmemb, size, compar);
+
+ if (item == NULL)
+ return (0);
+
+ sz = (caddr_t)base + nmemb * size - item;
+
+ if (sz > 0)
+ memmove(item, item + size, sz);
+
+ return (1);
+}
+
+static struct ifidx *
+ifidx_find(struct table_info *ti, void *key)
+{
+ struct ifidx *ifi;
+
+ ifi = bsearch(key, ti->state, ti->data, sizeof(struct ifidx),
+ compare_ifidx);
+
+ return (ifi);
+}
+
+static int
+ta_lookup_ifidx(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct ifidx *ifi;
+
+ ifi = ifidx_find(ti, key);
+
+ if (ifi != NULL) {
+ *val = ifi->value;
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+ta_init_ifidx(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
+ char *data, uint8_t tflags)
+{
+ struct iftable_cfg *icfg;
+
+ icfg = malloc(sizeof(struct iftable_cfg), M_IPFW, M_WAITOK | M_ZERO);
+
+ icfg->ii = ipfw_objhash_create(DEFAULT_IFIDX_SIZE);
+ icfg->size = DEFAULT_IFIDX_SIZE;
+ icfg->main_ptr = malloc(sizeof(struct ifidx) * icfg->size, M_IPFW,
+ M_WAITOK | M_ZERO);
+ icfg->ch = ch;
+
+ *ta_state = icfg;
+ ti->state = icfg->main_ptr;
+ ti->lookup = ta_lookup_ifidx;
+
+ return (0);
+}
+
+/*
+ * Handle tableinfo @ti pointer change (on table array resize).
+ */
+static void
+ta_change_ti_ifidx(void *ta_state, struct table_info *ti)
+{
+ struct iftable_cfg *icfg;
+
+ icfg = (struct iftable_cfg *)ta_state;
+ icfg->ti = ti;
+}
+
+static void
+destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no,
+ void *arg)
+{
+ struct ifentry *ife;
+ struct ip_fw_chain *ch;
+
+ ch = (struct ip_fw_chain *)arg;
+ ife = (struct ifentry *)no;
+
+ ipfw_iface_del_notify(ch, &ife->ic);
+ free(ife, M_IPFW_TBL);
+}
+
+
+/*
+ * Destroys table @ti
+ */
+static void
+ta_destroy_ifidx(void *ta_state, struct table_info *ti)
+{
+ struct iftable_cfg *icfg;
+ struct ip_fw_chain *ch;
+
+ icfg = (struct iftable_cfg *)ta_state;
+ ch = icfg->ch;
+
+ if (icfg->main_ptr != NULL)
+ free(icfg->main_ptr, M_IPFW);
+
+ ipfw_objhash_foreach(icfg->ii, destroy_ifidx_locked, ch);
+
+ ipfw_objhash_destroy(icfg->ii);
+
+ free(icfg, M_IPFW);
+}
+
+/*
+ * Provide algo-specific table info
+ */
+static void
+ta_dump_ifidx_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
+{
+ struct iftable_cfg *cfg;
+
+ cfg = (struct iftable_cfg *)ta_state;
+
+ tinfo->taclass4 = IPFW_TACLASS_ARRAY;
+ tinfo->size4 = cfg->size;
+ tinfo->count4 = cfg->used;
+ tinfo->itemsize4 = sizeof(struct ifidx);
+}
+
+/*
+ * Prepare state to add to the table:
+ * allocate ifentry and reference needed interface.
+ */
+static int
+ta_prepare_add_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_ifidx *tb;
+ char *ifname;
+ struct ifentry *ife;
+
+ tb = (struct ta_buf_ifidx *)ta_buf;
+
+ /* Check if string is terminated */
+ ifname = (char *)tei->paddr;
+ if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE)
+ return (EINVAL);
+
+ ife = malloc(sizeof(struct ifentry), M_IPFW_TBL, M_WAITOK | M_ZERO);
+ ife->ic.cb = if_notifier;
+ ife->ic.cbdata = ife;
+
+ if (ipfw_iface_ref(ch, ifname, &ife->ic) != 0) {
+ free(ife, M_IPFW_TBL);
+ return (EINVAL);
+ }
+
+ /* Use ipfw_iface 'ifname' field as stable storage */
+ ife->no.name = ife->ic.iface->ifname;
+
+ tb->ife = ife;
+
+ return (0);
+}
+
+static int
+ta_add_ifidx(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct iftable_cfg *icfg;
+ struct ifentry *ife, *tmp;
+ struct ta_buf_ifidx *tb;
+ struct ipfw_iface *iif;
+ struct ifidx *ifi;
+ char *ifname;
+ uint32_t value;
+
+ tb = (struct ta_buf_ifidx *)ta_buf;
+ ifname = (char *)tei->paddr;
+ icfg = (struct iftable_cfg *)ta_state;
+ ife = tb->ife;
+
+ ife->icfg = icfg;
+ ife->value = tei->value;
+
+ tmp = (struct ifentry *)ipfw_objhash_lookup_name(icfg->ii, 0, ifname);
+
+ if (tmp != NULL) {
+ if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
+ return (EEXIST);
+
+ /* Exchange values in @tmp and @tei */
+ value = tmp->value;
+ tmp->value = tei->value;
+ tei->value = value;
+
+ iif = tmp->ic.iface;
+ if (iif->resolved != 0) {
+ /* We have to update runtime value, too */
+ ifi = ifidx_find(ti, &iif->ifindex);
+ ifi->value = ife->value;
+ }
+
+ /* Indicate that update has happened instead of addition */
+ tei->flags |= TEI_FLAGS_UPDATED;
+ *pnum = 0;
+ return (0);
+ }
+
+ if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
+ return (EFBIG);
+
+ /* Link to internal list */
+ ipfw_objhash_add(icfg->ii, &ife->no);
+
+ /* Link notifier (possible running its callback) */
+ ipfw_iface_add_notify(icfg->ch, &ife->ic);
+ icfg->count++;
+
+ tb->ife = NULL;
+ *pnum = 1;
+
+ return (0);
+}
+
+/*
+ * Prepare to delete key from table.
+ * Do basic interface name checks.
+ */
+static int
+ta_prepare_del_ifidx(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_ifidx *tb;
+ char *ifname;
+
+ tb = (struct ta_buf_ifidx *)ta_buf;
+
+ /* Check if string is terminated */
+ ifname = (char *)tei->paddr;
+ if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE)
+ return (EINVAL);
+
+ return (0);
+}
+
+/*
+ * Remove key from both configuration list and
+ * runtime array. Removed interface notification.
+ */
+static int
+ta_del_ifidx(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct iftable_cfg *icfg;
+ struct ifentry *ife;
+ struct ta_buf_ifidx *tb;
+ char *ifname;
+ uint16_t ifindex;
+ int res;
+
+ tb = (struct ta_buf_ifidx *)ta_buf;
+ ifname = (char *)tei->paddr;
+ icfg = (struct iftable_cfg *)ta_state;
+ ife = tb->ife;
+
+ ife = (struct ifentry *)ipfw_objhash_lookup_name(icfg->ii, 0, ifname);
+
+ if (ife == NULL)
+ return (ENOENT);
+
+ if (ife->linked != 0) {
+ /* We have to remove item from runtime */
+ ifindex = ife->ic.iface->ifindex;
+
+ res = bdel(&ifindex, icfg->main_ptr, icfg->used,
+ sizeof(struct ifidx), compare_ifidx);
+
+ KASSERT(res == 1, ("index %d does not exist", ifindex));
+ icfg->used--;
+ ti->data = icfg->used;
+ ife->linked = 0;
+ }
+
+ /* Unlink from local list */
+ ipfw_objhash_del(icfg->ii, &ife->no);
+ /* Unlink notifier */
+ ipfw_iface_del_notify(icfg->ch, &ife->ic);
+
+ icfg->count--;
+ tei->value = ife->value;
+
+ tb->ife = ife;
+ *pnum = 1;
+
+ return (0);
+}
+
+/*
+ * Flush deleted entry.
+ * Drops interface reference and frees entry.
+ */
+static void
+ta_flush_ifidx_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_ifidx *tb;
+
+ tb = (struct ta_buf_ifidx *)ta_buf;
+
+ if (tb->ife != NULL) {
+ /* Unlink first */
+ ipfw_iface_unref(ch, &tb->ife->ic);
+ free(tb->ife, M_IPFW_TBL);
+ }
+}
+
+
+/*
+ * Handle interface announce/withdrawal for particular table.
+ * Every real runtime array modification happens here.
+ */
+static void
+if_notifier(struct ip_fw_chain *ch, void *cbdata, uint16_t ifindex)
+{
+ struct ifentry *ife;
+ struct ifidx ifi;
+ struct iftable_cfg *icfg;
+ struct table_info *ti;
+ int res;
+
+ ife = (struct ifentry *)cbdata;
+ icfg = ife->icfg;
+ ti = icfg->ti;
+
+ KASSERT(ti != NULL, ("ti=NULL, check change_ti handler"));
+
+ if (ife->linked == 0 && ifindex != 0) {
+ /* Interface announce */
+ ifi.kidx = ifindex;
+ ifi.spare = 0;
+ ifi.value = ife->value;
+ res = badd(&ifindex, &ifi, icfg->main_ptr, icfg->used,
+ sizeof(struct ifidx), compare_ifidx);
+ KASSERT(res == 1, ("index %d already exists", ifindex));
+ icfg->used++;
+ ti->data = icfg->used;
+ ife->linked = 1;
+ } else if (ife->linked != 0 && ifindex == 0) {
+ /* Interface withdrawal */
+ ifindex = ife->ic.iface->ifindex;
+
+ res = bdel(&ifindex, icfg->main_ptr, icfg->used,
+ sizeof(struct ifidx), compare_ifidx);
+
+ KASSERT(res == 1, ("index %d does not exist", ifindex));
+ icfg->used--;
+ ti->data = icfg->used;
+ ife->linked = 0;
+ }
+}
+
+
+/*
+ * Table growing callbacks.
+ */
+
+static int
+ta_need_modify_ifidx(void *ta_state, struct table_info *ti, uint32_t count,
+ uint64_t *pflags)
+{
+ struct iftable_cfg *cfg;
+ uint32_t size;
+
+ cfg = (struct iftable_cfg *)ta_state;
+
+ size = cfg->size;
+ while (size < cfg->count + count)
+ size *= 2;
+
+ if (size != cfg->size) {
+ *pflags = size;
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Allocate ned, larger runtime ifidx array.
+ */
+static int
+ta_prepare_mod_ifidx(void *ta_buf, uint64_t *pflags)
+{
+ struct mod_item *mi;
+
+ mi = (struct mod_item *)ta_buf;
+
+ memset(mi, 0, sizeof(struct mod_item));
+ mi->size = *pflags;
+ mi->main_ptr = malloc(sizeof(struct ifidx) * mi->size, M_IPFW,
+ M_WAITOK | M_ZERO);
+
+ return (0);
+}
+
+/*
+ * Copy data from old runtime array to new one.
+ */
+static int
+ta_fill_mod_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t *pflags)
+{
+ struct mod_item *mi;
+ struct iftable_cfg *icfg;
+
+ mi = (struct mod_item *)ta_buf;
+ icfg = (struct iftable_cfg *)ta_state;
+
+ /* Check if we still need to grow array */
+ if (icfg->size >= mi->size) {
+ *pflags = 0;
+ return (0);
+ }
+
+ memcpy(mi->main_ptr, icfg->main_ptr, icfg->used * sizeof(struct ifidx));
+
+ return (0);
+}
+
+/*
+ * Switch old & new arrays.
+ */
+static void
+ta_modify_ifidx(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t pflags)
+{
+ struct mod_item *mi;
+ struct iftable_cfg *icfg;
+ void *old_ptr;
+
+ mi = (struct mod_item *)ta_buf;
+ icfg = (struct iftable_cfg *)ta_state;
+
+ old_ptr = icfg->main_ptr;
+ icfg->main_ptr = mi->main_ptr;
+ icfg->size = mi->size;
+ ti->state = icfg->main_ptr;
+
+ mi->main_ptr = old_ptr;
+}
+
+/*
+ * Free unneded array.
+ */
+static void
+ta_flush_mod_ifidx(void *ta_buf)
+{
+ struct mod_item *mi;
+
+ mi = (struct mod_item *)ta_buf;
+ if (mi->main_ptr != NULL)
+ free(mi->main_ptr, M_IPFW);
+}
+
+static int
+ta_dump_ifidx_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
+{
+ struct ifentry *ife;
+
+ ife = (struct ifentry *)e;
+
+ tent->masklen = 8 * IF_NAMESIZE;
+ memcpy(&tent->k, ife->no.name, IF_NAMESIZE);
+ tent->v.kidx = ife->value;
+
+ return (0);
+}
+
+static int
+ta_find_ifidx_tentry(void *ta_state, struct table_info *ti,
+ ipfw_obj_tentry *tent)
+{
+ struct iftable_cfg *icfg;
+ struct ifentry *ife;
+ char *ifname;
+
+ icfg = (struct iftable_cfg *)ta_state;
+ ifname = tent->k.iface;
+
+ if (strnlen(ifname, IF_NAMESIZE) == IF_NAMESIZE)
+ return (EINVAL);
+
+ ife = (struct ifentry *)ipfw_objhash_lookup_name(icfg->ii, 0, ifname);
+
+ if (ife != NULL) {
+ ta_dump_ifidx_tentry(ta_state, ti, ife, tent);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+struct wa_ifidx {
+ ta_foreach_f *f;
+ void *arg;
+};
+
+static void
+foreach_ifidx(struct namedobj_instance *ii, struct named_object *no,
+ void *arg)
+{
+ struct ifentry *ife;
+ struct wa_ifidx *wa;
+
+ ife = (struct ifentry *)no;
+ wa = (struct wa_ifidx *)arg;
+
+ wa->f(ife, wa->arg);
+}
+
+static void
+ta_foreach_ifidx(void *ta_state, struct table_info *ti, ta_foreach_f *f,
+ void *arg)
+{
+ struct iftable_cfg *icfg;
+ struct wa_ifidx wa;
+
+ icfg = (struct iftable_cfg *)ta_state;
+
+ wa.f = f;
+ wa.arg = arg;
+
+ ipfw_objhash_foreach(icfg->ii, foreach_ifidx, &wa);
+}
+
+struct table_algo iface_idx = {
+ .name = "iface:array",
+ .type = IPFW_TABLE_INTERFACE,
+ .flags = TA_FLAG_DEFAULT,
+ .ta_buf_size = sizeof(struct ta_buf_ifidx),
+ .init = ta_init_ifidx,
+ .destroy = ta_destroy_ifidx,
+ .prepare_add = ta_prepare_add_ifidx,
+ .prepare_del = ta_prepare_del_ifidx,
+ .add = ta_add_ifidx,
+ .del = ta_del_ifidx,
+ .flush_entry = ta_flush_ifidx_entry,
+ .foreach = ta_foreach_ifidx,
+ .dump_tentry = ta_dump_ifidx_tentry,
+ .find_tentry = ta_find_ifidx_tentry,
+ .dump_tinfo = ta_dump_ifidx_tinfo,
+ .need_modify = ta_need_modify_ifidx,
+ .prepare_mod = ta_prepare_mod_ifidx,
+ .fill_mod = ta_fill_mod_ifidx,
+ .modify = ta_modify_ifidx,
+ .flush_mod = ta_flush_mod_ifidx,
+ .change_ti = ta_change_ti_ifidx,
+};
+
+/*
+ * Number array cmds.
+ *
+ * Implementation:
+ *
+ * Runtime part:
+ * - sorted array of "struct numarray" pointed by ti->state.
+ * Array is allocated with rounding up to NUMARRAY_CHUNK.
+ * - current array size is stored in ti->data
+ *
+ */
+
+struct numarray {
+ uint32_t number;
+ uint32_t value;
+};
+
+struct numarray_cfg {
+ void *main_ptr;
+ size_t size; /* Number of items allocated in array */
+ size_t used; /* Number of items _active_ now */
+};
+
+struct ta_buf_numarray
+{
+ struct numarray na;
+};
+
+int compare_numarray(const void *k, const void *v);
+
+int
+compare_numarray(const void *k, const void *v)
+{
+ const struct numarray *na;
+ uint32_t key;
+
+ key = *((const uint32_t *)k);
+ na = (const struct numarray *)v;
+
+ if (key < na->number)
+ return (-1);
+ else if (key > na->number)
+ return (1);
+
+ return (0);
+}
+
+static struct numarray *
+numarray_find(struct table_info *ti, void *key)
+{
+ struct numarray *ri;
+
+ ri = bsearch(key, ti->state, ti->data, sizeof(struct numarray),
+ compare_ifidx);
+
+ return (ri);
+}
+
+static int
+ta_lookup_numarray(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct numarray *ri;
+
+ ri = numarray_find(ti, key);
+
+ if (ri != NULL) {
+ *val = ri->value;
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+ta_init_numarray(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
+ char *data, uint8_t tflags)
+{
+ struct numarray_cfg *cfg;
+
+ cfg = malloc(sizeof(*cfg), M_IPFW, M_WAITOK | M_ZERO);
+
+ cfg->size = 16;
+ cfg->main_ptr = malloc(sizeof(struct numarray) * cfg->size, M_IPFW,
+ M_WAITOK | M_ZERO);
+
+ *ta_state = cfg;
+ ti->state = cfg->main_ptr;
+ ti->lookup = ta_lookup_numarray;
+
+ return (0);
+}
+
+/*
+ * Destroys table @ti
+ */
+static void
+ta_destroy_numarray(void *ta_state, struct table_info *ti)
+{
+ struct numarray_cfg *cfg;
+
+ cfg = (struct numarray_cfg *)ta_state;
+
+ if (cfg->main_ptr != NULL)
+ free(cfg->main_ptr, M_IPFW);
+
+ free(cfg, M_IPFW);
+}
+
+/*
+ * Provide algo-specific table info
+ */
+static void
+ta_dump_numarray_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
+{
+ struct numarray_cfg *cfg;
+
+ cfg = (struct numarray_cfg *)ta_state;
+
+ tinfo->taclass4 = IPFW_TACLASS_ARRAY;
+ tinfo->size4 = cfg->size;
+ tinfo->count4 = cfg->used;
+ tinfo->itemsize4 = sizeof(struct numarray);
+}
+
+/*
+ * Prepare for addition/deletion to an array.
+ */
+static int
+ta_prepare_add_numarray(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_numarray *tb;
+
+ tb = (struct ta_buf_numarray *)ta_buf;
+
+ tb->na.number = *((uint32_t *)tei->paddr);
+
+ return (0);
+}
+
+static int
+ta_add_numarray(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct numarray_cfg *cfg;
+ struct ta_buf_numarray *tb;
+ struct numarray *ri;
+ int res;
+ uint32_t value;
+
+ tb = (struct ta_buf_numarray *)ta_buf;
+ cfg = (struct numarray_cfg *)ta_state;
+
+ /* Read current value from @tei */
+ tb->na.value = tei->value;
+
+ ri = numarray_find(ti, &tb->na.number);
+
+ if (ri != NULL) {
+ if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
+ return (EEXIST);
+
+ /* Exchange values between ri and @tei */
+ value = ri->value;
+ ri->value = tei->value;
+ tei->value = value;
+ /* Indicate that update has happened instead of addition */
+ tei->flags |= TEI_FLAGS_UPDATED;
+ *pnum = 0;
+ return (0);
+ }
+
+ if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
+ return (EFBIG);
+
+ res = badd(&tb->na.number, &tb->na, cfg->main_ptr, cfg->used,
+ sizeof(struct numarray), compare_numarray);
+
+ KASSERT(res == 1, ("number %d already exists", tb->na.number));
+ cfg->used++;
+ ti->data = cfg->used;
+ *pnum = 1;
+
+ return (0);
+}
+
+/*
+ * Remove key from both configuration list and
+ * runtime array. Removed interface notification.
+ */
+static int
+ta_del_numarray(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct numarray_cfg *cfg;
+ struct ta_buf_numarray *tb;
+ struct numarray *ri;
+ int res;
+
+ tb = (struct ta_buf_numarray *)ta_buf;
+ cfg = (struct numarray_cfg *)ta_state;
+
+ ri = numarray_find(ti, &tb->na.number);
+ if (ri == NULL)
+ return (ENOENT);
+
+ tei->value = ri->value;
+
+ res = bdel(&tb->na.number, cfg->main_ptr, cfg->used,
+ sizeof(struct numarray), compare_numarray);
+
+ KASSERT(res == 1, ("number %u does not exist", tb->na.number));
+ cfg->used--;
+ ti->data = cfg->used;
+ *pnum = 1;
+
+ return (0);
+}
+
+static void
+ta_flush_numarray_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+
+ /* We don't have any state, do nothing */
+}
+
+
+/*
+ * Table growing callbacks.
+ */
+
+static int
+ta_need_modify_numarray(void *ta_state, struct table_info *ti, uint32_t count,
+ uint64_t *pflags)
+{
+ struct numarray_cfg *cfg;
+ size_t size;
+
+ cfg = (struct numarray_cfg *)ta_state;
+
+ size = cfg->size;
+ while (size < cfg->used + count)
+ size *= 2;
+
+ if (size != cfg->size) {
+ *pflags = size;
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Allocate new, larger runtime array.
+ */
+static int
+ta_prepare_mod_numarray(void *ta_buf, uint64_t *pflags)
+{
+ struct mod_item *mi;
+
+ mi = (struct mod_item *)ta_buf;
+
+ memset(mi, 0, sizeof(struct mod_item));
+ mi->size = *pflags;
+ mi->main_ptr = malloc(sizeof(struct numarray) * mi->size, M_IPFW,
+ M_WAITOK | M_ZERO);
+
+ return (0);
+}
+
+/*
+ * Copy data from old runtime array to new one.
+ */
+static int
+ta_fill_mod_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t *pflags)
+{
+ struct mod_item *mi;
+ struct numarray_cfg *cfg;
+
+ mi = (struct mod_item *)ta_buf;
+ cfg = (struct numarray_cfg *)ta_state;
+
+ /* Check if we still need to grow array */
+ if (cfg->size >= mi->size) {
+ *pflags = 0;
+ return (0);
+ }
+
+ memcpy(mi->main_ptr, cfg->main_ptr, cfg->used * sizeof(struct numarray));
+
+ return (0);
+}
+
+/*
+ * Switch old & new arrays.
+ */
+static void
+ta_modify_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t pflags)
+{
+ struct mod_item *mi;
+ struct numarray_cfg *cfg;
+ void *old_ptr;
+
+ mi = (struct mod_item *)ta_buf;
+ cfg = (struct numarray_cfg *)ta_state;
+
+ old_ptr = cfg->main_ptr;
+ cfg->main_ptr = mi->main_ptr;
+ cfg->size = mi->size;
+ ti->state = cfg->main_ptr;
+
+ mi->main_ptr = old_ptr;
+}
+
+/*
+ * Free unneded array.
+ */
+static void
+ta_flush_mod_numarray(void *ta_buf)
+{
+ struct mod_item *mi;
+
+ mi = (struct mod_item *)ta_buf;
+ if (mi->main_ptr != NULL)
+ free(mi->main_ptr, M_IPFW);
+}
+
+static int
+ta_dump_numarray_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
+{
+ struct numarray *na;
+
+ na = (struct numarray *)e;
+
+ tent->k.key = na->number;
+ tent->v.kidx = na->value;
+
+ return (0);
+}
+
+static int
+ta_find_numarray_tentry(void *ta_state, struct table_info *ti,
+ ipfw_obj_tentry *tent)
+{
+ struct numarray_cfg *cfg;
+ struct numarray *ri;
+
+ cfg = (struct numarray_cfg *)ta_state;
+
+ ri = numarray_find(ti, &tent->k.key);
+
+ if (ri != NULL) {
+ ta_dump_numarray_tentry(ta_state, ti, ri, tent);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static void
+ta_foreach_numarray(void *ta_state, struct table_info *ti, ta_foreach_f *f,
+ void *arg)
+{
+ struct numarray_cfg *cfg;
+ struct numarray *array;
+ int i;
+
+ cfg = (struct numarray_cfg *)ta_state;
+ array = cfg->main_ptr;
+
+ for (i = 0; i < cfg->used; i++)
+ f(&array[i], arg);
+}
+
+struct table_algo number_array = {
+ .name = "number:array",
+ .type = IPFW_TABLE_NUMBER,
+ .ta_buf_size = sizeof(struct ta_buf_numarray),
+ .init = ta_init_numarray,
+ .destroy = ta_destroy_numarray,
+ .prepare_add = ta_prepare_add_numarray,
+ .prepare_del = ta_prepare_add_numarray,
+ .add = ta_add_numarray,
+ .del = ta_del_numarray,
+ .flush_entry = ta_flush_numarray_entry,
+ .foreach = ta_foreach_numarray,
+ .dump_tentry = ta_dump_numarray_tentry,
+ .find_tentry = ta_find_numarray_tentry,
+ .dump_tinfo = ta_dump_numarray_tinfo,
+ .need_modify = ta_need_modify_numarray,
+ .prepare_mod = ta_prepare_mod_numarray,
+ .fill_mod = ta_fill_mod_numarray,
+ .modify = ta_modify_numarray,
+ .flush_mod = ta_flush_mod_numarray,
+};
+
+/*
+ * flow:hash cmds
+ *
+ *
+ * ti->data:
+ * [inv.mask4][inv.mask6][log2hsize4][log2hsize6]
+ * [ 8][ 8[ 8][ 8]
+ *
+ * inv.mask4: 32 - mask
+ * inv.mask6:
+ * 1) _slow lookup: mask
+ * 2) _aligned: (128 - mask) / 8
+ * 3) _64: 8
+ *
+ *
+ * pflags:
+ * [hsize4][hsize6]
+ * [ 16][ 16]
+ */
+
+struct fhashentry;
+
+SLIST_HEAD(fhashbhead, fhashentry);
+
+struct fhashentry {
+ SLIST_ENTRY(fhashentry) next;
+ uint8_t af;
+ uint8_t proto;
+ uint16_t spare0;
+ uint16_t dport;
+ uint16_t sport;
+ uint32_t value;
+ uint32_t spare1;
+};
+
+struct fhashentry4 {
+ struct fhashentry e;
+ struct in_addr dip;
+ struct in_addr sip;
+};
+
+struct fhashentry6 {
+ struct fhashentry e;
+ struct in6_addr dip6;
+ struct in6_addr sip6;
+};
+
+struct fhash_cfg {
+ struct fhashbhead *head;
+ size_t size;
+ size_t items;
+ struct fhashentry4 fe4;
+ struct fhashentry6 fe6;
+};
+
+struct ta_buf_fhash {
+ void *ent_ptr;
+ struct fhashentry6 fe6;
+};
+
+static __inline int
+cmp_flow_ent(struct fhashentry *a, struct fhashentry *b, size_t sz)
+{
+ uint64_t *ka, *kb;
+
+ ka = (uint64_t *)(&a->next + 1);
+ kb = (uint64_t *)(&b->next + 1);
+
+ if (*ka == *kb && (memcmp(a + 1, b + 1, sz) == 0))
+ return (1);
+
+ return (0);
+}
+
+static __inline uint32_t
+hash_flow4(struct fhashentry4 *f, int hsize)
+{
+ uint32_t i;
+
+ i = (f->dip.s_addr) ^ (f->sip.s_addr) ^ (f->e.dport) ^ (f->e.sport);
+
+ return (i % (hsize - 1));
+}
+
+static __inline uint32_t
+hash_flow6(struct fhashentry6 *f, int hsize)
+{
+ uint32_t i;
+
+ i = (f->dip6.__u6_addr.__u6_addr32[2]) ^
+ (f->dip6.__u6_addr.__u6_addr32[3]) ^
+ (f->sip6.__u6_addr.__u6_addr32[2]) ^
+ (f->sip6.__u6_addr.__u6_addr32[3]) ^
+ (f->e.dport) ^ (f->e.sport);
+
+ return (i % (hsize - 1));
+}
+
+static uint32_t
+hash_flow_ent(struct fhashentry *ent, uint32_t size)
+{
+ uint32_t hash;
+
+ if (ent->af == AF_INET) {
+ hash = hash_flow4((struct fhashentry4 *)ent, size);
+ } else {
+ hash = hash_flow6((struct fhashentry6 *)ent, size);
+ }
+
+ return (hash);
+}
+
+static int
+ta_lookup_fhash(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct fhashbhead *head;
+ struct fhashentry *ent;
+ struct fhashentry4 *m4;
+ struct ipfw_flow_id *id;
+ uint16_t hash, hsize;
+
+ id = (struct ipfw_flow_id *)key;
+ head = (struct fhashbhead *)ti->state;
+ hsize = ti->data;
+ m4 = (struct fhashentry4 *)ti->xstate;
+
+ if (id->addr_type == 4) {
+ struct fhashentry4 f;
+
+ /* Copy hash mask */
+ f = *m4;
+
+ f.dip.s_addr &= id->dst_ip;
+ f.sip.s_addr &= id->src_ip;
+ f.e.dport &= id->dst_port;
+ f.e.sport &= id->src_port;
+ f.e.proto &= id->proto;
+ hash = hash_flow4(&f, hsize);
+ SLIST_FOREACH(ent, &head[hash], next) {
+ if (cmp_flow_ent(ent, &f.e, 2 * 4) != 0) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ } else if (id->addr_type == 6) {
+ struct fhashentry6 f;
+ uint64_t *fp, *idp;
+
+ /* Copy hash mask */
+ f = *((struct fhashentry6 *)(m4 + 1));
+
+ /* Handle lack of __u6_addr.__u6_addr64 */
+ fp = (uint64_t *)&f.dip6;
+ idp = (uint64_t *)&id->dst_ip6;
+ /* src IPv6 is stored after dst IPv6 */
+ *fp++ &= *idp++;
+ *fp++ &= *idp++;
+ *fp++ &= *idp++;
+ *fp &= *idp;
+ f.e.dport &= id->dst_port;
+ f.e.sport &= id->src_port;
+ f.e.proto &= id->proto;
+ hash = hash_flow6(&f, hsize);
+ SLIST_FOREACH(ent, &head[hash], next) {
+ if (cmp_flow_ent(ent, &f.e, 2 * 16) != 0) {
+ *val = ent->value;
+ return (1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * New table.
+ */
+static int
+ta_init_fhash(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
+ char *data, uint8_t tflags)
+{
+ int i;
+ struct fhash_cfg *cfg;
+ struct fhashentry4 *fe4;
+ struct fhashentry6 *fe6;
+
+ cfg = malloc(sizeof(struct fhash_cfg), M_IPFW, M_WAITOK | M_ZERO);
+
+ cfg->size = 512;
+
+ cfg->head = malloc(sizeof(struct fhashbhead) * cfg->size, M_IPFW,
+ M_WAITOK | M_ZERO);
+ for (i = 0; i < cfg->size; i++)
+ SLIST_INIT(&cfg->head[i]);
+
+ /* Fill in fe masks based on @tflags */
+ fe4 = &cfg->fe4;
+ fe6 = &cfg->fe6;
+ if (tflags & IPFW_TFFLAG_SRCIP) {
+ memset(&fe4->sip, 0xFF, sizeof(fe4->sip));
+ memset(&fe6->sip6, 0xFF, sizeof(fe6->sip6));
+ }
+ if (tflags & IPFW_TFFLAG_DSTIP) {
+ memset(&fe4->dip, 0xFF, sizeof(fe4->dip));
+ memset(&fe6->dip6, 0xFF, sizeof(fe6->dip6));
+ }
+ if (tflags & IPFW_TFFLAG_SRCPORT) {
+ memset(&fe4->e.sport, 0xFF, sizeof(fe4->e.sport));
+ memset(&fe6->e.sport, 0xFF, sizeof(fe6->e.sport));
+ }
+ if (tflags & IPFW_TFFLAG_DSTPORT) {
+ memset(&fe4->e.dport, 0xFF, sizeof(fe4->e.dport));
+ memset(&fe6->e.dport, 0xFF, sizeof(fe6->e.dport));
+ }
+ if (tflags & IPFW_TFFLAG_PROTO) {
+ memset(&fe4->e.proto, 0xFF, sizeof(fe4->e.proto));
+ memset(&fe6->e.proto, 0xFF, sizeof(fe6->e.proto));
+ }
+
+ fe4->e.af = AF_INET;
+ fe6->e.af = AF_INET6;
+
+ *ta_state = cfg;
+ ti->state = cfg->head;
+ ti->xstate = &cfg->fe4;
+ ti->data = cfg->size;
+ ti->lookup = ta_lookup_fhash;
+
+ return (0);
+}
+
+static void
+ta_destroy_fhash(void *ta_state, struct table_info *ti)
+{
+ struct fhash_cfg *cfg;
+ struct fhashentry *ent, *ent_next;
+ int i;
+
+ cfg = (struct fhash_cfg *)ta_state;
+
+ for (i = 0; i < cfg->size; i++)
+ SLIST_FOREACH_SAFE(ent, &cfg->head[i], next, ent_next)
+ free(ent, M_IPFW_TBL);
+
+ free(cfg->head, M_IPFW);
+ free(cfg, M_IPFW);
+}
+
+/*
+ * Provide algo-specific table info
+ */
+static void
+ta_dump_fhash_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
+{
+ struct fhash_cfg *cfg;
+
+ cfg = (struct fhash_cfg *)ta_state;
+
+ tinfo->flags = IPFW_TATFLAGS_AFITEM;
+ tinfo->taclass4 = IPFW_TACLASS_HASH;
+ tinfo->size4 = cfg->size;
+ tinfo->count4 = cfg->items;
+ tinfo->itemsize4 = sizeof(struct fhashentry4);
+ tinfo->itemsize6 = sizeof(struct fhashentry6);
+}
+
+static int
+ta_dump_fhash_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
+{
+ struct fhash_cfg *cfg;
+ struct fhashentry *ent;
+ struct fhashentry4 *fe4;
+ struct fhashentry6 *fe6;
+ struct tflow_entry *tfe;
+
+ cfg = (struct fhash_cfg *)ta_state;
+ ent = (struct fhashentry *)e;
+ tfe = &tent->k.flow;
+
+ tfe->af = ent->af;
+ tfe->proto = ent->proto;
+ tfe->dport = htons(ent->dport);
+ tfe->sport = htons(ent->sport);
+ tent->v.kidx = ent->value;
+ tent->subtype = ent->af;
+
+ if (ent->af == AF_INET) {
+ fe4 = (struct fhashentry4 *)ent;
+ tfe->a.a4.sip.s_addr = htonl(fe4->sip.s_addr);
+ tfe->a.a4.dip.s_addr = htonl(fe4->dip.s_addr);
+ tent->masklen = 32;
+#ifdef INET6
+ } else {
+ fe6 = (struct fhashentry6 *)ent;
+ tfe->a.a6.sip6 = fe6->sip6;
+ tfe->a.a6.dip6 = fe6->dip6;
+ tent->masklen = 128;
+#endif
+ }
+
+ return (0);
+}
+
+static int
+tei_to_fhash_ent(struct tentry_info *tei, struct fhashentry *ent)
+{
+ struct fhashentry4 *fe4;
+ struct fhashentry6 *fe6;
+ struct tflow_entry *tfe;
+
+ tfe = (struct tflow_entry *)tei->paddr;
+
+ ent->af = tei->subtype;
+ ent->proto = tfe->proto;
+ ent->dport = ntohs(tfe->dport);
+ ent->sport = ntohs(tfe->sport);
+
+ if (tei->subtype == AF_INET) {
+#ifdef INET
+ fe4 = (struct fhashentry4 *)ent;
+ fe4->sip.s_addr = ntohl(tfe->a.a4.sip.s_addr);
+ fe4->dip.s_addr = ntohl(tfe->a.a4.dip.s_addr);
+#endif
+#ifdef INET6
+ } else if (tei->subtype == AF_INET6) {
+ fe6 = (struct fhashentry6 *)ent;
+ fe6->sip6 = tfe->a.a6.sip6;
+ fe6->dip6 = tfe->a.a6.dip6;
+#endif
+ } else {
+ /* Unknown CIDR type */
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+
+static int
+ta_find_fhash_tentry(void *ta_state, struct table_info *ti,
+ ipfw_obj_tentry *tent)
+{
+ struct fhash_cfg *cfg;
+ struct fhashbhead *head;
+ struct fhashentry *ent, *tmp;
+ struct fhashentry6 fe6;
+ struct tentry_info tei;
+ int error;
+ uint32_t hash;
+ size_t sz;
+
+ cfg = (struct fhash_cfg *)ta_state;
+
+ ent = &fe6.e;
+
+ memset(&fe6, 0, sizeof(fe6));
+ memset(&tei, 0, sizeof(tei));
+
+ tei.paddr = &tent->k.flow;
+ tei.subtype = tent->subtype;
+
+ if ((error = tei_to_fhash_ent(&tei, ent)) != 0)
+ return (error);
+
+ head = cfg->head;
+ hash = hash_flow_ent(ent, cfg->size);
+
+ if (tei.subtype == AF_INET)
+ sz = 2 * sizeof(struct in_addr);
+ else
+ sz = 2 * sizeof(struct in6_addr);
+
+ /* Check for existence */
+ SLIST_FOREACH(tmp, &head[hash], next) {
+ if (cmp_flow_ent(tmp, ent, sz) != 0) {
+ ta_dump_fhash_tentry(ta_state, ti, tmp, tent);
+ return (0);
+ }
+ }
+
+ return (ENOENT);
+}
+
+static void
+ta_foreach_fhash(void *ta_state, struct table_info *ti, ta_foreach_f *f,
+ void *arg)
+{
+ struct fhash_cfg *cfg;
+ struct fhashentry *ent, *ent_next;
+ int i;
+
+ cfg = (struct fhash_cfg *)ta_state;
+
+ for (i = 0; i < cfg->size; i++)
+ SLIST_FOREACH_SAFE(ent, &cfg->head[i], next, ent_next)
+ f(ent, arg);
+}
+
+static int
+ta_prepare_add_fhash(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_fhash *tb;
+ struct fhashentry *ent;
+ size_t sz;
+ int error;
+
+ tb = (struct ta_buf_fhash *)ta_buf;
+
+ if (tei->subtype == AF_INET)
+ sz = sizeof(struct fhashentry4);
+ else if (tei->subtype == AF_INET6)
+ sz = sizeof(struct fhashentry6);
+ else
+ return (EINVAL);
+
+ ent = malloc(sz, M_IPFW_TBL, M_WAITOK | M_ZERO);
+
+ error = tei_to_fhash_ent(tei, ent);
+ if (error != 0) {
+ free(ent, M_IPFW_TBL);
+ return (error);
+ }
+ tb->ent_ptr = ent;
+
+ return (0);
+}
+
+static int
+ta_add_fhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct fhash_cfg *cfg;
+ struct fhashbhead *head;
+ struct fhashentry *ent, *tmp;
+ struct ta_buf_fhash *tb;
+ int exists;
+ uint32_t hash, value;
+ size_t sz;
+
+ cfg = (struct fhash_cfg *)ta_state;
+ tb = (struct ta_buf_fhash *)ta_buf;
+ ent = (struct fhashentry *)tb->ent_ptr;
+ exists = 0;
+
+ /* Read current value from @tei */
+ ent->value = tei->value;
+
+ head = cfg->head;
+ hash = hash_flow_ent(ent, cfg->size);
+
+ if (tei->subtype == AF_INET)
+ sz = 2 * sizeof(struct in_addr);
+ else
+ sz = 2 * sizeof(struct in6_addr);
+
+ /* Check for existence */
+ SLIST_FOREACH(tmp, &head[hash], next) {
+ if (cmp_flow_ent(tmp, ent, sz) != 0) {
+ exists = 1;
+ break;
+ }
+ }
+
+ if (exists == 1) {
+ if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
+ return (EEXIST);
+ /* Record already exists. Update value if we're asked to */
+ /* Exchange values between tmp and @tei */
+ value = tmp->value;
+ tmp->value = tei->value;
+ tei->value = value;
+ /* Indicate that update has happened instead of addition */
+ tei->flags |= TEI_FLAGS_UPDATED;
+ *pnum = 0;
+ } else {
+ if ((tei->flags & TEI_FLAGS_DONTADD) != 0)
+ return (EFBIG);
+
+ SLIST_INSERT_HEAD(&head[hash], ent, next);
+ tb->ent_ptr = NULL;
+ *pnum = 1;
+
+ /* Update counters and check if we need to grow hash */
+ cfg->items++;
+ }
+
+ return (0);
+}
+
+static int
+ta_prepare_del_fhash(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_fhash *tb;
+
+ tb = (struct ta_buf_fhash *)ta_buf;
+
+ return (tei_to_fhash_ent(tei, &tb->fe6.e));
+}
+
+static int
+ta_del_fhash(void *ta_state, struct table_info *ti, struct tentry_info *tei,
+ void *ta_buf, uint32_t *pnum)
+{
+ struct fhash_cfg *cfg;
+ struct fhashbhead *head;
+ struct fhashentry *ent, *tmp;
+ struct ta_buf_fhash *tb;
+ uint32_t hash;
+ size_t sz;
+
+ cfg = (struct fhash_cfg *)ta_state;
+ tb = (struct ta_buf_fhash *)ta_buf;
+ ent = &tb->fe6.e;
+
+ head = cfg->head;
+ hash = hash_flow_ent(ent, cfg->size);
+
+ if (tei->subtype == AF_INET)
+ sz = 2 * sizeof(struct in_addr);
+ else
+ sz = 2 * sizeof(struct in6_addr);
+
+ /* Check for existence */
+ SLIST_FOREACH(tmp, &head[hash], next) {
+ if (cmp_flow_ent(tmp, ent, sz) == 0)
+ continue;
+
+ SLIST_REMOVE(&head[hash], tmp, fhashentry, next);
+ tei->value = tmp->value;
+ *pnum = 1;
+ cfg->items--;
+ tb->ent_ptr = tmp;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static void
+ta_flush_fhash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
+ void *ta_buf)
+{
+ struct ta_buf_fhash *tb;
+
+ tb = (struct ta_buf_fhash *)ta_buf;
+
+ if (tb->ent_ptr != NULL)
+ free(tb->ent_ptr, M_IPFW_TBL);
+}
+
+/*
+ * Hash growing callbacks.
+ */
+
+static int
+ta_need_modify_fhash(void *ta_state, struct table_info *ti, uint32_t count,
+ uint64_t *pflags)
+{
+ struct fhash_cfg *cfg;
+
+ cfg = (struct fhash_cfg *)ta_state;
+
+ if (cfg->items > cfg->size && cfg->size < 65536) {
+ *pflags = cfg->size * 2;
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Allocate new, larger fhash.
+ */
+static int
+ta_prepare_mod_fhash(void *ta_buf, uint64_t *pflags)
+{
+ struct mod_item *mi;
+ struct fhashbhead *head;
+ int i;
+
+ mi = (struct mod_item *)ta_buf;
+
+ memset(mi, 0, sizeof(struct mod_item));
+ mi->size = *pflags;
+ head = malloc(sizeof(struct fhashbhead) * mi->size, M_IPFW,
+ M_WAITOK | M_ZERO);
+ for (i = 0; i < mi->size; i++)
+ SLIST_INIT(&head[i]);
+
+ mi->main_ptr = head;
+
+ return (0);
+}
+
+/*
+ * Copy data from old runtime array to new one.
+ */
+static int
+ta_fill_mod_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t *pflags)
+{
+
+ /* In is not possible to do rehash if we're not holidng WLOCK. */
+ return (0);
+}
+
+/*
+ * Switch old & new arrays.
+ */
+static void
+ta_modify_fhash(void *ta_state, struct table_info *ti, void *ta_buf,
+ uint64_t pflags)
+{
+ struct mod_item *mi;
+ struct fhash_cfg *cfg;
+ struct fhashbhead *old_head, *new_head;
+ struct fhashentry *ent, *ent_next;
+ int i;
+ uint32_t nhash;
+ size_t old_size;
+
+ mi = (struct mod_item *)ta_buf;
+ cfg = (struct fhash_cfg *)ta_state;
+
+ old_size = cfg->size;
+ old_head = ti->state;
+
+ new_head = (struct fhashbhead *)mi->main_ptr;
+ for (i = 0; i < old_size; i++) {
+ SLIST_FOREACH_SAFE(ent, &old_head[i], next, ent_next) {
+ nhash = hash_flow_ent(ent, mi->size);
+ SLIST_INSERT_HEAD(&new_head[nhash], ent, next);
+ }
+ }
+
+ ti->state = new_head;
+ ti->data = mi->size;
+ cfg->head = new_head;
+ cfg->size = mi->size;
+
+ mi->main_ptr = old_head;
+}
+
+/*
+ * Free unneded array.
+ */
+static void
+ta_flush_mod_fhash(void *ta_buf)
+{
+ struct mod_item *mi;
+
+ mi = (struct mod_item *)ta_buf;
+ if (mi->main_ptr != NULL)
+ free(mi->main_ptr, M_IPFW);
+}
+
+struct table_algo flow_hash = {
+ .name = "flow:hash",
+ .type = IPFW_TABLE_FLOW,
+ .flags = TA_FLAG_DEFAULT,
+ .ta_buf_size = sizeof(struct ta_buf_fhash),
+ .init = ta_init_fhash,
+ .destroy = ta_destroy_fhash,
+ .prepare_add = ta_prepare_add_fhash,
+ .prepare_del = ta_prepare_del_fhash,
+ .add = ta_add_fhash,
+ .del = ta_del_fhash,
+ .flush_entry = ta_flush_fhash_entry,
+ .foreach = ta_foreach_fhash,
+ .dump_tentry = ta_dump_fhash_tentry,
+ .find_tentry = ta_find_fhash_tentry,
+ .dump_tinfo = ta_dump_fhash_tinfo,
+ .need_modify = ta_need_modify_fhash,
+ .prepare_mod = ta_prepare_mod_fhash,
+ .fill_mod = ta_fill_mod_fhash,
+ .modify = ta_modify_fhash,
+ .flush_mod = ta_flush_mod_fhash,
+};
+
+/*
+ * Kernel fibs bindings.
+ *
+ * Implementation:
+ *
+ * Runtime part:
+ * - fully relies on route API
+ * - fib number is stored in ti->data
+ *
+ */
+
+static struct rtentry *
+lookup_kfib(void *key, int keylen, int fib)
+{
+ struct sockaddr *s;
+
+ if (keylen == 4) {
+ struct sockaddr_in sin;
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = *(in_addr_t *)key;
+ s = (struct sockaddr *)&sin;
+ } else {
+ struct sockaddr_in6 sin6;
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = *(struct in6_addr *)key;
+ s = (struct sockaddr *)&sin6;
+ }
+
+ return (rtalloc1_fib(s, 0, 0, fib));
+}
+
+static int
+ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen,
+ uint32_t *val)
+{
+ struct rtentry *rte;
+
+ if ((rte = lookup_kfib(key, keylen, ti->data)) == NULL)
+ return (0);
+
+ *val = 0;
+ RTFREE_LOCKED(rte);
+
+ return (1);
+}
+
+/* Parse 'fib=%d' */
+static int
+kfib_parse_opts(int *pfib, char *data)
+{
+ char *pdel, *pend, *s;
+ int fibnum;
+
+ if (data == NULL)
+ return (0);
+ if ((pdel = strchr(data, ' ')) == NULL)
+ return (0);
+ while (*pdel == ' ')
+ pdel++;
+ if (strncmp(pdel, "fib=", 4) != 0)
+ return (EINVAL);
+ if ((s = strchr(pdel, ' ')) != NULL)
+ *s++ = '\0';
+
+ pdel += 4;
+ /* Need \d+ */
+ fibnum = strtol(pdel, &pend, 10);
+ if (*pend != '\0')
+ return (EINVAL);
+
+ *pfib = fibnum;
+
+ return (0);
+}
+
+static void
+ta_print_kfib_config(void *ta_state, struct table_info *ti, char *buf,
+ size_t bufsize)
+{
+
+ if (ti->data != 0)
+ snprintf(buf, bufsize, "%s fib=%lu", "addr:kfib", ti->data);
+ else
+ snprintf(buf, bufsize, "%s", "addr:kfib");
+}
+
+static int
+ta_init_kfib(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
+ char *data, uint8_t tflags)
+{
+ int error, fibnum;
+
+ fibnum = 0;
+ if ((error = kfib_parse_opts(&fibnum, data)) != 0)
+ return (error);
+
+ if (fibnum >= rt_numfibs)
+ return (E2BIG);
+
+ ti->data = fibnum;
+ ti->lookup = ta_lookup_kfib;
+
+ return (0);
+}
+
+/*
+ * Destroys table @ti
+ */
+static void
+ta_destroy_kfib(void *ta_state, struct table_info *ti)
+{
+
+}
+
+/*
+ * Provide algo-specific table info
+ */
+static void
+ta_dump_kfib_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo)
+{
+
+ tinfo->flags = IPFW_TATFLAGS_AFDATA;
+ tinfo->taclass4 = IPFW_TACLASS_RADIX;
+ tinfo->count4 = 0;
+ tinfo->itemsize4 = sizeof(struct rtentry);
+ tinfo->taclass6 = IPFW_TACLASS_RADIX;
+ tinfo->count6 = 0;
+ tinfo->itemsize6 = sizeof(struct rtentry);
+}
+
+static int
+contigmask(uint8_t *p, int len)
+{
+ int i, n;
+
+ for (i = 0; i < len ; i++)
+ if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */
+ break;
+ for (n= i + 1; n < len; n++)
+ if ( (p[n/8] & (1 << (7 - (n % 8)))) != 0)
+ return (-1); /* mask not contiguous */
+ return (i);
+}
+
+
+static int
+ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
+{
+ struct rtentry *rte;
+ struct sockaddr_in *addr, *mask;
+ struct sockaddr_in6 *addr6, *mask6;
+ int len;
+
+ rte = (struct rtentry *)e;
+ addr = (struct sockaddr_in *)rt_key(rte);
+ mask = (struct sockaddr_in *)rt_mask(rte);
+ len = 0;
+
+ /* Guess IPv4/IPv6 radix by sockaddr family */
+ if (addr->sin_family == AF_INET) {
+ tent->k.addr.s_addr = addr->sin_addr.s_addr;
+ len = 32;
+ if (mask != NULL)
+ len = contigmask((uint8_t *)&mask->sin_addr, 32);
+ if (len == -1)
+ len = 0;
+ tent->masklen = len;
+ tent->subtype = AF_INET;
+ tent->v.kidx = 0; /* Do we need to put GW here? */
+#ifdef INET6
+ } else if (addr->sin_family == AF_INET6) {
+ addr6 = (struct sockaddr_in6 *)addr;
+ mask6 = (struct sockaddr_in6 *)mask;
+ memcpy(&tent->k, &addr6->sin6_addr, sizeof(struct in6_addr));
+ len = 128;
+ if (mask6 != NULL)
+ len = contigmask((uint8_t *)&mask6->sin6_addr, 128);
+ if (len == -1)
+ len = 0;
+ tent->masklen = len;
+ tent->subtype = AF_INET6;
+ tent->v.kidx = 0;
+#endif
+ }
+
+ return (0);
+}
+
+static int
+ta_find_kfib_tentry(void *ta_state, struct table_info *ti,
+ ipfw_obj_tentry *tent)
+{
+ struct rtentry *rte;
+ void *key;
+ int keylen;
+
+ if (tent->subtype == AF_INET) {
+ key = &tent->k.addr;
+ keylen = sizeof(struct in_addr);
+ } else {
+ key = &tent->k.addr6;
+ keylen = sizeof(struct in6_addr);
+ }
+
+ if ((rte = lookup_kfib(key, keylen, ti->data)) == NULL)
+ return (0);
+
+ if (rte != NULL) {
+ ta_dump_kfib_tentry(ta_state, ti, rte, tent);
+ RTFREE_LOCKED(rte);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static void
+ta_foreach_kfib(void *ta_state, struct table_info *ti, ta_foreach_f *f,
+ void *arg)
+{
+ struct radix_node_head *rnh;
+ int error;
+
+ rnh = rt_tables_get_rnh(ti->data, AF_INET);
+ if (rnh != NULL) {
+ RADIX_NODE_HEAD_RLOCK(rnh);
+ error = rnh->rnh_walktree(rnh, (walktree_f_t *)f, arg);
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+ }
+
+ rnh = rt_tables_get_rnh(ti->data, AF_INET6);
+ if (rnh != NULL) {
+ RADIX_NODE_HEAD_RLOCK(rnh);
+ error = rnh->rnh_walktree(rnh, (walktree_f_t *)f, arg);
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+ }
+}
+
+struct table_algo addr_kfib = {
+ .name = "addr:kfib",
+ .type = IPFW_TABLE_ADDR,
+ .flags = TA_FLAG_READONLY,
+ .ta_buf_size = 0,
+ .init = ta_init_kfib,
+ .destroy = ta_destroy_kfib,
+ .foreach = ta_foreach_kfib,
+ .dump_tentry = ta_dump_kfib_tentry,
+ .find_tentry = ta_find_kfib_tentry,
+ .dump_tinfo = ta_dump_kfib_tinfo,
+ .print_config = ta_print_kfib_config,
+};
+
+void
+ipfw_table_algo_init(struct ip_fw_chain *ch)
+{
+ size_t sz;
+
+ /*
+ * Register all algorithms presented here.
+ */
+ sz = sizeof(struct table_algo);
+ ipfw_add_table_algo(ch, &addr_radix, sz, &addr_radix.idx);
+ ipfw_add_table_algo(ch, &addr_hash, sz, &addr_hash.idx);
+ ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx);
+ ipfw_add_table_algo(ch, &number_array, sz, &number_array.idx);
+ ipfw_add_table_algo(ch, &flow_hash, sz, &flow_hash.idx);
+ ipfw_add_table_algo(ch, &addr_kfib, sz, &addr_kfib.idx);
+}
+
+void
+ipfw_table_algo_destroy(struct ip_fw_chain *ch)
+{
+
+ ipfw_del_table_algo(ch, addr_radix.idx);
+ ipfw_del_table_algo(ch, addr_hash.idx);
+ ipfw_del_table_algo(ch, iface_idx.idx);
+ ipfw_del_table_algo(ch, number_array.idx);
+ ipfw_del_table_algo(ch, flow_hash.idx);
+ ipfw_del_table_algo(ch, addr_kfib.idx);
+}
+
+
diff --git a/sys/netpfil/ipfw/ip_fw_table_value.c b/sys/netpfil/ipfw/ip_fw_table_value.c
new file mode 100644
index 0000000..1e780a4
--- /dev/null
+++ b/sys/netpfil/ipfw/ip_fw_table_value.c
@@ -0,0 +1,812 @@
+/*-
+ * Copyright (c) 2014 Yandex LLC
+ * Copyright (c) 2014 Alexander V. Chernikov
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c 270407 2014-08-23 12:41:39Z melifaro $");
+
+/*
+ * Multi-field value support for ipfw tables.
+ *
+ * This file contains necessary functions to convert
+ * large multi-field values into u32 indices suitable to be fed
+ * to various table algorithms. Other machinery like proper refcounting,
+ * internal structures resizing are also kept here.
+ */
+
+#include "opt_ipfw.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/hash.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
+#include <sys/rmlock.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/queue.h>
+#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */
+
+#include <netinet/in.h>
+#include <netinet/ip_var.h> /* struct ipfw_rule_ref */
+#include <netinet/ip_fw.h>
+
+#include <netpfil/ipfw/ip_fw_private.h>
+#include <netpfil/ipfw/ip_fw_table.h>
+
+static uint32_t hash_table_value(struct namedobj_instance *ni, void *key,
+ uint32_t kopt);
+static int cmp_table_value(struct named_object *no, void *key, uint32_t kopt);
+
+static int list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd);
+
+static struct ipfw_sopt_handler scodes[] = {
+ { IP_FW_TABLE_VLIST, 0, HDIR_GET, list_table_values },
+};
+
+#define CHAIN_TO_VI(chain) (CHAIN_TO_TCFG(chain)->valhash)
+
+struct table_val_link
+{
+ struct named_object no;
+ struct table_value *pval; /* Pointer to real table value */
+};
+#define VALDATA_START_SIZE 64 /* Allocate 64-items array by default */
+
+struct vdump_args {
+ struct ip_fw_chain *ch;
+ struct sockopt_data *sd;
+ struct table_value *pval;
+ int error;
+};
+
+
+static uint32_t
+hash_table_value(struct namedobj_instance *ni, void *key, uint32_t kopt)
+{
+
+ return (hash32_buf(key, 56, 0));
+}
+
+static int
+cmp_table_value(struct named_object *no, void *key, uint32_t kopt)
+{
+
+ return (memcmp(((struct table_val_link *)no)->pval, key, 56));
+}
+
+static void
+mask_table_value(struct table_value *src, struct table_value *dst,
+ uint32_t mask)
+{
+#define _MCPY(f, b) if ((mask & (b)) != 0) { dst->f = src->f; }
+
+ memset(dst, 0, sizeof(*dst));
+ _MCPY(tag, IPFW_VTYPE_TAG);
+ _MCPY(pipe, IPFW_VTYPE_PIPE);
+ _MCPY(divert, IPFW_VTYPE_DIVERT);
+ _MCPY(skipto, IPFW_VTYPE_SKIPTO);
+ _MCPY(netgraph, IPFW_VTYPE_NETGRAPH);
+ _MCPY(fib, IPFW_VTYPE_FIB);
+ _MCPY(nat, IPFW_VTYPE_NAT);
+ _MCPY(dscp, IPFW_VTYPE_DSCP);
+ _MCPY(nh4, IPFW_VTYPE_NH4);
+ _MCPY(nh6, IPFW_VTYPE_NH6);
+#undef _MCPY
+}
+
+static void
+get_value_ptrs(struct ip_fw_chain *ch, struct table_config *tc, int vshared,
+ struct table_value **ptv, struct namedobj_instance **pvi)
+{
+ struct table_value *pval;
+ struct namedobj_instance *vi;
+
+ if (vshared != 0) {
+ pval = (struct table_value *)ch->valuestate;
+ vi = CHAIN_TO_VI(ch);
+ } else {
+ pval = NULL;
+ vi = NULL;
+ //pval = (struct table_value *)&tc->ti.data;
+ }
+
+ if (ptv != NULL)
+ *ptv = pval;
+ if (pvi != NULL)
+ *pvi = vi;
+}
+
+/*
+ * Update pointers to real vaues after @pval change.
+ */
+static void
+update_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg)
+{
+ struct vdump_args *da;
+ struct table_val_link *ptv;
+ struct table_value *pval;
+
+ da = (struct vdump_args *)arg;
+ ptv = (struct table_val_link *)no;
+
+ pval = da->pval;
+ ptv->pval = &pval[ptv->no.kidx];
+
+}
+
+/*
+ * Grows value storage shared among all tables.
+ * Drops/reacquires UH locks.
+ * Notifies other running adds on @ch shared storage resize.
+ * Note function does not guarantee that free space
+ * will be available after invocation, so one caller needs
+ * to roll cycle himself.
+ *
+ * Returns 0 if case of no errors.
+ */
+static int
+resize_shared_value_storage(struct ip_fw_chain *ch)
+{
+ struct tables_config *tcfg;
+ struct namedobj_instance *vi;
+ struct table_value *pval, *valuestate, *old_valuestate;
+ void *new_idx;
+ struct vdump_args da;
+ int new_blocks;
+ int val_size, val_size_old;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ valuestate = NULL;
+ new_idx = NULL;
+
+ pval = (struct table_value *)ch->valuestate;
+ vi = CHAIN_TO_VI(ch);
+ tcfg = CHAIN_TO_TCFG(ch);
+
+ val_size = tcfg->val_size * 2;
+
+ if (val_size == (1 << 30))
+ return (ENOSPC);
+
+ IPFW_UH_WUNLOCK(ch);
+
+ valuestate = malloc(sizeof(struct table_value) * val_size, M_IPFW,
+ M_WAITOK | M_ZERO);
+ ipfw_objhash_bitmap_alloc(val_size, (void *)&new_idx,
+ &new_blocks);
+
+ IPFW_UH_WLOCK(ch);
+
+ /*
+ * Check if we still need to resize
+ */
+ if (tcfg->val_size >= val_size)
+ goto done;
+
+ /* Update pointers and notify everyone we're changing @ch */
+ pval = (struct table_value *)ch->valuestate;
+ rollback_toperation_state(ch, ch);
+
+ /* Good. Let's merge */
+ memcpy(valuestate, pval, sizeof(struct table_value) * tcfg->val_size);
+ ipfw_objhash_bitmap_merge(CHAIN_TO_VI(ch), &new_idx, &new_blocks);
+
+ IPFW_WLOCK(ch);
+ /* Change pointers */
+ old_valuestate = ch->valuestate;
+ ch->valuestate = valuestate;
+ valuestate = old_valuestate;
+ ipfw_objhash_bitmap_swap(CHAIN_TO_VI(ch), &new_idx, &new_blocks);
+
+ val_size_old = tcfg->val_size;
+ tcfg->val_size = val_size;
+ val_size = val_size_old;
+ IPFW_WUNLOCK(ch);
+ /* Update pointers to reflect resize */
+ memset(&da, 0, sizeof(da));
+ da.pval = (struct table_value *)ch->valuestate;
+ ipfw_objhash_foreach(vi, update_tvalue, &da);
+
+done:
+ free(valuestate, M_IPFW);
+ ipfw_objhash_bitmap_free(new_idx, new_blocks);
+
+ return (0);
+}
+
+/*
+ * Drops reference for table value with index @kidx, stored in @pval and
+ * @vi. Frees value if it has no references.
+ */
+static void
+unref_table_value(struct namedobj_instance *vi, struct table_value *pval,
+ uint32_t kidx)
+{
+ struct table_val_link *ptvl;
+
+ KASSERT(pval[kidx].refcnt > 0, ("Refcount is 0 on kidx %d", kidx));
+ if (--pval[kidx].refcnt > 0)
+ return;
+
+ /* Last reference, delete item */
+ ptvl = (struct table_val_link *)ipfw_objhash_lookup_kidx(vi, kidx);
+ KASSERT(ptvl != NULL, ("lookup on value kidx %d failed", kidx));
+ ipfw_objhash_del(vi, &ptvl->no);
+ ipfw_objhash_free_idx(vi, kidx);
+ free(ptvl, M_IPFW);
+}
+
+struct flush_args {
+ struct ip_fw_chain *ch;
+ struct table_algo *ta;
+ struct table_info *ti;
+ void *astate;
+ ipfw_obj_tentry tent;
+};
+
+static int
+unref_table_value_cb(void *e, void *arg)
+{
+ struct flush_args *fa;
+ struct ip_fw_chain *ch;
+ struct table_algo *ta;
+ ipfw_obj_tentry *tent;
+ int error;
+
+ fa = (struct flush_args *)arg;
+
+ ta = fa->ta;
+ memset(&fa->tent, 0, sizeof(fa->tent));
+ tent = &fa->tent;
+ error = ta->dump_tentry(fa->astate, fa->ti, e, tent);
+ if (error != 0)
+ return (error);
+
+ ch = fa->ch;
+
+ unref_table_value(CHAIN_TO_VI(ch),
+ (struct table_value *)ch->valuestate, tent->v.kidx);
+
+ return (0);
+}
+
+/*
+ * Drop references for each value used in @tc.
+ */
+void
+ipfw_unref_table_values(struct ip_fw_chain *ch, struct table_config *tc,
+ struct table_algo *ta, void *astate, struct table_info *ti)
+{
+ struct flush_args fa;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ memset(&fa, 0, sizeof(fa));
+ fa.ch = ch;
+ fa.ta = ta;
+ fa.astate = astate;
+ fa.ti = ti;
+
+ ta->foreach(astate, ti, unref_table_value_cb, &fa);
+}
+
+/*
+ * Table operation state handler.
+ * Called when we are going to change something in @tc which
+ * may lead to inconsistencies in on-going table data addition.
+ *
+ * Here we rollback all already committed state (table values, currently)
+ * and set "modified" field to non-zero value to indicate
+ * that we need to restart original operation.
+ */
+void
+rollback_table_values(struct tableop_state *ts)
+{
+ struct ip_fw_chain *ch;
+ struct table_value *pval;
+ struct tentry_info *ptei;
+ struct namedobj_instance *vi;
+ int i;
+
+ ch = ts->ch;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ /* Get current table value pointer */
+ get_value_ptrs(ch, ts->tc, ts->vshared, &pval, &vi);
+
+ for (i = 0; i < ts->count; i++) {
+ ptei = &ts->tei[i];
+
+ if (ptei->value == 0)
+ continue;
+
+ unref_table_value(vi, pval, ptei->value);
+ }
+}
+
+/*
+ * Allocate new value index in either shared or per-table array.
+ * Function may drop/reacquire UH lock.
+ *
+ * Returns 0 on success.
+ */
+static int
+alloc_table_vidx(struct ip_fw_chain *ch, struct tableop_state *ts,
+ struct namedobj_instance *vi, uint16_t *pvidx)
+{
+ int error, vlimit;
+ uint16_t vidx;
+
+ IPFW_UH_WLOCK_ASSERT(ch);
+
+ error = ipfw_objhash_alloc_idx(vi, &vidx);
+ if (error != 0) {
+
+ /*
+ * We need to resize array. This involves
+ * lock/unlock, so we need to check "modified"
+ * state.
+ */
+ ts->opstate.func(ts->tc, &ts->opstate);
+ error = resize_shared_value_storage(ch);
+ return (error); /* ts->modified should be set, we will restart */
+ }
+
+ vlimit = ts->ta->vlimit;
+ if (vlimit != 0 && vidx >= vlimit) {
+
+ /*
+ * Algorithm is not able to store given index.
+ * We have to rollback state, start using
+ * per-table value array or return error
+ * if we're already using it.
+ *
+ * TODO: do not rollback state if
+ * atomicity is not required.
+ */
+ if (ts->vshared != 0) {
+ /* shared -> per-table */
+ return (ENOSPC); /* TODO: proper error */
+ }
+
+ /* per-table. Fail for now. */
+ return (ENOSPC); /* TODO: proper error */
+ }
+
+ *pvidx = vidx;
+ return (0);
+}
+
+/*
+ * Drops value reference for unused values (updates, deletes, partially
+ * successful adds or rollbacks).
+ */
+void
+ipfw_garbage_table_values(struct ip_fw_chain *ch, struct table_config *tc,
+ struct tentry_info *tei, uint32_t count, int rollback)
+{
+ int i;
+ struct tentry_info *ptei;
+ struct table_value *pval;
+ struct namedobj_instance *vi;
+
+ /*
+ * We have two slightly different ADD cases here:
+ * either (1) we are successful / partially successful,
+ * in that case we need
+ * * to ignore ADDED entries values
+ * * rollback every other values (either UPDATED since
+ * old value has been stored there, or some failure like
+ * EXISTS or LIMIT or simply "ignored" case.
+ *
+ * (2): atomic rollback of partially successful operation
+ * in that case we simply need to unref all entries.
+ *
+ * DELETE case is simpler: no atomic support there, so
+ * we simply unref all non-zero values.
+ */
+
+ /*
+ * Get current table value pointers.
+ * XXX: Properly read vshared
+ */
+ get_value_ptrs(ch, tc, 1, &pval, &vi);
+
+ for (i = 0; i < count; i++) {
+ ptei = &tei[i];
+
+ if (ptei->value == 0) {
+
+ /*
+ * We may be deleting non-existing record.
+ * Skip.
+ */
+ continue;
+ }
+
+ if ((ptei->flags & TEI_FLAGS_ADDED) != 0 && rollback == 0) {
+ ptei->value = 0;
+ continue;
+ }
+
+ unref_table_value(vi, pval, ptei->value);
+ ptei->value = 0;
+ }
+}
+
+/*
+ * Main function used to link values of entries going to be added,
+ * to the index. Since we may perform many UH locks drops/acquires,
+ * handle changes by checking tablestate "modified" field.
+ *
+ * Success: return 0.
+ */
+int
+ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts)
+{
+ int error, i, found;
+ struct namedobj_instance *vi;
+ struct table_config *tc;
+ struct tentry_info *tei, *ptei;
+ uint32_t count, vlimit;
+ uint16_t vidx;
+ struct table_val_link *ptv;
+ struct table_value tval, *pval;
+
+ /*
+ * Stage 1: reference all existing values and
+ * save their indices.
+ */
+ IPFW_UH_WLOCK_ASSERT(ch);
+ get_value_ptrs(ch, ts->tc, ts->vshared, &pval, &vi);
+
+ error = 0;
+ found = 0;
+ vlimit = ts->ta->vlimit;
+ vidx = 0;
+ tc = ts->tc;
+ tei = ts->tei;
+ count = ts->count;
+ for (i = 0; i < count; i++) {
+ ptei = &tei[i];
+ ptei->value = 0; /* Ensure value is always 0 in the beginnig */
+ mask_table_value(ptei->pvalue, &tval, ts->vmask);
+ ptv = (struct table_val_link *)ipfw_objhash_lookup_name(vi, 0,
+ (char *)&tval);
+ if (ptv == NULL)
+ continue;
+ /* Deal with vlimit later */
+ if (vlimit > 0 && vlimit <= ptv->no.kidx)
+ continue;
+
+ /* Value found. Bump refcount */
+ ptv->pval->refcnt++;
+ ptei->value = ptv->no.kidx;
+ found++;
+ }
+
+ if (ts->count == found) {
+ /* We've found all values , no need ts create new ones */
+ return (0);
+ }
+
+ /*
+ * we have added some state here, let's attach operation
+ * state ts the list ts be able ts rollback if necessary.
+ */
+ add_toperation_state(ch, ts);
+ /* Ensure table won't disappear */
+ tc_ref(tc);
+ IPFW_UH_WUNLOCK(ch);
+
+ /*
+ * Stage 2: allocate objects for non-existing values.
+ */
+ for (i = 0; i < count; i++) {
+ ptei = &tei[i];
+ if (ptei->value != 0)
+ continue;
+ if (ptei->ptv != NULL)
+ continue;
+ ptei->ptv = malloc(sizeof(struct table_val_link), M_IPFW,
+ M_WAITOK | M_ZERO);
+ }
+
+ /*
+ * Stage 3: allocate index numbers for new values
+ * and link them to index.
+ */
+ IPFW_UH_WLOCK(ch);
+ tc_unref(tc);
+ del_toperation_state(ch, ts);
+ if (ts->modified != 0) {
+
+ /*
+ * In general, we should free all state/indexes here
+ * and return. However, we keep allocated state instead
+ * to ensure we achieve some progress on each restart.
+ */
+ return (0);
+ }
+
+ KASSERT(pval == ch->tablestate, ("resize_storage() notify failure"));
+
+ /* Let's try to link values */
+ for (i = 0; i < count; i++) {
+ ptei = &tei[i];
+ if (ptei->value != 0) {
+
+ /*
+ * We may be here after several process restarts,
+ * so we need to update all fields that might
+ * have changed.
+ */
+ ptv = (struct table_val_link *)ptei->ptv;
+ ptv->pval = &pval[i];
+ continue;
+ }
+
+ /* Check if record has appeared */
+ mask_table_value(ptei->pvalue, &tval, ts->vmask);
+ ptv = (struct table_val_link *)ipfw_objhash_lookup_name(vi, 0,
+ (char *)&tval);
+ if (ptv != NULL) {
+ ptv->pval->refcnt++;
+ ptei->value = ptv->no.kidx;
+ continue;
+ }
+
+ /* May perform UH unlock/lock */
+ error = alloc_table_vidx(ch, ts, vi, &vidx);
+ if (error != 0) {
+ ts->opstate.func(ts->tc, &ts->opstate);
+ return (error);
+ }
+ /* value storage resize has happened, return */
+ if (ts->modified != 0)
+ return (0);
+
+ /* Finally, we have allocated valid index, let's add entry */
+ ptei->value = vidx;
+ ptv = (struct table_val_link *)ptei->ptv;
+ ptei->ptv = NULL;
+
+ ptv->no.kidx = vidx;
+ ptv->no.name = (char *)&pval[vidx];
+ ptv->pval = &pval[vidx];
+ memcpy(ptv->pval, &tval, sizeof(struct table_value));
+ pval[vidx].refcnt = 1;
+ ipfw_objhash_add(vi, &ptv->no);
+ }
+
+ return (0);
+}
+
+/*
+ * Compability function used to import data from old
+ * IP_FW_TABLE_ADD / IP_FW_TABLE_XADD opcodes.
+ */
+void
+ipfw_import_table_value_legacy(uint32_t value, struct table_value *v)
+{
+
+ memset(v, 0, sizeof(*v));
+ v->tag = value;
+ v->pipe = value;
+ v->divert = value;
+ v->skipto = value;
+ v->netgraph = value;
+ v->fib = value;
+ v->nat = value;
+ v->nh4 = value; /* host format */
+ v->dscp = value;
+ v->limit = value;
+}
+
+/*
+ * Export data to legacy table dumps opcodes.
+ */
+uint32_t
+ipfw_export_table_value_legacy(struct table_value *v)
+{
+
+ /*
+ * TODO: provide more compatibility depending on
+ * vmask value.
+ */
+ return (v->tag);
+}
+
+/*
+ * Imports table value from current userland format.
+ * Saves value in kernel format to the same place.
+ */
+void
+ipfw_import_table_value_v1(ipfw_table_value *iv)
+{
+ struct table_value v;
+
+ memset(&v, 0, sizeof(v));
+ v.tag = iv->tag;
+ v.pipe = iv->pipe;
+ v.divert = iv->divert;
+ v.skipto = iv->skipto;
+ v.netgraph = iv->netgraph;
+ v.fib = iv->fib;
+ v.nat = iv->nat;
+ v.dscp = iv->dscp;
+ v.nh4 = iv->nh4;
+ v.nh6 = iv->nh6;
+ v.limit = iv->limit;
+
+ memcpy(iv, &v, sizeof(ipfw_table_value));
+}
+
+/*
+ * Export real table value @v to current userland format.
+ * Note that @v and @piv may point to the same memory.
+ */
+void
+ipfw_export_table_value_v1(struct table_value *v, ipfw_table_value *piv)
+{
+ ipfw_table_value iv;
+
+ memset(&iv, 0, sizeof(iv));
+ iv.tag = v->tag;
+ iv.pipe = v->pipe;
+ iv.divert = v->divert;
+ iv.skipto = v->skipto;
+ iv.netgraph = v->netgraph;
+ iv.fib = v->fib;
+ iv.nat = v->nat;
+ iv.dscp = v->dscp;
+ iv.limit = v->limit;
+ iv.nh4 = v->nh4;
+ iv.nh6 = v->nh6;
+
+ memcpy(piv, &iv, sizeof(iv));
+}
+
+/*
+ * Exports real value data into ipfw_table_value structure.
+ * Utilizes "spare1" field to store kernel index.
+ */
+static void
+dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg)
+{
+ struct vdump_args *da;
+ struct table_val_link *ptv;
+ struct table_value *v;
+
+ da = (struct vdump_args *)arg;
+ ptv = (struct table_val_link *)no;
+
+ v = (struct table_value *)ipfw_get_sopt_space(da->sd, sizeof(*v));
+ /* Out of memory, returning */
+ if (v == NULL) {
+ da->error = ENOMEM;
+ return;
+ }
+
+ memcpy(v, ptv->pval, sizeof(*v));
+ v->spare1 = ptv->no.kidx;
+}
+
+/*
+ * Dumps all shared/table value data
+ * Data layout (v1)(current):
+ * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_table_value x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ struct _ipfw_obj_lheader *olh;
+ struct namedobj_instance *vi;
+ struct vdump_args da;
+ uint32_t count, size;
+
+ olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
+ if (olh == NULL)
+ return (EINVAL);
+ if (sd->valsize < olh->size)
+ return (EINVAL);
+
+ IPFW_UH_RLOCK(ch);
+ vi = CHAIN_TO_VI(ch);
+
+ count = ipfw_objhash_count(vi);
+ size = count * sizeof(ipfw_table_value) + sizeof(ipfw_obj_lheader);
+
+ /* Fill in header regadless of buffer size */
+ olh->count = count;
+ olh->objsize = sizeof(ipfw_table_value);
+
+ if (size > olh->size) {
+ olh->size = size;
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOMEM);
+ }
+ olh->size = size;
+
+ /*
+ * Do the actual value dump
+ */
+ memset(&da, 0, sizeof(da));
+ da.ch = ch;
+ da.sd = sd;
+ ipfw_objhash_foreach(vi, dump_tvalue, &da);
+
+ IPFW_UH_RUNLOCK(ch);
+
+ return (0);
+}
+
+void
+ipfw_table_value_init(struct ip_fw_chain *ch, int first)
+{
+ struct tables_config *tcfg;
+
+ ch->valuestate = malloc(VALDATA_START_SIZE * sizeof(struct table_value),
+ M_IPFW, M_WAITOK | M_ZERO);
+
+ tcfg = ch->tblcfg;
+
+ tcfg->val_size = VALDATA_START_SIZE;
+ tcfg->valhash = ipfw_objhash_create(tcfg->val_size);
+ ipfw_objhash_set_funcs(tcfg->valhash, hash_table_value,
+ cmp_table_value);
+
+ IPFW_ADD_SOPT_HANDLER(first, scodes);
+}
+
+static void
+destroy_value(struct namedobj_instance *ni, struct named_object *no,
+ void *arg)
+{
+
+ free(no, M_IPFW);
+}
+
+void
+ipfw_table_value_destroy(struct ip_fw_chain *ch, int last)
+{
+
+ IPFW_DEL_SOPT_HANDLER(last, scodes);
+
+ free(ch->valuestate, M_IPFW);
+ ipfw_objhash_foreach(CHAIN_TO_VI(ch), destroy_value, ch);
+ ipfw_objhash_destroy(CHAIN_TO_VI(ch));
+}
+
diff --git a/sys/ofed/drivers/net/mlx4/mlx4.h b/sys/ofed/drivers/net/mlx4/mlx4.h
index 624a61c..47fde25 100644
--- a/sys/ofed/drivers/net/mlx4/mlx4.h
+++ b/sys/ofed/drivers/net/mlx4/mlx4.h
@@ -1234,6 +1234,7 @@ int mlx4_trans_to_dmfs_attach(struct mlx4_dev *dev, struct mlx4_qp *qp,
u8 gid[16], u8 port,
int block_mcast_loopback,
enum mlx4_protocol prot, u64 *reg_id);
+int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
diff --git a/sys/ofed/include/linux/mlx4/device.h b/sys/ofed/include/linux/mlx4/device.h
index a1beedb..c1095a5 100644
--- a/sys/ofed/include/linux/mlx4/device.h
+++ b/sys/ofed/include/linux/mlx4/device.h
@@ -1208,7 +1208,6 @@ int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port);
int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port);
int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port);
int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port);
-int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac);
void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac);
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
deleted file mode 100644
index 848af79..0000000
--- a/sys/pc98/pc98/machdep.c
+++ /dev/null
@@ -1,2999 +0,0 @@
-/*-
- * Copyright (c) 1992 Terrence R. Lambert.
- * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_apic.h"
-#include "opt_atpic.h"
-#include "opt_compat.h"
-#include "opt_cpu.h"
-#include "opt_ddb.h"
-#include "opt_inet.h"
-#include "opt_isa.h"
-#include "opt_kstack_pages.h"
-#include "opt_maxmem.h"
-#include "opt_mp_watchdog.h"
-#include "opt_npx.h"
-#include "opt_perfmon.h"
-
-#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/systm.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/bus.h>
-#include <sys/callout.h>
-#include <sys/cons.h>
-#include <sys/cpu.h>
-#include <sys/eventhandler.h>
-#include <sys/exec.h>
-#include <sys/imgact.h>
-#include <sys/kdb.h>
-#include <sys/kernel.h>
-#include <sys/ktr.h>
-#include <sys/linker.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/memrange.h>
-#include <sys/msgbuf.h>
-#include <sys/mutex.h>
-#include <sys/pcpu.h>
-#include <sys/ptrace.h>
-#include <sys/reboot.h>
-#include <sys/rwlock.h>
-#include <sys/sched.h>
-#include <sys/signalvar.h>
-#ifdef SMP
-#include <sys/smp.h>
-#endif
-#include <sys/syscallsubr.h>
-#include <sys/sysctl.h>
-#include <sys/sysent.h>
-#include <sys/sysproto.h>
-#include <sys/ucontext.h>
-#include <sys/vmmeter.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-#include <vm/vm_map.h>
-#include <vm/vm_object.h>
-#include <vm/vm_pager.h>
-#include <vm/vm_param.h>
-
-#ifdef DDB
-#ifndef KDB
-#error KDB must be enabled in order for DDB to work!
-#endif
-#include <ddb/ddb.h>
-#include <ddb/db_sym.h>
-#endif
-
-#include <pc98/pc98/pc98_machdep.h>
-
-#include <net/netisr.h>
-
-#include <machine/bootinfo.h>
-#include <machine/clock.h>
-#include <machine/cpu.h>
-#include <machine/cputypes.h>
-#include <machine/intr_machdep.h>
-#include <x86/mca.h>
-#include <machine/md_var.h>
-#include <machine/mp_watchdog.h>
-#include <machine/pc/bios.h>
-#include <machine/pcb.h>
-#include <machine/pcb_ext.h>
-#include <machine/proc.h>
-#include <machine/reg.h>
-#include <machine/sigframe.h>
-#include <machine/specialreg.h>
-#include <machine/vm86.h>
-#include <x86/init.h>
-#ifdef PERFMON
-#include <machine/perfmon.h>
-#endif
-#ifdef SMP
-#include <machine/smp.h>
-#endif
-
-#ifdef DEV_APIC
-#include <x86/apicvar.h>
-#endif
-
-#ifdef DEV_ISA
-#include <x86/isa/icu.h>
-#endif
-
-/* Sanity check for __curthread() */
-CTASSERT(offsetof(struct pcpu, pc_curthread) == 0);
-
-extern void init386(int first);
-extern void dblfault_handler(void);
-
-#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
-#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
-
-#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
-#define CPU_ENABLE_SSE
-#endif
-
-static void cpu_startup(void *);
-static void fpstate_drop(struct thread *td);
-static void get_fpcontext(struct thread *td, mcontext_t *mcp);
-static int set_fpcontext(struct thread *td, const mcontext_t *mcp);
-#ifdef CPU_ENABLE_SSE
-static void set_fpregs_xmm(struct save87 *, struct savexmm *);
-static void fill_fpregs_xmm(struct savexmm *, struct save87 *);
-#endif /* CPU_ENABLE_SSE */
-SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
-
-int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */
-int need_post_dma_flush; /* If 1, use invd after DMA transfer. */
-
-int _udatasel, _ucodesel;
-u_int basemem;
-
-static int ispc98 = 1;
-SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, "");
-
-int cold = 1;
-
-#ifdef COMPAT_43
-static void osendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask);
-#endif
-#ifdef COMPAT_FREEBSD4
-static void freebsd4_sendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask);
-#endif
-
-long Maxmem = 0;
-long realmem = 0;
-
-/*
- * The number of PHYSMAP entries must be one less than the number of
- * PHYSSEG entries because the PHYSMAP entry that spans the largest
- * physical address that is accessible by ISA DMA is split into two
- * PHYSSEG entries.
- */
-#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1))
-
-vm_paddr_t phys_avail[PHYSMAP_SIZE + 2];
-vm_paddr_t dump_avail[PHYSMAP_SIZE + 2];
-
-/* must be 2 less so 0 0 can signal end of chunks */
-#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(phys_avail[0])) - 2)
-#define DUMP_AVAIL_ARRAY_END ((sizeof(dump_avail) / sizeof(dump_avail[0])) - 2)
-
-struct kva_md_info kmi;
-
-static struct trapframe proc0_tf;
-struct pcpu __pcpu[MAXCPU];
-
-struct mtx icu_lock;
-
-struct mem_range_softc mem_range_softc;
-
- /* Default init_ops implementation. */
- struct init_ops init_ops = {
- .early_clock_source_init = i8254_init,
- .early_delay = i8254_delay,
- };
-
-static void
-cpu_startup(dummy)
- void *dummy;
-{
- uintmax_t memsize;
-
- /*
- * Good {morning,afternoon,evening,night}.
- */
- startrtclock();
- printcpuinfo();
- panicifcpuunsupported();
-#ifdef PERFMON
- perfmon_init();
-#endif
- realmem = Maxmem;
-
- /*
- * Display physical memory.
- */
- memsize = ptoa((uintmax_t)Maxmem);
- printf("real memory = %ju (%ju MB)\n", memsize, memsize >> 20);
-
- /*
- * Display any holes after the first chunk of extended memory.
- */
- if (bootverbose) {
- int indx;
-
- printf("Physical memory chunk(s):\n");
- for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
- vm_paddr_t size;
-
- size = phys_avail[indx + 1] - phys_avail[indx];
- printf(
- "0x%016jx - 0x%016jx, %ju bytes (%ju pages)\n",
- (uintmax_t)phys_avail[indx],
- (uintmax_t)phys_avail[indx + 1] - 1,
- (uintmax_t)size, (uintmax_t)size / PAGE_SIZE);
- }
- }
-
- vm_ksubmap_init(&kmi);
-
- printf("avail memory = %ju (%ju MB)\n",
- ptoa((uintmax_t)vm_cnt.v_free_count),
- ptoa((uintmax_t)vm_cnt.v_free_count) / 1048576);
-
- /*
- * Set up buffers, so they can be used to read disk labels.
- */
- bufinit();
- vm_pager_bufferinit();
- cpu_setregs();
-}
-
-/*
- * Send an interrupt to process.
- *
- * Stack is set up to allow sigcode stored
- * at top to call routine, followed by kcall
- * to sigreturn routine below. After sigreturn
- * resets the signal mask, the stack, and the
- * frame pointer, it returns to the user
- * specified pc, psl.
- */
-#ifdef COMPAT_43
-static void
-osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
-{
- struct osigframe sf, *fp;
- struct proc *p;
- struct thread *td;
- struct sigacts *psp;
- struct trapframe *regs;
- int sig;
- int oonstack;
-
- td = curthread;
- p = td->td_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
- sig = ksi->ksi_signo;
- psp = p->p_sigacts;
- mtx_assert(&psp->ps_mtx, MA_OWNED);
- regs = td->td_frame;
- oonstack = sigonstack(regs->tf_esp);
-
- /* Allocate space for the signal handler context. */
- if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
- SIGISMEMBER(psp->ps_sigonstack, sig)) {
- fp = (struct osigframe *)(td->td_sigstk.ss_sp +
- td->td_sigstk.ss_size - sizeof(struct osigframe));
-#if defined(COMPAT_43)
- td->td_sigstk.ss_flags |= SS_ONSTACK;
-#endif
- } else
- fp = (struct osigframe *)regs->tf_esp - 1;
-
- /* Translate the signal if appropriate. */
- if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
- sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
-
- /* Build the argument list for the signal handler. */
- sf.sf_signum = sig;
- sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
- bzero(&sf.sf_siginfo, sizeof(sf.sf_siginfo));
- if (SIGISMEMBER(psp->ps_siginfo, sig)) {
- /* Signal handler installed with SA_SIGINFO. */
- sf.sf_arg2 = (register_t)&fp->sf_siginfo;
- sf.sf_siginfo.si_signo = sig;
- sf.sf_siginfo.si_code = ksi->ksi_code;
- sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher;
- sf.sf_addr = 0;
- } else {
- /* Old FreeBSD-style arguments. */
- sf.sf_arg2 = ksi->ksi_code;
- sf.sf_addr = (register_t)ksi->ksi_addr;
- sf.sf_ahu.sf_handler = catcher;
- }
- mtx_unlock(&psp->ps_mtx);
- PROC_UNLOCK(p);
-
- /* Save most if not all of trap frame. */
- sf.sf_siginfo.si_sc.sc_eax = regs->tf_eax;
- sf.sf_siginfo.si_sc.sc_ebx = regs->tf_ebx;
- sf.sf_siginfo.si_sc.sc_ecx = regs->tf_ecx;
- sf.sf_siginfo.si_sc.sc_edx = regs->tf_edx;
- sf.sf_siginfo.si_sc.sc_esi = regs->tf_esi;
- sf.sf_siginfo.si_sc.sc_edi = regs->tf_edi;
- sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
- sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
- sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
- sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
- sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
- sf.sf_siginfo.si_sc.sc_gs = rgs();
- sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
-
- /* Build the signal context to be used by osigreturn(). */
- sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
- SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
- sf.sf_siginfo.si_sc.sc_sp = regs->tf_esp;
- sf.sf_siginfo.si_sc.sc_fp = regs->tf_ebp;
- sf.sf_siginfo.si_sc.sc_pc = regs->tf_eip;
- sf.sf_siginfo.si_sc.sc_ps = regs->tf_eflags;
- sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
- sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
-
- /*
- * If we're a vm86 process, we want to save the segment registers.
- * We also change eflags to be our emulated eflags, not the actual
- * eflags.
- */
- if (regs->tf_eflags & PSL_VM) {
- /* XXX confusing names: `tf' isn't a trapframe; `regs' is. */
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
-
- sf.sf_siginfo.si_sc.sc_gs = tf->tf_vm86_gs;
- sf.sf_siginfo.si_sc.sc_fs = tf->tf_vm86_fs;
- sf.sf_siginfo.si_sc.sc_es = tf->tf_vm86_es;
- sf.sf_siginfo.si_sc.sc_ds = tf->tf_vm86_ds;
-
- if (vm86->vm86_has_vme == 0)
- sf.sf_siginfo.si_sc.sc_ps =
- (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
- (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
- /* See sendsig() for comments. */
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
- }
-
- /*
- * Copy the sigframe out to the user's stack.
- */
- if (copyout(&sf, fp, sizeof(*fp)) != 0) {
-#ifdef DEBUG
- printf("process %ld has trashed its stack\n", (long)p->p_pid);
-#endif
- PROC_LOCK(p);
- sigexit(td, SIGILL);
- }
-
- regs->tf_esp = (int)fp;
- if (p->p_sysent->sv_sigcode_base != 0) {
- regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode -
- szosigcode;
- } else {
- /* a.out sysentvec does not use shared page */
- regs->tf_eip = p->p_sysent->sv_psstrings - szosigcode;
- }
- regs->tf_eflags &= ~(PSL_T | PSL_D);
- regs->tf_cs = _ucodesel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- load_gs(_udatasel);
- regs->tf_ss = _udatasel;
- PROC_LOCK(p);
- mtx_lock(&psp->ps_mtx);
-}
-#endif /* COMPAT_43 */
-
-#ifdef COMPAT_FREEBSD4
-static void
-freebsd4_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
-{
- struct sigframe4 sf, *sfp;
- struct proc *p;
- struct thread *td;
- struct sigacts *psp;
- struct trapframe *regs;
- int sig;
- int oonstack;
-
- td = curthread;
- p = td->td_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
- sig = ksi->ksi_signo;
- psp = p->p_sigacts;
- mtx_assert(&psp->ps_mtx, MA_OWNED);
- regs = td->td_frame;
- oonstack = sigonstack(regs->tf_esp);
-
- /* Save user context. */
- bzero(&sf, sizeof(sf));
- sf.sf_uc.uc_sigmask = *mask;
- sf.sf_uc.uc_stack = td->td_sigstk;
- sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
- ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
- sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
- sf.sf_uc.uc_mcontext.mc_gs = rgs();
- bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
- bzero(sf.sf_uc.uc_mcontext.mc_fpregs,
- sizeof(sf.sf_uc.uc_mcontext.mc_fpregs));
- bzero(sf.sf_uc.uc_mcontext.__spare__,
- sizeof(sf.sf_uc.uc_mcontext.__spare__));
- bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
-
- /* Allocate space for the signal handler context. */
- if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
- SIGISMEMBER(psp->ps_sigonstack, sig)) {
- sfp = (struct sigframe4 *)(td->td_sigstk.ss_sp +
- td->td_sigstk.ss_size - sizeof(struct sigframe4));
-#if defined(COMPAT_43)
- td->td_sigstk.ss_flags |= SS_ONSTACK;
-#endif
- } else
- sfp = (struct sigframe4 *)regs->tf_esp - 1;
-
- /* Translate the signal if appropriate. */
- if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
- sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
-
- /* Build the argument list for the signal handler. */
- sf.sf_signum = sig;
- sf.sf_ucontext = (register_t)&sfp->sf_uc;
- bzero(&sf.sf_si, sizeof(sf.sf_si));
- if (SIGISMEMBER(psp->ps_siginfo, sig)) {
- /* Signal handler installed with SA_SIGINFO. */
- sf.sf_siginfo = (register_t)&sfp->sf_si;
- sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
-
- /* Fill in POSIX parts */
- sf.sf_si.si_signo = sig;
- sf.sf_si.si_code = ksi->ksi_code;
- sf.sf_si.si_addr = ksi->ksi_addr;
- } else {
- /* Old FreeBSD-style arguments. */
- sf.sf_siginfo = ksi->ksi_code;
- sf.sf_addr = (register_t)ksi->ksi_addr;
- sf.sf_ahu.sf_handler = catcher;
- }
- mtx_unlock(&psp->ps_mtx);
- PROC_UNLOCK(p);
-
- /*
- * If we're a vm86 process, we want to save the segment registers.
- * We also change eflags to be our emulated eflags, not the actual
- * eflags.
- */
- if (regs->tf_eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
-
- sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
- sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
- sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
- sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
-
- if (vm86->vm86_has_vme == 0)
- sf.sf_uc.uc_mcontext.mc_eflags =
- (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
- (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
- /*
- * Clear PSL_NT to inhibit T_TSSFLT faults on return from
- * syscalls made by the signal handler. This just avoids
- * wasting time for our lazy fixup of such faults. PSL_NT
- * does nothing in vm86 mode, but vm86 programs can set it
- * almost legitimately in probes for old cpu types.
- */
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
- }
-
- /*
- * Copy the sigframe out to the user's stack.
- */
- if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
-#ifdef DEBUG
- printf("process %ld has trashed its stack\n", (long)p->p_pid);
-#endif
- PROC_LOCK(p);
- sigexit(td, SIGILL);
- }
-
- regs->tf_esp = (int)sfp;
- regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode -
- szfreebsd4_sigcode;
- regs->tf_eflags &= ~(PSL_T | PSL_D);
- regs->tf_cs = _ucodesel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- regs->tf_ss = _udatasel;
- PROC_LOCK(p);
- mtx_lock(&psp->ps_mtx);
-}
-#endif /* COMPAT_FREEBSD4 */
-
-void
-sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
-{
- struct sigframe sf, *sfp;
- struct proc *p;
- struct thread *td;
- struct sigacts *psp;
- char *sp;
- struct trapframe *regs;
- struct segment_descriptor *sdp;
- int sig;
- int oonstack;
-
- td = curthread;
- p = td->td_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
- sig = ksi->ksi_signo;
- psp = p->p_sigacts;
- mtx_assert(&psp->ps_mtx, MA_OWNED);
-#ifdef COMPAT_FREEBSD4
- if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
- freebsd4_sendsig(catcher, ksi, mask);
- return;
- }
-#endif
-#ifdef COMPAT_43
- if (SIGISMEMBER(psp->ps_osigset, sig)) {
- osendsig(catcher, ksi, mask);
- return;
- }
-#endif
- regs = td->td_frame;
- oonstack = sigonstack(regs->tf_esp);
-
- /* Save user context. */
- bzero(&sf, sizeof(sf));
- sf.sf_uc.uc_sigmask = *mask;
- sf.sf_uc.uc_stack = td->td_sigstk;
- sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
- ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
- sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
- sf.sf_uc.uc_mcontext.mc_gs = rgs();
- bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
- sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
- get_fpcontext(td, &sf.sf_uc.uc_mcontext);
- fpstate_drop(td);
- /*
- * Unconditionally fill the fsbase and gsbase into the mcontext.
- */
- sdp = &td->td_pcb->pcb_fsd;
- sf.sf_uc.uc_mcontext.mc_fsbase = sdp->sd_hibase << 24 |
- sdp->sd_lobase;
- sdp = &td->td_pcb->pcb_gsd;
- sf.sf_uc.uc_mcontext.mc_gsbase = sdp->sd_hibase << 24 |
- sdp->sd_lobase;
- sf.sf_uc.uc_mcontext.mc_flags = 0;
- bzero(sf.sf_uc.uc_mcontext.mc_spare2,
- sizeof(sf.sf_uc.uc_mcontext.mc_spare2));
- bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
-
- /* Allocate space for the signal handler context. */
- if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
- SIGISMEMBER(psp->ps_sigonstack, sig)) {
- sp = td->td_sigstk.ss_sp +
- td->td_sigstk.ss_size - sizeof(struct sigframe);
-#if defined(COMPAT_43)
- td->td_sigstk.ss_flags |= SS_ONSTACK;
-#endif
- } else
- sp = (char *)regs->tf_esp - sizeof(struct sigframe);
- /* Align to 16 bytes. */
- sfp = (struct sigframe *)((unsigned int)sp & ~0xF);
-
- /* Translate the signal if appropriate. */
- if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
- sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
-
- /* Build the argument list for the signal handler. */
- sf.sf_signum = sig;
- sf.sf_ucontext = (register_t)&sfp->sf_uc;
- bzero(&sf.sf_si, sizeof(sf.sf_si));
- if (SIGISMEMBER(psp->ps_siginfo, sig)) {
- /* Signal handler installed with SA_SIGINFO. */
- sf.sf_siginfo = (register_t)&sfp->sf_si;
- sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
-
- /* Fill in POSIX parts */
- sf.sf_si = ksi->ksi_info;
- sf.sf_si.si_signo = sig; /* maybe a translated signal */
- } else {
- /* Old FreeBSD-style arguments. */
- sf.sf_siginfo = ksi->ksi_code;
- sf.sf_addr = (register_t)ksi->ksi_addr;
- sf.sf_ahu.sf_handler = catcher;
- }
- mtx_unlock(&psp->ps_mtx);
- PROC_UNLOCK(p);
-
- /*
- * If we're a vm86 process, we want to save the segment registers.
- * We also change eflags to be our emulated eflags, not the actual
- * eflags.
- */
- if (regs->tf_eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
-
- sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
- sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
- sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
- sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
-
- if (vm86->vm86_has_vme == 0)
- sf.sf_uc.uc_mcontext.mc_eflags =
- (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
- (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
- /*
- * Clear PSL_NT to inhibit T_TSSFLT faults on return from
- * syscalls made by the signal handler. This just avoids
- * wasting time for our lazy fixup of such faults. PSL_NT
- * does nothing in vm86 mode, but vm86 programs can set it
- * almost legitimately in probes for old cpu types.
- */
- tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
- }
-
- /*
- * Copy the sigframe out to the user's stack.
- */
- if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
-#ifdef DEBUG
- printf("process %ld has trashed its stack\n", (long)p->p_pid);
-#endif
- PROC_LOCK(p);
- sigexit(td, SIGILL);
- }
-
- regs->tf_esp = (int)sfp;
- regs->tf_eip = p->p_sysent->sv_sigcode_base;
- if (regs->tf_eip == 0)
- regs->tf_eip = p->p_sysent->sv_psstrings - szsigcode;
- regs->tf_eflags &= ~(PSL_T | PSL_D);
- regs->tf_cs = _ucodesel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- regs->tf_ss = _udatasel;
- PROC_LOCK(p);
- mtx_lock(&psp->ps_mtx);
-}
-
-/*
- * System call to cleanup state after a signal
- * has been taken. Reset signal mask and
- * stack state from context left by sendsig (above).
- * Return to previous pc and psl as specified by
- * context left by sendsig. Check carefully to
- * make sure that the user has not modified the
- * state to gain improper privileges.
- *
- * MPSAFE
- */
-#ifdef COMPAT_43
-int
-osigreturn(td, uap)
- struct thread *td;
- struct osigreturn_args /* {
- struct osigcontext *sigcntxp;
- } */ *uap;
-{
- struct osigcontext sc;
- struct trapframe *regs;
- struct osigcontext *scp;
- int eflags, error;
- ksiginfo_t ksi;
-
- regs = td->td_frame;
- error = copyin(uap->sigcntxp, &sc, sizeof(sc));
- if (error != 0)
- return (error);
- scp = &sc;
- eflags = scp->sc_ps;
- if (eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86;
-
- /*
- * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
- * set up the vm86 area, and we can't enter vm86 mode.
- */
- if (td->td_pcb->pcb_ext == 0)
- return (EINVAL);
- vm86 = &td->td_pcb->pcb_ext->ext_vm86;
- if (vm86->vm86_inited == 0)
- return (EINVAL);
-
- /* Go back to user mode if both flags are set. */
- if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) {
- ksiginfo_init_trap(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_code = BUS_OBJERR;
- ksi.ksi_addr = (void *)regs->tf_eip;
- trapsignal(td, &ksi);
- }
-
- if (vm86->vm86_has_vme) {
- eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
- (eflags & VME_USERCHANGE) | PSL_VM;
- } else {
- vm86->vm86_eflags = eflags; /* save VIF, VIP */
- eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
- (eflags & VM_USERCHANGE) | PSL_VM;
- }
- tf->tf_vm86_ds = scp->sc_ds;
- tf->tf_vm86_es = scp->sc_es;
- tf->tf_vm86_fs = scp->sc_fs;
- tf->tf_vm86_gs = scp->sc_gs;
- tf->tf_ds = _udatasel;
- tf->tf_es = _udatasel;
- tf->tf_fs = _udatasel;
- } else {
- /*
- * Don't allow users to change privileged or reserved flags.
- */
- if (!EFL_SECURE(eflags, regs->tf_eflags)) {
- return (EINVAL);
- }
-
- /*
- * Don't allow users to load a valid privileged %cs. Let the
- * hardware check for invalid selectors, excess privilege in
- * other selectors, invalid %eip's and invalid %esp's.
- */
- if (!CS_SECURE(scp->sc_cs)) {
- ksiginfo_init_trap(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_code = BUS_OBJERR;
- ksi.ksi_trapno = T_PROTFLT;
- ksi.ksi_addr = (void *)regs->tf_eip;
- trapsignal(td, &ksi);
- return (EINVAL);
- }
- regs->tf_ds = scp->sc_ds;
- regs->tf_es = scp->sc_es;
- regs->tf_fs = scp->sc_fs;
- }
-
- /* Restore remaining registers. */
- regs->tf_eax = scp->sc_eax;
- regs->tf_ebx = scp->sc_ebx;
- regs->tf_ecx = scp->sc_ecx;
- regs->tf_edx = scp->sc_edx;
- regs->tf_esi = scp->sc_esi;
- regs->tf_edi = scp->sc_edi;
- regs->tf_cs = scp->sc_cs;
- regs->tf_ss = scp->sc_ss;
- regs->tf_isp = scp->sc_isp;
- regs->tf_ebp = scp->sc_fp;
- regs->tf_esp = scp->sc_sp;
- regs->tf_eip = scp->sc_pc;
- regs->tf_eflags = eflags;
-
-#if defined(COMPAT_43)
- if (scp->sc_onstack & 1)
- td->td_sigstk.ss_flags |= SS_ONSTACK;
- else
- td->td_sigstk.ss_flags &= ~SS_ONSTACK;
-#endif
- kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL,
- SIGPROCMASK_OLD);
- return (EJUSTRETURN);
-}
-#endif /* COMPAT_43 */
-
-#ifdef COMPAT_FREEBSD4
-/*
- * MPSAFE
- */
-int
-freebsd4_sigreturn(td, uap)
- struct thread *td;
- struct freebsd4_sigreturn_args /* {
- const ucontext4 *sigcntxp;
- } */ *uap;
-{
- struct ucontext4 uc;
- struct trapframe *regs;
- struct ucontext4 *ucp;
- int cs, eflags, error;
- ksiginfo_t ksi;
-
- error = copyin(uap->sigcntxp, &uc, sizeof(uc));
- if (error != 0)
- return (error);
- ucp = &uc;
- regs = td->td_frame;
- eflags = ucp->uc_mcontext.mc_eflags;
- if (eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86;
-
- /*
- * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
- * set up the vm86 area, and we can't enter vm86 mode.
- */
- if (td->td_pcb->pcb_ext == 0)
- return (EINVAL);
- vm86 = &td->td_pcb->pcb_ext->ext_vm86;
- if (vm86->vm86_inited == 0)
- return (EINVAL);
-
- /* Go back to user mode if both flags are set. */
- if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) {
- ksiginfo_init_trap(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_code = BUS_OBJERR;
- ksi.ksi_addr = (void *)regs->tf_eip;
- trapsignal(td, &ksi);
- }
- if (vm86->vm86_has_vme) {
- eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
- (eflags & VME_USERCHANGE) | PSL_VM;
- } else {
- vm86->vm86_eflags = eflags; /* save VIF, VIP */
- eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
- (eflags & VM_USERCHANGE) | PSL_VM;
- }
- bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
- tf->tf_eflags = eflags;
- tf->tf_vm86_ds = tf->tf_ds;
- tf->tf_vm86_es = tf->tf_es;
- tf->tf_vm86_fs = tf->tf_fs;
- tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
- tf->tf_ds = _udatasel;
- tf->tf_es = _udatasel;
- tf->tf_fs = _udatasel;
- } else {
- /*
- * Don't allow users to change privileged or reserved flags.
- */
- if (!EFL_SECURE(eflags, regs->tf_eflags)) {
- uprintf("pid %d (%s): freebsd4_sigreturn eflags = 0x%x\n",
- td->td_proc->p_pid, td->td_name, eflags);
- return (EINVAL);
- }
-
- /*
- * Don't allow users to load a valid privileged %cs. Let the
- * hardware check for invalid selectors, excess privilege in
- * other selectors, invalid %eip's and invalid %esp's.
- */
- cs = ucp->uc_mcontext.mc_cs;
- if (!CS_SECURE(cs)) {
- uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n",
- td->td_proc->p_pid, td->td_name, cs);
- ksiginfo_init_trap(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_code = BUS_OBJERR;
- ksi.ksi_trapno = T_PROTFLT;
- ksi.ksi_addr = (void *)regs->tf_eip;
- trapsignal(td, &ksi);
- return (EINVAL);
- }
-
- bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
- }
-
-#if defined(COMPAT_43)
- if (ucp->uc_mcontext.mc_onstack & 1)
- td->td_sigstk.ss_flags |= SS_ONSTACK;
- else
- td->td_sigstk.ss_flags &= ~SS_ONSTACK;
-#endif
- kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
- return (EJUSTRETURN);
-}
-#endif /* COMPAT_FREEBSD4 */
-
-/*
- * MPSAFE
- */
-int
-sys_sigreturn(td, uap)
- struct thread *td;
- struct sigreturn_args /* {
- const struct __ucontext *sigcntxp;
- } */ *uap;
-{
- ucontext_t uc;
- struct trapframe *regs;
- ucontext_t *ucp;
- int cs, eflags, error, ret;
- ksiginfo_t ksi;
-
- error = copyin(uap->sigcntxp, &uc, sizeof(uc));
- if (error != 0)
- return (error);
- ucp = &uc;
- regs = td->td_frame;
- eflags = ucp->uc_mcontext.mc_eflags;
- if (eflags & PSL_VM) {
- struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
- struct vm86_kernel *vm86;
-
- /*
- * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
- * set up the vm86 area, and we can't enter vm86 mode.
- */
- if (td->td_pcb->pcb_ext == 0)
- return (EINVAL);
- vm86 = &td->td_pcb->pcb_ext->ext_vm86;
- if (vm86->vm86_inited == 0)
- return (EINVAL);
-
- /* Go back to user mode if both flags are set. */
- if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) {
- ksiginfo_init_trap(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_code = BUS_OBJERR;
- ksi.ksi_addr = (void *)regs->tf_eip;
- trapsignal(td, &ksi);
- }
-
- if (vm86->vm86_has_vme) {
- eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
- (eflags & VME_USERCHANGE) | PSL_VM;
- } else {
- vm86->vm86_eflags = eflags; /* save VIF, VIP */
- eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
- (eflags & VM_USERCHANGE) | PSL_VM;
- }
- bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
- tf->tf_eflags = eflags;
- tf->tf_vm86_ds = tf->tf_ds;
- tf->tf_vm86_es = tf->tf_es;
- tf->tf_vm86_fs = tf->tf_fs;
- tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
- tf->tf_ds = _udatasel;
- tf->tf_es = _udatasel;
- tf->tf_fs = _udatasel;
- } else {
- /*
- * Don't allow users to change privileged or reserved flags.
- */
- if (!EFL_SECURE(eflags, regs->tf_eflags)) {
- uprintf("pid %d (%s): sigreturn eflags = 0x%x\n",
- td->td_proc->p_pid, td->td_name, eflags);
- return (EINVAL);
- }
-
- /*
- * Don't allow users to load a valid privileged %cs. Let the
- * hardware check for invalid selectors, excess privilege in
- * other selectors, invalid %eip's and invalid %esp's.
- */
- cs = ucp->uc_mcontext.mc_cs;
- if (!CS_SECURE(cs)) {
- uprintf("pid %d (%s): sigreturn cs = 0x%x\n",
- td->td_proc->p_pid, td->td_name, cs);
- ksiginfo_init_trap(&ksi);
- ksi.ksi_signo = SIGBUS;
- ksi.ksi_code = BUS_OBJERR;
- ksi.ksi_trapno = T_PROTFLT;
- ksi.ksi_addr = (void *)regs->tf_eip;
- trapsignal(td, &ksi);
- return (EINVAL);
- }
-
- ret = set_fpcontext(td, &ucp->uc_mcontext);
- if (ret != 0)
- return (ret);
- bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
- }
-
-#if defined(COMPAT_43)
- if (ucp->uc_mcontext.mc_onstack & 1)
- td->td_sigstk.ss_flags |= SS_ONSTACK;
- else
- td->td_sigstk.ss_flags &= ~SS_ONSTACK;
-#endif
-
- kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
- return (EJUSTRETURN);
-}
-
-/*
- * Machine dependent boot() routine
- *
- * I haven't seen anything to put here yet
- * Possibly some stuff might be grafted back here from boot()
- */
-void
-cpu_boot(int howto)
-{
-}
-
-/*
- * Flush the D-cache for non-DMA I/O so that the I-cache can
- * be made coherent later.
- */
-void
-cpu_flush_dcache(void *ptr, size_t len)
-{
- /* Not applicable */
-}
-
-/* Get current clock frequency for the given cpu id. */
-int
-cpu_est_clockrate(int cpu_id, uint64_t *rate)
-{
- uint64_t tsc1, tsc2;
- register_t reg;
-
- if (pcpu_find(cpu_id) == NULL || rate == NULL)
- return (EINVAL);
- if ((cpu_feature & CPUID_TSC) == 0)
- return (EOPNOTSUPP);
-
-#ifdef SMP
- if (smp_cpus > 1) {
- /* Schedule ourselves on the indicated cpu. */
- thread_lock(curthread);
- sched_bind(curthread, cpu_id);
- thread_unlock(curthread);
- }
-#endif
-
- /* Calibrate by measuring a short delay. */
- reg = intr_disable();
- tsc1 = rdtsc();
- DELAY(1000);
- tsc2 = rdtsc();
- intr_restore(reg);
- *rate = (tsc2 - tsc1) * 1000;
-
-#ifdef SMP
- if (smp_cpus > 1) {
- thread_lock(curthread);
- sched_unbind(curthread);
- thread_unlock(curthread);
- }
-#endif
-
- return (0);
-}
-
-
-/*
- * Shutdown the CPU as much as possible
- */
-void
-cpu_halt(void)
-{
- for (;;)
- halt();
-}
-
-static int idle_mwait = 1; /* Use MONITOR/MWAIT for short idle. */
-SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RWTUN, &idle_mwait,
- 0, "Use MONITOR/MWAIT for short idle");
-
-#define STATE_RUNNING 0x0
-#define STATE_MWAIT 0x1
-#define STATE_SLEEPING 0x2
-
-static void
-cpu_idle_hlt(sbintime_t sbt)
-{
- int *state;
-
- state = (int *)PCPU_PTR(monitorbuf);
- *state = STATE_SLEEPING;
-
- /*
- * Since we may be in a critical section from cpu_idle(), if
- * an interrupt fires during that critical section we may have
- * a pending preemption. If the CPU halts, then that thread
- * may not execute until a later interrupt awakens the CPU.
- * To handle this race, check for a runnable thread after
- * disabling interrupts and immediately return if one is
- * found. Also, we must absolutely guarentee that hlt is
- * the next instruction after sti. This ensures that any
- * interrupt that fires after the call to disable_intr() will
- * immediately awaken the CPU from hlt. Finally, please note
- * that on x86 this works fine because of interrupts enabled only
- * after the instruction following sti takes place, while IF is set
- * to 1 immediately, allowing hlt instruction to acknowledge the
- * interrupt.
- */
- disable_intr();
- if (sched_runnable())
- enable_intr();
- else
- __asm __volatile("sti; hlt");
- *state = STATE_RUNNING;
-}
-
-/*
- * MWAIT cpu power states. Lower 4 bits are sub-states.
- */
-#define MWAIT_C0 0xf0
-#define MWAIT_C1 0x00
-#define MWAIT_C2 0x10
-#define MWAIT_C3 0x20
-#define MWAIT_C4 0x30
-
-static void
-cpu_idle_mwait(sbintime_t sbt)
-{
- int *state;
-
- state = (int *)PCPU_PTR(monitorbuf);
- *state = STATE_MWAIT;
-
- /* See comments in cpu_idle_hlt(). */
- disable_intr();
- if (sched_runnable()) {
- enable_intr();
- *state = STATE_RUNNING;
- return;
- }
- cpu_monitor(state, 0, 0);
- if (*state == STATE_MWAIT)
- __asm __volatile("sti; mwait" : : "a" (MWAIT_C1), "c" (0));
- else
- enable_intr();
- *state = STATE_RUNNING;
-}
-
-static void
-cpu_idle_spin(sbintime_t sbt)
-{
- int *state;
- int i;
-
- state = (int *)PCPU_PTR(monitorbuf);
- *state = STATE_RUNNING;
-
- /*
- * The sched_runnable() call is racy but as long as there is
- * a loop missing it one time will have just a little impact if any
- * (and it is much better than missing the check at all).
- */
- for (i = 0; i < 1000; i++) {
- if (sched_runnable())
- return;
- cpu_spinwait();
- }
-}
-
-void (*cpu_idle_fn)(sbintime_t) = cpu_idle_hlt;
-
-void
-cpu_idle(int busy)
-{
- sbintime_t sbt = -1;
-
- CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
- busy, curcpu);
-#if defined(MP_WATCHDOG)
- ap_watchdog(PCPU_GET(cpuid));
-#endif
- /* If we are busy - try to use fast methods. */
- if (busy) {
- if ((cpu_feature2 & CPUID2_MON) && idle_mwait) {
- cpu_idle_mwait(busy);
- goto out;
- }
- }
-
- /* If we have time - switch timers into idle mode. */
- if (!busy) {
- critical_enter();
- sbt = cpu_idleclock();
- }
-
- /* Call main idle method. */
- cpu_idle_fn(sbt);
-
- /* Switch timers back into active mode. */
- if (!busy) {
- cpu_activeclock();
- critical_exit();
- }
-out:
- CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done",
- busy, curcpu);
-}
-
-int
-cpu_idle_wakeup(int cpu)
-{
- struct pcpu *pcpu;
- int *state;
-
- pcpu = pcpu_find(cpu);
- state = (int *)pcpu->pc_monitorbuf;
- /*
- * This doesn't need to be atomic since missing the race will
- * simply result in unnecessary IPIs.
- */
- if (*state == STATE_SLEEPING)
- return (0);
- if (*state == STATE_MWAIT)
- *state = STATE_RUNNING;
- return (1);
-}
-
-/*
- * Ordered by speed/power consumption.
- */
-struct {
- void *id_fn;
- char *id_name;
-} idle_tbl[] = {
- { cpu_idle_spin, "spin" },
- { cpu_idle_mwait, "mwait" },
- { cpu_idle_hlt, "hlt" },
- { NULL, NULL }
-};
-
-static int
-idle_sysctl_available(SYSCTL_HANDLER_ARGS)
-{
- char *avail, *p;
- int error;
- int i;
-
- avail = malloc(256, M_TEMP, M_WAITOK);
- p = avail;
- for (i = 0; idle_tbl[i].id_name != NULL; i++) {
- if (strstr(idle_tbl[i].id_name, "mwait") &&
- (cpu_feature2 & CPUID2_MON) == 0)
- continue;
- p += sprintf(p, "%s%s", p != avail ? ", " : "",
- idle_tbl[i].id_name);
- }
- error = sysctl_handle_string(oidp, avail, 0, req);
- free(avail, M_TEMP);
- return (error);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, idle_available, CTLTYPE_STRING | CTLFLAG_RD,
- 0, 0, idle_sysctl_available, "A", "list of available idle functions");
-
-static int
-idle_sysctl(SYSCTL_HANDLER_ARGS)
-{
- char buf[16];
- int error;
- char *p;
- int i;
-
- p = "unknown";
- for (i = 0; idle_tbl[i].id_name != NULL; i++) {
- if (idle_tbl[i].id_fn == cpu_idle_fn) {
- p = idle_tbl[i].id_name;
- break;
- }
- }
- strncpy(buf, p, sizeof(buf));
- error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
- if (error != 0 || req->newptr == NULL)
- return (error);
- for (i = 0; idle_tbl[i].id_name != NULL; i++) {
- if (strstr(idle_tbl[i].id_name, "mwait") &&
- (cpu_feature2 & CPUID2_MON) == 0)
- continue;
- if (strcmp(idle_tbl[i].id_name, buf))
- continue;
- cpu_idle_fn = idle_tbl[i].id_fn;
- return (0);
- }
- return (EINVAL);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, idle, CTLTYPE_STRING | CTLFLAG_RW, 0, 0,
- idle_sysctl, "A", "currently selected idle function");
-
-/*
- * Reset registers to default values on exec.
- */
-void
-exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
-{
- struct trapframe *regs = td->td_frame;
- struct pcb *pcb = td->td_pcb;
-
- /* Reset pc->pcb_gs and %gs before possibly invalidating it. */
- pcb->pcb_gs = _udatasel;
- load_gs(_udatasel);
-
- mtx_lock_spin(&dt_lock);
- if (td->td_proc->p_md.md_ldt)
- user_ldt_free(td);
- else
- mtx_unlock_spin(&dt_lock);
-
- bzero((char *)regs, sizeof(struct trapframe));
- regs->tf_eip = imgp->entry_addr;
- regs->tf_esp = stack;
- regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T);
- regs->tf_ss = _udatasel;
- regs->tf_ds = _udatasel;
- regs->tf_es = _udatasel;
- regs->tf_fs = _udatasel;
- regs->tf_cs = _ucodesel;
-
- /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
- regs->tf_ebx = imgp->ps_strings;
-
- /*
- * Reset the hardware debug registers if they were in use.
- * They won't have any meaning for the newly exec'd process.
- */
- if (pcb->pcb_flags & PCB_DBREGS) {
- pcb->pcb_dr0 = 0;
- pcb->pcb_dr1 = 0;
- pcb->pcb_dr2 = 0;
- pcb->pcb_dr3 = 0;
- pcb->pcb_dr6 = 0;
- pcb->pcb_dr7 = 0;
- if (pcb == curpcb) {
- /*
- * Clear the debug registers on the running
- * CPU, otherwise they will end up affecting
- * the next process we switch to.
- */
- reset_dbregs();
- }
- pcb->pcb_flags &= ~PCB_DBREGS;
- }
-
- /*
- * Initialize the math emulator (if any) for the current process.
- * Actually, just clear the bit that says that the emulator has
- * been initialized. Initialization is delayed until the process
- * traps to the emulator (if it is done at all) mainly because
- * emulators don't provide an entry point for initialization.
- */
- td->td_pcb->pcb_flags &= ~FP_SOFTFP;
- pcb->pcb_initial_npxcw = __INITIAL_NPXCW__;
-
- /*
- * Drop the FP state if we hold it, so that the process gets a
- * clean FP state if it uses the FPU again.
- */
- fpstate_drop(td);
-
- /*
- * XXX - Linux emulator
- * Make sure sure edx is 0x0 on entry. Linux binaries depend
- * on it.
- */
- td->td_retval[1] = 0;
-}
-
-void
-cpu_setregs(void)
-{
- unsigned int cr0;
-
- cr0 = rcr0();
-
- /*
- * CR0_MP, CR0_NE and CR0_TS are set for NPX (FPU) support:
- *
- * Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
- * instructions. We must set the CR0_MP bit and use the CR0_TS
- * bit to control the trap, because setting the CR0_EM bit does
- * not cause WAIT instructions to trap. It's important to trap
- * WAIT instructions - otherwise the "wait" variants of no-wait
- * control instructions would degenerate to the "no-wait" variants
- * after FP context switches but work correctly otherwise. It's
- * particularly important to trap WAITs when there is no NPX -
- * otherwise the "wait" variants would always degenerate.
- *
- * Try setting CR0_NE to get correct error reporting on 486DX's.
- * Setting it should fail or do nothing on lesser processors.
- */
- cr0 |= CR0_MP | CR0_NE | CR0_TS | CR0_WP | CR0_AM;
- load_cr0(cr0);
- load_gs(_udatasel);
-}
-
-u_long bootdev; /* not a struct cdev *- encoding is different */
-SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev,
- CTLFLAG_RD, &bootdev, 0, "Maybe the Boot device (not in struct cdev *format)");
-
-/*
- * Initialize 386 and configure to run kernel
- */
-
-/*
- * Initialize segments & interrupt table
- */
-
-int _default_ldt;
-
-union descriptor gdt[NGDT * MAXCPU]; /* global descriptor table */
-union descriptor ldt[NLDT]; /* local descriptor table */
-static struct gate_descriptor idt0[NIDT];
-struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */
-struct region_descriptor r_gdt, r_idt; /* table descriptors */
-struct mtx dt_lock; /* lock for GDT and LDT */
-
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
-extern int has_f00f_bug;
-#endif
-
-static struct i386tss dblfault_tss;
-static char dblfault_stack[PAGE_SIZE];
-
-extern vm_offset_t proc0kstack;
-
-
-/*
- * software prototypes -- in more palatable form.
- *
- * GCODE_SEL through GUDATA_SEL must be in this order for syscall/sysret
- * GUFS_SEL and GUGS_SEL must be in this order (swtch.s knows it)
- */
-struct soft_segment_descriptor gdt_segs[] = {
-/* GNULL_SEL 0 Null Descriptor */
-{ .ssd_base = 0x0,
- .ssd_limit = 0x0,
- .ssd_type = 0,
- .ssd_dpl = SEL_KPL,
- .ssd_p = 0,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
-/* GPRIV_SEL 1 SMP Per-Processor Private Data Descriptor */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = SEL_KPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GUFS_SEL 2 %fs Descriptor for user */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = SEL_UPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GUGS_SEL 3 %gs Descriptor for user */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = SEL_UPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GCODE_SEL 4 Code Descriptor for kernel */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMERA,
- .ssd_dpl = SEL_KPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GDATA_SEL 5 Data Descriptor for kernel */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = SEL_KPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GUCODE_SEL 6 Code Descriptor for user */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMERA,
- .ssd_dpl = SEL_UPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GUDATA_SEL 7 Data Descriptor for user */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = SEL_UPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
-{ .ssd_base = 0x400,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = SEL_KPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GPROC0_SEL 9 Proc 0 Tss Descriptor */
-{
- .ssd_base = 0x0,
- .ssd_limit = sizeof(struct i386tss)-1,
- .ssd_type = SDT_SYS386TSS,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
-/* GLDT_SEL 10 LDT Descriptor */
-{ .ssd_base = (int) ldt,
- .ssd_limit = sizeof(ldt)-1,
- .ssd_type = SDT_SYSLDT,
- .ssd_dpl = SEL_UPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
-/* GUSERLDT_SEL 11 User LDT Descriptor per process */
-{ .ssd_base = (int) ldt,
- .ssd_limit = (512 * sizeof(union descriptor)-1),
- .ssd_type = SDT_SYSLDT,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
-/* GPANIC_SEL 12 Panic Tss Descriptor */
-{ .ssd_base = (int) &dblfault_tss,
- .ssd_limit = sizeof(struct i386tss)-1,
- .ssd_type = SDT_SYS386TSS,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
-/* GBIOSCODE32_SEL 13 BIOS 32-bit interface (32bit Code) */
-{ .ssd_base = 0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMERA,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 1 },
-/* GBIOSCODE16_SEL 14 BIOS 32-bit interface (16bit Code) */
-{ .ssd_base = 0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMERA,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 1 },
-/* GBIOSDATA_SEL 15 BIOS 32-bit interface (Data) */
-{ .ssd_base = 0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-/* GBIOSUTIL_SEL 16 BIOS 16-bit interface (Utility) */
-{ .ssd_base = 0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 1 },
-/* GBIOSARGS_SEL 17 BIOS 16-bit interface (Arguments) */
-{ .ssd_base = 0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = 0,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 1 },
-/* GNDIS_SEL 18 NDIS Descriptor */
-{ .ssd_base = 0x0,
- .ssd_limit = 0x0,
- .ssd_type = 0,
- .ssd_dpl = 0,
- .ssd_p = 0,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
-};
-
-static struct soft_segment_descriptor ldt_segs[] = {
- /* Null Descriptor - overwritten by call gate */
-{ .ssd_base = 0x0,
- .ssd_limit = 0x0,
- .ssd_type = 0,
- .ssd_dpl = 0,
- .ssd_p = 0,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
- /* Null Descriptor - overwritten by call gate */
-{ .ssd_base = 0x0,
- .ssd_limit = 0x0,
- .ssd_type = 0,
- .ssd_dpl = 0,
- .ssd_p = 0,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
- /* Null Descriptor - overwritten by call gate */
-{ .ssd_base = 0x0,
- .ssd_limit = 0x0,
- .ssd_type = 0,
- .ssd_dpl = 0,
- .ssd_p = 0,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
- /* Code Descriptor for user */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMERA,
- .ssd_dpl = SEL_UPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
- /* Null Descriptor - overwritten by call gate */
-{ .ssd_base = 0x0,
- .ssd_limit = 0x0,
- .ssd_type = 0,
- .ssd_dpl = 0,
- .ssd_p = 0,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 0,
- .ssd_gran = 0 },
- /* Data Descriptor for user */
-{ .ssd_base = 0x0,
- .ssd_limit = 0xfffff,
- .ssd_type = SDT_MEMRWA,
- .ssd_dpl = SEL_UPL,
- .ssd_p = 1,
- .ssd_xx = 0, .ssd_xx1 = 0,
- .ssd_def32 = 1,
- .ssd_gran = 1 },
-};
-
-void
-setidt(idx, func, typ, dpl, selec)
- int idx;
- inthand_t *func;
- int typ;
- int dpl;
- int selec;
-{
- struct gate_descriptor *ip;
-
- ip = idt + idx;
- ip->gd_looffset = (int)func;
- ip->gd_selector = selec;
- ip->gd_stkcpy = 0;
- ip->gd_xx = 0;
- ip->gd_type = typ;
- ip->gd_dpl = dpl;
- ip->gd_p = 1;
- ip->gd_hioffset = ((int)func)>>16 ;
-}
-
-extern inthand_t
- IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
- IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
- IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
- IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
- IDTVEC(xmm),
-#ifdef KDTRACE_HOOKS
- IDTVEC(dtrace_ret),
-#endif
- IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall);
-
-#ifdef DDB
-/*
- * Display the index and function name of any IDT entries that don't use
- * the default 'rsvd' entry point.
- */
-DB_SHOW_COMMAND(idt, db_show_idt)
-{
- struct gate_descriptor *ip;
- int idx;
- uintptr_t func;
-
- ip = idt;
- for (idx = 0; idx < NIDT && !db_pager_quit; idx++) {
- func = (ip->gd_hioffset << 16 | ip->gd_looffset);
- if (func != (uintptr_t)&IDTVEC(rsvd)) {
- db_printf("%3d\t", idx);
- db_printsym(func, DB_STGY_PROC);
- db_printf("\n");
- }
- ip++;
- }
-}
-
-/* Show privileged registers. */
-DB_SHOW_COMMAND(sysregs, db_show_sysregs)
-{
- uint64_t idtr, gdtr;
-
- idtr = ridt();
- db_printf("idtr\t0x%08x/%04x\n",
- (u_int)(idtr >> 16), (u_int)idtr & 0xffff);
- gdtr = rgdt();
- db_printf("gdtr\t0x%08x/%04x\n",
- (u_int)(gdtr >> 16), (u_int)gdtr & 0xffff);
- db_printf("ldtr\t0x%04x\n", rldt());
- db_printf("tr\t0x%04x\n", rtr());
- db_printf("cr0\t0x%08x\n", rcr0());
- db_printf("cr2\t0x%08x\n", rcr2());
- db_printf("cr3\t0x%08x\n", rcr3());
- db_printf("cr4\t0x%08x\n", rcr4());
-}
-#endif
-
-void
-sdtossd(sd, ssd)
- struct segment_descriptor *sd;
- struct soft_segment_descriptor *ssd;
-{
- ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase;
- ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
- ssd->ssd_type = sd->sd_type;
- ssd->ssd_dpl = sd->sd_dpl;
- ssd->ssd_p = sd->sd_p;
- ssd->ssd_def32 = sd->sd_def32;
- ssd->ssd_gran = sd->sd_gran;
-}
-
-static void
-basemem_setup(void)
-{
- vm_paddr_t pa;
- pt_entry_t *pte;
- int i;
-
- if (basemem > 640) {
- printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
- basemem);
- basemem = 640;
- }
-
- /*
- * XXX if biosbasemem is now < 640, there is a `hole'
- * between the end of base memory and the start of
- * ISA memory. The hole may be empty or it may
- * contain BIOS code or data. Map it read/write so
- * that the BIOS can write to it. (Memory from 0 to
- * the physical end of the kernel is mapped read-only
- * to begin with and then parts of it are remapped.
- * The parts that aren't remapped form holes that
- * remain read-only and are unused by the kernel.
- * The base memory area is below the physical end of
- * the kernel and right now forms a read-only hole.
- * The part of it from PAGE_SIZE to
- * (trunc_page(biosbasemem * 1024) - 1) will be
- * remapped and used by the kernel later.)
- *
- * This code is similar to the code used in
- * pmap_mapdev, but since no memory needs to be
- * allocated we simply change the mapping.
- */
- for (pa = trunc_page(basemem * 1024);
- pa < ISA_HOLE_START; pa += PAGE_SIZE)
- pmap_kenter(KERNBASE + pa, pa);
-
- /*
- * Map pages between basemem and ISA_HOLE_START, if any, r/w into
- * the vm86 page table so that vm86 can scribble on them using
- * the vm86 map too. XXX: why 2 ways for this and only 1 way for
- * page 0, at least as initialized here?
- */
- pte = (pt_entry_t *)vm86paddr;
- for (i = basemem / 4; i < 160; i++)
- pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
-}
-
-/*
- * Populate the (physmap) array with base/bound pairs describing the
- * available physical memory in the system, then test this memory and
- * build the phys_avail array describing the actually-available memory.
- *
- * If we cannot accurately determine the physical memory map, then use
- * value from the 0xE801 call, and failing that, the RTC.
- *
- * Total memory size may be set by the kernel environment variable
- * hw.physmem or the compile-time define MAXMEM.
- *
- * XXX first should be vm_paddr_t.
- */
-static void
-getmemsize(int first)
-{
- int off, physmap_idx, pa_indx, da_indx;
- u_long physmem_tunable, memtest;
- vm_paddr_t physmap[PHYSMAP_SIZE];
- pt_entry_t *pte;
- quad_t dcons_addr, dcons_size;
- int i;
- int pg_n;
- u_int extmem;
- u_int under16;
- vm_paddr_t pa;
-
- bzero(physmap, sizeof(physmap));
-
- /* XXX - some of EPSON machines can't use PG_N */
- pg_n = PG_N;
- if (pc98_machine_type & M_EPSON_PC98) {
- switch (epson_machine_id) {
-#ifdef WB_CACHE
- default:
-#endif
- case EPSON_PC486_HX:
- case EPSON_PC486_HG:
- case EPSON_PC486_HA:
- pg_n = 0;
- break;
- }
- }
-
- under16 = pc98_getmemsize(&basemem, &extmem);
- basemem_setup();
-
- physmap[0] = 0;
- physmap[1] = basemem * 1024;
- physmap_idx = 2;
- physmap[physmap_idx] = 0x100000;
- physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024;
-
- /*
- * Now, physmap contains a map of physical memory.
- */
-
-#ifdef SMP
- /* make hole for AP bootstrap code */
- physmap[1] = mp_bootaddress(physmap[1]);
-#endif
-
- /*
- * Maxmem isn't the "maximum memory", it's one larger than the
- * highest page of the physical address space. It should be
- * called something like "Maxphyspage". We may adjust this
- * based on ``hw.physmem'' and the results of the memory test.
- */
- Maxmem = atop(physmap[physmap_idx + 1]);
-
-#ifdef MAXMEM
- Maxmem = MAXMEM / 4;
-#endif
-
- if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
- Maxmem = atop(physmem_tunable);
-
- /*
- * By default keep the memtest enabled. Use a general name so that
- * one could eventually do more with the code than just disable it.
- */
- memtest = 1;
- TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest);
-
- if (atop(physmap[physmap_idx + 1]) != Maxmem &&
- (boothowto & RB_VERBOSE))
- printf("Physical memory use set to %ldK\n", Maxmem * 4);
-
- /*
- * If Maxmem has been increased beyond what the system has detected,
- * extend the last memory segment to the new limit.
- */
- if (atop(physmap[physmap_idx + 1]) < Maxmem)
- physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem);
-
- /*
- * We need to divide chunk if Maxmem is larger than 16MB and
- * under 16MB area is not full of memory.
- * (1) system area (15-16MB region) is cut off
- * (2) extended memory is only over 16MB area (ex. Melco "HYPERMEMORY")
- */
- if ((under16 != 16 * 1024) && (extmem > 15 * 1024)) {
- /* 15M - 16M region is cut off, so need to divide chunk */
- physmap[physmap_idx + 1] = under16 * 1024;
- physmap_idx += 2;
- physmap[physmap_idx] = 0x1000000;
- physmap[physmap_idx + 1] = physmap[2] + extmem * 1024;
- }
-
- /* call pmap initialization to make new kernel address space */
- pmap_bootstrap(first);
-
- /*
- * Size up each available chunk of physical memory.
- */
- physmap[0] = PAGE_SIZE; /* mask off page 0 */
- pa_indx = 0;
- da_indx = 1;
- phys_avail[pa_indx++] = physmap[0];
- phys_avail[pa_indx] = physmap[0];
- dump_avail[da_indx] = physmap[0];
- pte = CMAP3;
-
- /*
- * Get dcons buffer address
- */
- if (getenv_quad("dcons.addr", &dcons_addr) == 0 ||
- getenv_quad("dcons.size", &dcons_size) == 0)
- dcons_addr = 0;
-
- /*
- * physmap is in bytes, so when converting to page boundaries,
- * round up the start address and round down the end address.
- */
- for (i = 0; i <= physmap_idx; i += 2) {
- vm_paddr_t end;
-
- end = ptoa((vm_paddr_t)Maxmem);
- if (physmap[i + 1] < end)
- end = trunc_page(physmap[i + 1]);
- for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) {
- int tmp, page_bad, full;
- int *ptr = (int *)CADDR3;
-
- full = FALSE;
- /*
- * block out kernel memory as not available.
- */
- if (pa >= KERNLOAD && pa < first)
- goto do_dump_avail;
-
- /*
- * block out dcons buffer
- */
- if (dcons_addr > 0
- && pa >= trunc_page(dcons_addr)
- && pa < dcons_addr + dcons_size)
- goto do_dump_avail;
-
- page_bad = FALSE;
- if (memtest == 0)
- goto skip_memtest;
-
- /*
- * map page into kernel: valid, read/write,non-cacheable
- */
- *pte = pa | PG_V | PG_RW | pg_n;
- invltlb();
-
- tmp = *(int *)ptr;
- /*
- * Test for alternating 1's and 0's
- */
- *(volatile int *)ptr = 0xaaaaaaaa;
- if (*(volatile int *)ptr != 0xaaaaaaaa)
- page_bad = TRUE;
- /*
- * Test for alternating 0's and 1's
- */
- *(volatile int *)ptr = 0x55555555;
- if (*(volatile int *)ptr != 0x55555555)
- page_bad = TRUE;
- /*
- * Test for all 1's
- */
- *(volatile int *)ptr = 0xffffffff;
- if (*(volatile int *)ptr != 0xffffffff)
- page_bad = TRUE;
- /*
- * Test for all 0's
- */
- *(volatile int *)ptr = 0x0;
- if (*(volatile int *)ptr != 0x0)
- page_bad = TRUE;
- /*
- * Restore original value.
- */
- *(int *)ptr = tmp;
-
-skip_memtest:
- /*
- * Adjust array of valid/good pages.
- */
- if (page_bad == TRUE)
- continue;
- /*
- * If this good page is a continuation of the
- * previous set of good pages, then just increase
- * the end pointer. Otherwise start a new chunk.
- * Note that "end" points one higher than end,
- * making the range >= start and < end.
- * If we're also doing a speculative memory
- * test and we at or past the end, bump up Maxmem
- * so that we keep going. The first bad page
- * will terminate the loop.
- */
- if (phys_avail[pa_indx] == pa) {
- phys_avail[pa_indx] += PAGE_SIZE;
- } else {
- pa_indx++;
- if (pa_indx == PHYS_AVAIL_ARRAY_END) {
- printf(
- "Too many holes in the physical address space, giving up\n");
- pa_indx--;
- full = TRUE;
- goto do_dump_avail;
- }
- phys_avail[pa_indx++] = pa; /* start */
- phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */
- }
- physmem++;
-do_dump_avail:
- if (dump_avail[da_indx] == pa) {
- dump_avail[da_indx] += PAGE_SIZE;
- } else {
- da_indx++;
- if (da_indx == DUMP_AVAIL_ARRAY_END) {
- da_indx--;
- goto do_next;
- }
- dump_avail[da_indx++] = pa; /* start */
- dump_avail[da_indx] = pa + PAGE_SIZE; /* end */
- }
-do_next:
- if (full)
- break;
- }
- }
- *pte = 0;
- invltlb();
-
- /*
- * XXX
- * The last chunk must contain at least one page plus the message
- * buffer to avoid complicating other code (message buffer address
- * calculation, etc.).
- */
- while (phys_avail[pa_indx - 1] + PAGE_SIZE +
- round_page(msgbufsize) >= phys_avail[pa_indx]) {
- physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
- phys_avail[pa_indx--] = 0;
- phys_avail[pa_indx--] = 0;
- }
-
- Maxmem = atop(phys_avail[pa_indx]);
-
- /* Trim off space for the message buffer. */
- phys_avail[pa_indx] -= round_page(msgbufsize);
-
- /* Map the message buffer. */
- for (off = 0; off < round_page(msgbufsize); off += PAGE_SIZE)
- pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] +
- off);
-
- PT_UPDATES_FLUSH();
-}
-
-void
-init386(first)
- int first;
-{
- struct gate_descriptor *gdp;
- int gsel_tss, metadata_missing, x, pa;
- size_t kstack0_sz;
- struct pcpu *pc;
-
- thread0.td_kstack = proc0kstack;
- thread0.td_kstack_pages = KSTACK_PAGES;
- kstack0_sz = thread0.td_kstack_pages * PAGE_SIZE;
- thread0.td_pcb = (struct pcb *)(thread0.td_kstack + kstack0_sz) - 1;
-
- /*
- * This may be done better later if it gets more high level
- * components in it. If so just link td->td_proc here.
- */
- proc_linkup0(&proc0, &thread0);
-
- /*
- * Initialize DMAC
- */
- pc98_init_dmac();
-
- metadata_missing = 0;
- if (bootinfo.bi_modulep) {
- preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE;
- preload_bootstrap_relocate(KERNBASE);
- } else {
- metadata_missing = 1;
- }
- if (envmode == 1)
- kern_envp = static_env;
- else if (bootinfo.bi_envp)
- kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;
-
- /* Init basic tunables, hz etc */
- init_param1();
-
- /*
- * Make gdt memory segments. All segments cover the full 4GB
- * of address space and permissions are enforced at page level.
- */
- gdt_segs[GCODE_SEL].ssd_limit = atop(0 - 1);
- gdt_segs[GDATA_SEL].ssd_limit = atop(0 - 1);
- gdt_segs[GUCODE_SEL].ssd_limit = atop(0 - 1);
- gdt_segs[GUDATA_SEL].ssd_limit = atop(0 - 1);
- gdt_segs[GUFS_SEL].ssd_limit = atop(0 - 1);
- gdt_segs[GUGS_SEL].ssd_limit = atop(0 - 1);
-
- pc = &__pcpu[0];
- gdt_segs[GPRIV_SEL].ssd_limit = atop(0 - 1);
- gdt_segs[GPRIV_SEL].ssd_base = (int) pc;
- gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss;
-
- for (x = 0; x < NGDT; x++)
- ssdtosd(&gdt_segs[x], &gdt[x].sd);
-
- r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
- r_gdt.rd_base = (int) gdt;
- mtx_init(&dt_lock, "descriptor tables", NULL, MTX_SPIN);
- lgdt(&r_gdt);
-
- pcpu_init(pc, 0, sizeof(struct pcpu));
- for (pa = first; pa < first + DPCPU_SIZE; pa += PAGE_SIZE)
- pmap_kenter(pa + KERNBASE, pa);
- dpcpu_init((void *)(first + KERNBASE), 0);
- first += DPCPU_SIZE;
- PCPU_SET(prvspace, pc);
- PCPU_SET(curthread, &thread0);
- PCPU_SET(curpcb, thread0.td_pcb);
-
- /*
- * Initialize mutexes.
- *
- * icu_lock: in order to allow an interrupt to occur in a critical
- * section, to set pcpu->ipending (etc...) properly, we
- * must be able to get the icu lock, so it can't be
- * under witness.
- */
- mutex_init();
- mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS | MTX_NOPROFILE);
-
- /* make ldt memory segments */
- ldt_segs[LUCODE_SEL].ssd_limit = atop(0 - 1);
- ldt_segs[LUDATA_SEL].ssd_limit = atop(0 - 1);
- for (x = 0; x < sizeof ldt_segs / sizeof ldt_segs[0]; x++)
- ssdtosd(&ldt_segs[x], &ldt[x].sd);
-
- _default_ldt = GSEL(GLDT_SEL, SEL_KPL);
- lldt(_default_ldt);
- PCPU_SET(currentldt, _default_ldt);
-
- /* exceptions */
- for (x = 0; x < NIDT; x++)
- setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_DE, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_DB, &IDTVEC(dbg), SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_NMI, &IDTVEC(nmi), SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_BP, &IDTVEC(bpt), SDT_SYS386IGT, SEL_UPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_OF, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_BR, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_NM, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL
- , GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_DF, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL));
- setidt(IDT_FPUGP, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_TS, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_NP, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_SS, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_PF, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_MF, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_AC, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_MC, &IDTVEC(mchk), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_XF, &IDTVEC(xmm), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall), SDT_SYS386TGT, SEL_UPL,
- GSEL(GCODE_SEL, SEL_KPL));
-#ifdef KDTRACE_HOOKS
- setidt(IDT_DTRACE_RET, &IDTVEC(dtrace_ret), SDT_SYS386TGT, SEL_UPL,
- GSEL(GCODE_SEL, SEL_KPL));
-#endif
-
- r_idt.rd_limit = sizeof(idt0) - 1;
- r_idt.rd_base = (int) idt;
- lidt(&r_idt);
-
- /*
- * Initialize the i8254 before the console so that console
- * initialization can use DELAY().
- */
- clock_init();
-
- /*
- * Initialize the console before we print anything out.
- */
- cninit();
-
- if (metadata_missing)
- printf("WARNING: loader(8) metadata is missing!\n");
-
-#ifdef DEV_ISA
-#ifdef DEV_ATPIC
- atpic_startup();
-#else
- /* Reset and mask the atpics and leave them shut down. */
- atpic_reset();
-
- /*
- * Point the ICU spurious interrupt vectors at the APIC spurious
- * interrupt handler.
- */
- setidt(IDT_IO_INTS + 7, IDTVEC(spuriousint), SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_IO_INTS + 15, IDTVEC(spuriousint), SDT_SYS386IGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
-#endif
-#endif
-
-#ifdef DDB
- db_fetch_ksymtab(bootinfo.bi_symtab,bootinfo.bi_esymtab);
-#endif
-
- kdb_init();
-
-#ifdef KDB
- if (boothowto & RB_KDB)
- kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
-#endif
-
- finishidentcpu(); /* Final stage of CPU initialization */
- setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
- GSEL(GCODE_SEL, SEL_KPL));
- initializecpu(); /* Initialize CPU registers */
- initializecpucache();
-
- /* make an initial tss so cpu can get interrupt stack on syscall! */
- /* Note: -16 is so we can grow the trapframe if we came from vm86 */
- PCPU_SET(common_tss.tss_esp0, thread0.td_kstack +
- kstack0_sz - sizeof(struct pcb) - 16);
- PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL));
- gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
- PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd);
- PCPU_SET(common_tssd, *PCPU_GET(tss_gdt));
- PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16);
- ltr(gsel_tss);
-
- /* pointer to selector slot for %fs/%gs */
- PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd);
-
- dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
- dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)];
- dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
- dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
- dblfault_tss.tss_cr3 = (int)IdlePTD;
- dblfault_tss.tss_eip = (int)dblfault_handler;
- dblfault_tss.tss_eflags = PSL_KERNEL;
- dblfault_tss.tss_ds = dblfault_tss.tss_es =
- dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL);
- dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL);
- dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
- dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
-
- vm86_initialize();
- getmemsize(first);
- init_param2(physmem);
-
- /* now running on new page tables, configured,and u/iom is accessible */
-
- msgbufinit(msgbufp, msgbufsize);
-
- /* make a call gate to reenter kernel with */
- gdp = &ldt[LSYS5CALLS_SEL].gd;
-
- x = (int) &IDTVEC(lcall_syscall);
- gdp->gd_looffset = x;
- gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
- gdp->gd_stkcpy = 1;
- gdp->gd_type = SDT_SYS386CGT;
- gdp->gd_dpl = SEL_UPL;
- gdp->gd_p = 1;
- gdp->gd_hioffset = x >> 16;
-
- /* XXX does this work? */
- /* XXX yes! */
- ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
- ldt[LSOL26CALLS_SEL] = ldt[LSYS5CALLS_SEL];
-
- /* transfer to user mode */
-
- _ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
- _udatasel = GSEL(GUDATA_SEL, SEL_UPL);
-
- /* setup proc 0's pcb */
- thread0.td_pcb->pcb_flags = 0;
- thread0.td_pcb->pcb_cr3 = (int)IdlePTD;
- thread0.td_pcb->pcb_ext = 0;
- thread0.td_frame = &proc0_tf;
-}
-
-void
-cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
-{
-
-}
-
-void
-spinlock_enter(void)
-{
- struct thread *td;
- register_t flags;
-
- td = curthread;
- if (td->td_md.md_spinlock_count == 0) {
- flags = intr_disable();
- td->td_md.md_spinlock_count = 1;
- td->td_md.md_saved_flags = flags;
- } else
- td->td_md.md_spinlock_count++;
- critical_enter();
-}
-
-void
-spinlock_exit(void)
-{
- struct thread *td;
- register_t flags;
-
- td = curthread;
- critical_exit();
- flags = td->td_md.md_saved_flags;
- td->td_md.md_spinlock_count--;
- if (td->td_md.md_spinlock_count == 0)
- intr_restore(flags);
-}
-
-#if defined(I586_CPU) && !defined(NO_F00F_HACK)
-static void f00f_hack(void *unused);
-SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL);
-
-static void
-f00f_hack(void *unused)
-{
- struct gate_descriptor *new_idt;
- vm_offset_t tmp;
-
- if (!has_f00f_bug)
- return;
-
- GIANT_REQUIRED;
-
- printf("Intel Pentium detected, installing workaround for F00F bug\n");
-
- tmp = kmem_malloc(kernel_arena, PAGE_SIZE * 2, M_WAITOK | M_ZERO);
- if (tmp == 0)
- panic("kmem_alloc returned 0");
-
- /* Put the problematic entry (#6) at the end of the lower page. */
- new_idt = (struct gate_descriptor*)
- (tmp + PAGE_SIZE - 7 * sizeof(struct gate_descriptor));
- bcopy(idt, new_idt, sizeof(idt0));
- r_idt.rd_base = (u_int)new_idt;
- lidt(&r_idt);
- idt = new_idt;
- pmap_protect(kernel_pmap, tmp, tmp + PAGE_SIZE, VM_PROT_READ);
-}
-#endif /* defined(I586_CPU) && !NO_F00F_HACK */
-
-/*
- * Construct a PCB from a trapframe. This is called from kdb_trap() where
- * we want to start a backtrace from the function that caused us to enter
- * the debugger. We have the context in the trapframe, but base the trace
- * on the PCB. The PCB doesn't have to be perfect, as long as it contains
- * enough for a backtrace.
- */
-void
-makectx(struct trapframe *tf, struct pcb *pcb)
-{
-
- pcb->pcb_edi = tf->tf_edi;
- pcb->pcb_esi = tf->tf_esi;
- pcb->pcb_ebp = tf->tf_ebp;
- pcb->pcb_ebx = tf->tf_ebx;
- pcb->pcb_eip = tf->tf_eip;
- pcb->pcb_esp = (ISPL(tf->tf_cs)) ? tf->tf_esp : (int)(tf + 1) - 8;
-}
-
-int
-ptrace_set_pc(struct thread *td, u_long addr)
-{
-
- td->td_frame->tf_eip = addr;
- return (0);
-}
-
-int
-ptrace_single_step(struct thread *td)
-{
- td->td_frame->tf_eflags |= PSL_T;
- return (0);
-}
-
-int
-ptrace_clear_single_step(struct thread *td)
-{
- td->td_frame->tf_eflags &= ~PSL_T;
- return (0);
-}
-
-int
-fill_regs(struct thread *td, struct reg *regs)
-{
- struct pcb *pcb;
- struct trapframe *tp;
-
- tp = td->td_frame;
- pcb = td->td_pcb;
- regs->r_gs = pcb->pcb_gs;
- return (fill_frame_regs(tp, regs));
-}
-
-int
-fill_frame_regs(struct trapframe *tp, struct reg *regs)
-{
- regs->r_fs = tp->tf_fs;
- regs->r_es = tp->tf_es;
- regs->r_ds = tp->tf_ds;
- regs->r_edi = tp->tf_edi;
- regs->r_esi = tp->tf_esi;
- regs->r_ebp = tp->tf_ebp;
- regs->r_ebx = tp->tf_ebx;
- regs->r_edx = tp->tf_edx;
- regs->r_ecx = tp->tf_ecx;
- regs->r_eax = tp->tf_eax;
- regs->r_eip = tp->tf_eip;
- regs->r_cs = tp->tf_cs;
- regs->r_eflags = tp->tf_eflags;
- regs->r_esp = tp->tf_esp;
- regs->r_ss = tp->tf_ss;
- return (0);
-}
-
-int
-set_regs(struct thread *td, struct reg *regs)
-{
- struct pcb *pcb;
- struct trapframe *tp;
-
- tp = td->td_frame;
- if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) ||
- !CS_SECURE(regs->r_cs))
- return (EINVAL);
- pcb = td->td_pcb;
- tp->tf_fs = regs->r_fs;
- tp->tf_es = regs->r_es;
- tp->tf_ds = regs->r_ds;
- tp->tf_edi = regs->r_edi;
- tp->tf_esi = regs->r_esi;
- tp->tf_ebp = regs->r_ebp;
- tp->tf_ebx = regs->r_ebx;
- tp->tf_edx = regs->r_edx;
- tp->tf_ecx = regs->r_ecx;
- tp->tf_eax = regs->r_eax;
- tp->tf_eip = regs->r_eip;
- tp->tf_cs = regs->r_cs;
- tp->tf_eflags = regs->r_eflags;
- tp->tf_esp = regs->r_esp;
- tp->tf_ss = regs->r_ss;
- pcb->pcb_gs = regs->r_gs;
- return (0);
-}
-
-#ifdef CPU_ENABLE_SSE
-static void
-fill_fpregs_xmm(sv_xmm, sv_87)
- struct savexmm *sv_xmm;
- struct save87 *sv_87;
-{
- register struct env87 *penv_87 = &sv_87->sv_env;
- register struct envxmm *penv_xmm = &sv_xmm->sv_env;
- int i;
-
- bzero(sv_87, sizeof(*sv_87));
-
- /* FPU control/status */
- penv_87->en_cw = penv_xmm->en_cw;
- penv_87->en_sw = penv_xmm->en_sw;
- penv_87->en_tw = penv_xmm->en_tw;
- penv_87->en_fip = penv_xmm->en_fip;
- penv_87->en_fcs = penv_xmm->en_fcs;
- penv_87->en_opcode = penv_xmm->en_opcode;
- penv_87->en_foo = penv_xmm->en_foo;
- penv_87->en_fos = penv_xmm->en_fos;
-
- /* FPU registers */
- for (i = 0; i < 8; ++i)
- sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc;
-}
-
-static void
-set_fpregs_xmm(sv_87, sv_xmm)
- struct save87 *sv_87;
- struct savexmm *sv_xmm;
-{
- register struct env87 *penv_87 = &sv_87->sv_env;
- register struct envxmm *penv_xmm = &sv_xmm->sv_env;
- int i;
-
- /* FPU control/status */
- penv_xmm->en_cw = penv_87->en_cw;
- penv_xmm->en_sw = penv_87->en_sw;
- penv_xmm->en_tw = penv_87->en_tw;
- penv_xmm->en_fip = penv_87->en_fip;
- penv_xmm->en_fcs = penv_87->en_fcs;
- penv_xmm->en_opcode = penv_87->en_opcode;
- penv_xmm->en_foo = penv_87->en_foo;
- penv_xmm->en_fos = penv_87->en_fos;
-
- /* FPU registers */
- for (i = 0; i < 8; ++i)
- sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i];
-}
-#endif /* CPU_ENABLE_SSE */
-
-int
-fill_fpregs(struct thread *td, struct fpreg *fpregs)
-{
-
- KASSERT(td == curthread || TD_IS_SUSPENDED(td) ||
- P_SHOULDSTOP(td->td_proc),
- ("not suspended thread %p", td));
-#ifdef DEV_NPX
- npxgetregs(td);
-#else
- bzero(fpregs, sizeof(*fpregs));
-#endif
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- fill_fpregs_xmm(&td->td_pcb->pcb_user_save.sv_xmm,
- (struct save87 *)fpregs);
- else
-#endif /* CPU_ENABLE_SSE */
- bcopy(&td->td_pcb->pcb_user_save.sv_87, fpregs,
- sizeof(*fpregs));
- return (0);
-}
-
-int
-set_fpregs(struct thread *td, struct fpreg *fpregs)
-{
-
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- set_fpregs_xmm((struct save87 *)fpregs,
- &td->td_pcb->pcb_user_save.sv_xmm);
- else
-#endif /* CPU_ENABLE_SSE */
- bcopy(fpregs, &td->td_pcb->pcb_user_save.sv_87,
- sizeof(*fpregs));
-#ifdef DEV_NPX
- npxuserinited(td);
-#endif
- return (0);
-}
-
-/*
- * Get machine context.
- */
-int
-get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
-{
- struct trapframe *tp;
- struct segment_descriptor *sdp;
-
- tp = td->td_frame;
-
- PROC_LOCK(curthread->td_proc);
- mcp->mc_onstack = sigonstack(tp->tf_esp);
- PROC_UNLOCK(curthread->td_proc);
- mcp->mc_gs = td->td_pcb->pcb_gs;
- mcp->mc_fs = tp->tf_fs;
- mcp->mc_es = tp->tf_es;
- mcp->mc_ds = tp->tf_ds;
- mcp->mc_edi = tp->tf_edi;
- mcp->mc_esi = tp->tf_esi;
- mcp->mc_ebp = tp->tf_ebp;
- mcp->mc_isp = tp->tf_isp;
- mcp->mc_eflags = tp->tf_eflags;
- if (flags & GET_MC_CLEAR_RET) {
- mcp->mc_eax = 0;
- mcp->mc_edx = 0;
- mcp->mc_eflags &= ~PSL_C;
- } else {
- mcp->mc_eax = tp->tf_eax;
- mcp->mc_edx = tp->tf_edx;
- }
- mcp->mc_ebx = tp->tf_ebx;
- mcp->mc_ecx = tp->tf_ecx;
- mcp->mc_eip = tp->tf_eip;
- mcp->mc_cs = tp->tf_cs;
- mcp->mc_esp = tp->tf_esp;
- mcp->mc_ss = tp->tf_ss;
- mcp->mc_len = sizeof(*mcp);
- get_fpcontext(td, mcp);
- sdp = &td->td_pcb->pcb_fsd;
- mcp->mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
- sdp = &td->td_pcb->pcb_gsd;
- mcp->mc_gsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
- mcp->mc_flags = 0;
- bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2));
- return (0);
-}
-
-/*
- * Set machine context.
- *
- * However, we don't set any but the user modifiable flags, and we won't
- * touch the cs selector.
- */
-int
-set_mcontext(struct thread *td, const mcontext_t *mcp)
-{
- struct trapframe *tp;
- int eflags, ret;
-
- tp = td->td_frame;
- if (mcp->mc_len != sizeof(*mcp))
- return (EINVAL);
- eflags = (mcp->mc_eflags & PSL_USERCHANGE) |
- (tp->tf_eflags & ~PSL_USERCHANGE);
- if ((ret = set_fpcontext(td, mcp)) == 0) {
- tp->tf_fs = mcp->mc_fs;
- tp->tf_es = mcp->mc_es;
- tp->tf_ds = mcp->mc_ds;
- tp->tf_edi = mcp->mc_edi;
- tp->tf_esi = mcp->mc_esi;
- tp->tf_ebp = mcp->mc_ebp;
- tp->tf_ebx = mcp->mc_ebx;
- tp->tf_edx = mcp->mc_edx;
- tp->tf_ecx = mcp->mc_ecx;
- tp->tf_eax = mcp->mc_eax;
- tp->tf_eip = mcp->mc_eip;
- tp->tf_eflags = eflags;
- tp->tf_esp = mcp->mc_esp;
- tp->tf_ss = mcp->mc_ss;
- td->td_pcb->pcb_gs = mcp->mc_gs;
- ret = 0;
- }
- return (ret);
-}
-
-static void
-get_fpcontext(struct thread *td, mcontext_t *mcp)
-{
-
-#ifndef DEV_NPX
- mcp->mc_fpformat = _MC_FPFMT_NODEV;
- mcp->mc_ownedfp = _MC_FPOWNED_NONE;
- bzero(mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
-#else
- mcp->mc_ownedfp = npxgetregs(td);
- bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate[0],
- sizeof(mcp->mc_fpstate));
- mcp->mc_fpformat = npxformat();
-#endif
-}
-
-static int
-set_fpcontext(struct thread *td, const mcontext_t *mcp)
-{
-
- if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
- return (0);
- else if (mcp->mc_fpformat != _MC_FPFMT_387 &&
- mcp->mc_fpformat != _MC_FPFMT_XMM)
- return (EINVAL);
- else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
- /* We don't care what state is left in the FPU or PCB. */
- fpstate_drop(td);
- else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
- mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
-#ifdef DEV_NPX
-#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr)
- ((union savefpu *)&mcp->mc_fpstate)->sv_xmm.sv_env.
- en_mxcsr &= cpu_mxcsr_mask;
-#endif
- npxsetregs(td, (union savefpu *)&mcp->mc_fpstate);
-#endif
- } else
- return (EINVAL);
- return (0);
-}
-
-static void
-fpstate_drop(struct thread *td)
-{
-
- KASSERT(PCB_USER_FPU(td->td_pcb), ("fpstate_drop: kernel-owned fpu"));
- critical_enter();
-#ifdef DEV_NPX
- if (PCPU_GET(fpcurthread) == td)
- npxdrop();
-#endif
- /*
- * XXX force a full drop of the npx. The above only drops it if we
- * owned it. npxgetregs() has the same bug in the !cpu_fxsr case.
- *
- * XXX I don't much like npxgetregs()'s semantics of doing a full
- * drop. Dropping only to the pcb matches fnsave's behaviour.
- * We only need to drop to !PCB_INITDONE in sendsig(). But
- * sendsig() is the only caller of npxgetregs()... perhaps we just
- * have too many layers.
- */
- curthread->td_pcb->pcb_flags &= ~(PCB_NPXINITDONE |
- PCB_NPXUSERINITDONE);
- critical_exit();
-}
-
-int
-fill_dbregs(struct thread *td, struct dbreg *dbregs)
-{
- struct pcb *pcb;
-
- if (td == NULL) {
- dbregs->dr[0] = rdr0();
- dbregs->dr[1] = rdr1();
- dbregs->dr[2] = rdr2();
- dbregs->dr[3] = rdr3();
- dbregs->dr[4] = rdr4();
- dbregs->dr[5] = rdr5();
- dbregs->dr[6] = rdr6();
- dbregs->dr[7] = rdr7();
- } else {
- pcb = td->td_pcb;
- dbregs->dr[0] = pcb->pcb_dr0;
- dbregs->dr[1] = pcb->pcb_dr1;
- dbregs->dr[2] = pcb->pcb_dr2;
- dbregs->dr[3] = pcb->pcb_dr3;
- dbregs->dr[4] = 0;
- dbregs->dr[5] = 0;
- dbregs->dr[6] = pcb->pcb_dr6;
- dbregs->dr[7] = pcb->pcb_dr7;
- }
- return (0);
-}
-
-int
-set_dbregs(struct thread *td, struct dbreg *dbregs)
-{
- struct pcb *pcb;
- int i;
-
- if (td == NULL) {
- load_dr0(dbregs->dr[0]);
- load_dr1(dbregs->dr[1]);
- load_dr2(dbregs->dr[2]);
- load_dr3(dbregs->dr[3]);
- load_dr4(dbregs->dr[4]);
- load_dr5(dbregs->dr[5]);
- load_dr6(dbregs->dr[6]);
- load_dr7(dbregs->dr[7]);
- } else {
- /*
- * Don't let an illegal value for dr7 get set. Specifically,
- * check for undefined settings. Setting these bit patterns
- * result in undefined behaviour and can lead to an unexpected
- * TRCTRAP.
- */
- for (i = 0; i < 4; i++) {
- if (DBREG_DR7_ACCESS(dbregs->dr[7], i) == 0x02)
- return (EINVAL);
- if (DBREG_DR7_LEN(dbregs->dr[7], i) == 0x02)
- return (EINVAL);
- }
-
- pcb = td->td_pcb;
-
- /*
- * Don't let a process set a breakpoint that is not within the
- * process's address space. If a process could do this, it
- * could halt the system by setting a breakpoint in the kernel
- * (if ddb was enabled). Thus, we need to check to make sure
- * that no breakpoints are being enabled for addresses outside
- * process's address space.
- *
- * XXX - what about when the watched area of the user's
- * address space is written into from within the kernel
- * ... wouldn't that still cause a breakpoint to be generated
- * from within kernel mode?
- */
-
- if (DBREG_DR7_ENABLED(dbregs->dr[7], 0)) {
- /* dr0 is enabled */
- if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (DBREG_DR7_ENABLED(dbregs->dr[7], 1)) {
- /* dr1 is enabled */
- if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (DBREG_DR7_ENABLED(dbregs->dr[7], 2)) {
- /* dr2 is enabled */
- if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- if (DBREG_DR7_ENABLED(dbregs->dr[7], 3)) {
- /* dr3 is enabled */
- if (dbregs->dr[3] >= VM_MAXUSER_ADDRESS)
- return (EINVAL);
- }
-
- pcb->pcb_dr0 = dbregs->dr[0];
- pcb->pcb_dr1 = dbregs->dr[1];
- pcb->pcb_dr2 = dbregs->dr[2];
- pcb->pcb_dr3 = dbregs->dr[3];
- pcb->pcb_dr6 = dbregs->dr[6];
- pcb->pcb_dr7 = dbregs->dr[7];
-
- pcb->pcb_flags |= PCB_DBREGS;
- }
-
- return (0);
-}
-
-/*
- * Return > 0 if a hardware breakpoint has been hit, and the
- * breakpoint was in user space. Return 0, otherwise.
- */
-int
-user_dbreg_trap(void)
-{
- u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */
- u_int32_t bp; /* breakpoint bits extracted from dr6 */
- int nbp; /* number of breakpoints that triggered */
- caddr_t addr[4]; /* breakpoint addresses */
- int i;
-
- dr7 = rdr7();
- if ((dr7 & 0x000000ff) == 0) {
- /*
- * all GE and LE bits in the dr7 register are zero,
- * thus the trap couldn't have been caused by the
- * hardware debug registers
- */
- return 0;
- }
-
- nbp = 0;
- dr6 = rdr6();
- bp = dr6 & 0x0000000f;
-
- if (!bp) {
- /*
- * None of the breakpoint bits are set meaning this
- * trap was not caused by any of the debug registers
- */
- return 0;
- }
-
- /*
- * at least one of the breakpoints were hit, check to see
- * which ones and if any of them are user space addresses
- */
-
- if (bp & 0x01) {
- addr[nbp++] = (caddr_t)rdr0();
- }
- if (bp & 0x02) {
- addr[nbp++] = (caddr_t)rdr1();
- }
- if (bp & 0x04) {
- addr[nbp++] = (caddr_t)rdr2();
- }
- if (bp & 0x08) {
- addr[nbp++] = (caddr_t)rdr3();
- }
-
- for (i = 0; i < nbp; i++) {
- if (addr[i] < (caddr_t)VM_MAXUSER_ADDRESS) {
- /*
- * addr[i] is in user space
- */
- return nbp;
- }
- }
-
- /*
- * None of the breakpoints are in user space.
- */
- return 0;
-}
-
-#ifdef KDB
-
-/*
- * Provide inb() and outb() as functions. They are normally only available as
- * inline functions, thus cannot be called from the debugger.
- */
-
-/* silence compiler warnings */
-u_char inb_(u_short);
-void outb_(u_short, u_char);
-
-u_char
-inb_(u_short port)
-{
- return inb(port);
-}
-
-void
-outb_(u_short port, u_char data)
-{
- outb(port, data);
-}
-
-#endif /* KDB */
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index f457905..87858ac 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -327,10 +327,12 @@ int bus_generic_detach(device_t dev);
void bus_generic_driver_added(device_t dev, driver_t *driver);
bus_dma_tag_t
bus_generic_get_dma_tag(device_t dev, device_t child);
+int bus_generic_get_domain(device_t dev, device_t child, int *domain);
struct resource_list *
bus_generic_get_resource_list (device_t, device_t);
void bus_generic_new_pass(device_t dev);
int bus_print_child_header(device_t dev, device_t child);
+int bus_print_child_domain(device_t dev, device_t child);
int bus_print_child_footer(device_t dev, device_t child);
int bus_generic_print_child(device_t dev, device_t child);
int bus_generic_probe(device_t dev);
diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h
index 328ce7c..a0cc52f 100644
--- a/sys/sys/cdefs.h
+++ b/sys/sys/cdefs.h
@@ -288,6 +288,8 @@
#if (defined(__cplusplus) && __cplusplus >= 201103L) || \
__has_extension(cxx_static_assert)
#define _Static_assert(x, y) static_assert(x, y)
+#elif __GNUC_PREREQ__(4,6)
+/* Nothing, gcc 4.6 and higher has _Static_assert built-in */
#elif defined(__COUNTER__)
#define _Static_assert(x, y) __Static_assert(x, __COUNTER__)
#define __Static_assert(x, y) ___Static_assert(x, y)
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 47ebd76..c712f76 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -221,6 +221,7 @@ struct knote {
struct proc *p_proc; /* proc pointer */
struct aiocblist *p_aio; /* AIO job pointer */
struct aioliojob *p_lio; /* LIO job pointer */
+ sbintime_t *p_nexttime; /* next timer event fires at */
void *p_v; /* generic other pointer */
} kn_ptr;
struct filterops *kn_fop;
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 9d23662..ac17819 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -38,6 +38,7 @@
#include <sys/event.h>
#include <sys/lock.h>
#include <sys/priority.h>
+#include <sys/seq.h>
#include <sys/sx.h>
#include <machine/_limits.h>
@@ -50,14 +51,16 @@ struct filecaps {
};
struct filedescent {
- struct file *fde_file; /* file structure for open file */
- struct filecaps fde_caps; /* per-descriptor rights */
- uint8_t fde_flags; /* per-process open file flags */
+ struct file *fde_file; /* file structure for open file */
+ struct filecaps fde_caps; /* per-descriptor rights */
+ uint8_t fde_flags; /* per-process open file flags */
+ seq_t fde_seq; /* keep file and caps in sync */
};
#define fde_rights fde_caps.fc_rights
#define fde_fcntls fde_caps.fc_fcntls
#define fde_ioctls fde_caps.fc_ioctls
#define fde_nioctls fde_caps.fc_nioctls
+#define fde_change_size (offsetof(struct filedescent, fde_seq))
/*
* This structure is used for the management of descriptors. It may be
@@ -82,6 +85,7 @@ struct filedesc {
int fd_holdleaderscount; /* block fdfree() for shared close() */
int fd_holdleaderswakeup; /* fdfree() needs wakeup */
};
+#define fd_seq(fdp, fd) (&(fdp)->fd_ofiles[(fd)].fde_seq)
/*
* Structure to keep track of (process leader, struct fildedesc) tuples.
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index d3e6ce0..a2411317 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -248,7 +248,7 @@ struct mbuf {
* Flags preserved when copying m_pkthdr.
*/
#define M_COPYFLAGS \
- (M_PKTHDR|M_EOR|M_RDONLY|M_BCAST|M_MCAST|M_VLANTAG|M_PROMISC| \
+ (M_PKTHDR|M_EOR|M_RDONLY|M_BCAST|M_MCAST|M_PROMISC|M_VLANTAG|M_FLOWID| \
M_PROTOFLAGS)
/*
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 18d92b2..eabc134 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1100036 /* Master, propagated to newvers */
+#define __FreeBSD_version 1100037 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/racct.h b/sys/sys/racct.h
index 3b34891..362529c 100644
--- a/sys/sys/racct.h
+++ b/sys/sys/racct.h
@@ -37,6 +37,7 @@
#define _RACCT_H_
#include <sys/cdefs.h>
+#include <sys/stdint.h>
#include <sys/queue.h>
#include <sys/types.h>
@@ -141,6 +142,8 @@ struct racct {
LIST_HEAD(, rctl_rule_link) r_rule_links;
};
+#ifdef RACCT
+
int racct_add(struct proc *p, int resource, uint64_t amount);
void racct_add_cred(struct ucred *cred, int resource, uint64_t amount);
void racct_add_force(struct proc *p, int resource, uint64_t amount);
@@ -162,4 +165,88 @@ void racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
struct ucred *newcred);
void racct_move(struct racct *dest, struct racct *src);
+#else
+
+static inline int
+racct_add(struct proc *p, int resource, uint64_t amount)
+{
+
+ return (0);
+}
+
+static inline void
+racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
+{
+}
+
+static inline void
+racct_add_force(struct proc *p, int resource, uint64_t amount)
+{
+}
+
+static inline int
+racct_set(struct proc *p, int resource, uint64_t amount)
+{
+
+ return (0);
+}
+
+static inline void
+racct_set_force(struct proc *p, int resource, uint64_t amount)
+{
+}
+
+static inline void
+racct_sub(struct proc *p, int resource, uint64_t amount)
+{
+}
+
+static inline void
+racct_sub_cred(struct ucred *cred, int resource, uint64_t amount)
+{
+}
+
+static inline uint64_t
+racct_get_limit(struct proc *p, int resource)
+{
+
+ return (UINT64_MAX);
+}
+
+static inline uint64_t
+racct_get_available(struct proc *p, int resource)
+{
+
+ return (UINT64_MAX);
+}
+
+static inline void
+racct_create(struct racct **racctp)
+{
+}
+
+static inline void
+racct_destroy(struct racct **racctp)
+{
+}
+
+static inline int
+racct_proc_fork(struct proc *parent, struct proc *child)
+{
+
+ return (0);
+}
+
+static inline void
+racct_proc_fork_done(struct proc *child)
+{
+}
+
+static inline void
+racct_proc_exit(struct proc *p)
+{
+}
+
+#endif
+
#endif /* !_RACCT_H_ */
diff --git a/sys/sys/seq.h b/sys/sys/seq.h
new file mode 100644
index 0000000..799b3a9
--- /dev/null
+++ b/sys/sys/seq.h
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2014 Mateusz Guzik <mjg@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_SEQ_H_
+#define _SYS_SEQ_H_
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+#endif
+#include <sys/types.h>
+
+/*
+ * seq_t may be included in structs visible to userspace
+ */
+typedef uint32_t seq_t;
+
+#ifdef _KERNEL
+
+/*
+ * Typical usage:
+ *
+ * writers:
+ * lock_exclusive(&obj->lock);
+ * seq_write_begin(&obj->seq);
+ * .....
+ * seq_write_end(&obj->seq);
+ * unlock_exclusive(&obj->unlock);
+ *
+ * readers:
+ * obj_t lobj;
+ * seq_t seq;
+ *
+ * for (;;) {
+ * seq = seq_read(&gobj->seq);
+ * lobj = gobj;
+ * if (seq_consistent(&gobj->seq, seq))
+ * break;
+ * cpu_spinwait();
+ * }
+ * foo(lobj);
+ */
+
+/* A hack to get MPASS macro */
+#include <sys/lock.h>
+
+#include <machine/cpu.h>
+
+/*
+ * This is a temporary hack until memory barriers are cleaned up.
+ *
+ * atomic_load_acq_int at least on amd64 provides a full memory barrier,
+ * in a way which affects perforance.
+ *
+ * Hack below covers all architectures and avoids most of the penalty at least
+ * on amd64.
+ */
+static __inline int
+atomic_load_acq_rmb_int(volatile u_int *p)
+{
+ volatile u_int v;
+
+ v = *p;
+ atomic_load_acq_int(&v);
+ return (v);
+}
+
+static __inline bool
+seq_in_modify(seq_t seqp)
+{
+
+ return (seqp & 1);
+}
+
+static __inline void
+seq_write_begin(seq_t *seqp)
+{
+
+ MPASS(!seq_in_modify(*seqp));
+ atomic_add_acq_int(seqp, 1);
+}
+
+static __inline void
+seq_write_end(seq_t *seqp)
+{
+
+ atomic_add_rel_int(seqp, 1);
+ MPASS(!seq_in_modify(*seqp));
+}
+
+static __inline seq_t
+seq_read(seq_t *seqp)
+{
+ seq_t ret;
+
+ for (;;) {
+ ret = atomic_load_acq_rmb_int(seqp);
+ if (seq_in_modify(ret)) {
+ cpu_spinwait();
+ continue;
+ }
+ break;
+ }
+
+ return (ret);
+}
+
+static __inline seq_t
+seq_consistent(seq_t *seqp, seq_t oldseq)
+{
+
+ return (atomic_load_acq_rmb_int(seqp) == oldseq);
+}
+
+static __inline seq_t
+seq_consistent_nomb(seq_t *seqp, seq_t oldseq)
+{
+
+ return (*seqp == oldseq);
+}
+
+#endif /* _KERNEL */
+#endif /* _SYS_SEQ_H_ */
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 5c3933b..bfdae0d 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -43,6 +43,7 @@
#include <sys/sockbuf.h>
#include <sys/sockstate.h>
#ifdef _KERNEL
+#include <sys/caprights.h>
#include <sys/sockopt.h>
#endif
@@ -318,6 +319,8 @@ extern int maxsockets;
extern u_long sb_max;
extern so_gen_t so_gencnt;
+struct file;
+struct filedesc;
struct mbuf;
struct sockaddr;
struct ucred;
@@ -336,6 +339,8 @@ struct uio;
*/
int sockargs(struct mbuf **mp, caddr_t buf, int buflen, int type);
int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
+int getsock_cap(struct filedesc *fdp, int fd, cap_rights_t *rightsp,
+ struct file **fpp, u_int *fflagp);
void soabort(struct socket *so);
int soaccept(struct socket *so, struct sockaddr **nam);
int socheckuid(struct socket *so, uid_t uid);
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
index a495008..576b420 100644
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 263318 2014-03-18 21:32:03Z attilio
+ * created from FreeBSD: head/sys/kern/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
#define SYS_syscall 0
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
index 7095556..47d2046 100644
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -1,7 +1,7 @@
# FreeBSD system call names.
# DO NOT EDIT-- this file is automatically generated.
# $FreeBSD$
-# created from FreeBSD: head/sys/kern/syscalls.master 263318 2014-03-18 21:32:03Z attilio
+# created from FreeBSD: head/sys/kern/syscalls.master 272823 2014-10-09 15:16:52Z marcel
MIASM = \
syscall.o \
exit.o \
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
index 5087a4c..3d203ad 100644
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 263318 2014-03-18 21:32:03Z attilio
+ * created from FreeBSD: head/sys/kern/syscalls.master 272823 2014-10-09 15:16:52Z marcel
*/
#ifndef _SYS_SYSPROTO_H_
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 0f2732c..eae7272 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -232,6 +232,7 @@ void hexdump(const void *ptr, int length, const char *hdr, int flags);
#define ovbcopy(f, t, l) bcopy((f), (t), (l))
void bcopy(const void *from, void *to, size_t len) __nonnull(1) __nonnull(2);
void bzero(void *buf, size_t len) __nonnull(1);
+void explicit_bzero(void *, size_t) __nonnull(1);;
void *memcpy(void *to, const void *from, size_t len) __nonnull(1) __nonnull(2);
void *memmove(void *dest, const void *src, size_t n) __nonnull(1) __nonnull(2);
@@ -443,4 +444,6 @@ bitcount16(uint32_t x)
return (x);
}
+void intr_prof_stack_use(struct thread *td, struct trapframe *frame);
+
#endif /* !_SYS_SYSTM_H_ */
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index e1648d4..81e4520 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -108,7 +108,6 @@ void cred_update_thread(struct thread *td);
void crfree(struct ucred *cr);
struct ucred *crget(void);
struct ucred *crhold(struct ucred *cr);
-int crshared(struct ucred *cr);
void cru2x(struct ucred *cr, struct xucred *xcr);
void crsetgroups(struct ucred *cr, int n, gid_t *groups);
int groupmember(gid_t gid, struct ucred *cred);
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 6b07295..8610aca 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -305,6 +305,7 @@ struct vattr {
#define IO_NORMAL 0x0800 /* operate on regular data */
#define IO_NOMACCHECK 0x1000 /* MAC checks unnecessary */
#define IO_BUFLOCKED 0x2000 /* ffs flag; indir buf is locked */
+#define IO_RANGELOCKED 0x4000 /* range locked */
#define IO_SEQMAX 0x7F /* seq heuristic max value */
#define IO_SEQSHIFT 16 /* seq heuristic in upper 16 bits */
diff --git a/sys/ufs/ufs/dir.h b/sys/ufs/ufs/dir.h
index 65f3ab1..574a32f 100644
--- a/sys/ufs/ufs/dir.h
+++ b/sys/ufs/ufs/dir.h
@@ -110,7 +110,7 @@ struct direct {
*
*/
#define DIRECTSIZ(namlen) \
- (((uintptr_t)&((struct direct *)0)->d_name + \
+ ((__offsetof(struct direct, d_name) + \
((namlen)+1)*sizeof(((struct direct *)0)->d_name[0]) + 3) & ~3)
#if (BYTE_ORDER == LITTLE_ENDIAN)
#define DIRSIZ(oldfmt, dp) \
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 81b714a..8527b09 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -135,8 +135,8 @@ static LIST_HEAD(,uma_keg) uma_kegs = LIST_HEAD_INITIALIZER(uma_kegs);
static LIST_HEAD(,uma_zone) uma_cachezones =
LIST_HEAD_INITIALIZER(uma_cachezones);
-/* This mutex protects the keg list */
-static struct mtx_padalign uma_mtx;
+/* This RW lock protects the keg list */
+static struct rwlock_padalign uma_rwlock;
/* Linked list of boot time pages */
static LIST_HEAD(,uma_slab) uma_boot_pages =
@@ -897,16 +897,14 @@ zone_drain_wait(uma_zone_t zone, int waitok)
while (zone->uz_flags & UMA_ZFLAG_DRAINING) {
if (waitok == M_NOWAIT)
goto out;
- mtx_unlock(&uma_mtx);
msleep(zone, zone->uz_lockptr, PVM, "zonedrain", 1);
- mtx_lock(&uma_mtx);
}
zone->uz_flags |= UMA_ZFLAG_DRAINING;
bucket_cache_drain(zone);
ZONE_UNLOCK(zone);
/*
* The DRAINING flag protects us from being freed while
- * we're running. Normally the uma_mtx would protect us but we
+ * we're running. Normally the uma_rwlock would protect us but we
* must be able to release and acquire the right lock for each keg.
*/
zone_foreach_keg(zone, &keg_drain);
@@ -1542,9 +1540,9 @@ keg_ctor(void *mem, int size, void *udata, int flags)
LIST_INSERT_HEAD(&keg->uk_zones, zone, uz_link);
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_INSERT_HEAD(&uma_kegs, keg, uk_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
return (0);
}
@@ -1594,9 +1592,9 @@ zone_ctor(void *mem, int size, void *udata, int flags)
zone->uz_release = arg->release;
zone->uz_arg = arg->arg;
zone->uz_lockptr = &zone->uz_lock;
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_INSERT_HEAD(&uma_cachezones, zone, uz_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
goto out;
}
@@ -1613,7 +1611,7 @@ zone_ctor(void *mem, int size, void *udata, int flags)
zone->uz_fini = arg->fini;
zone->uz_lockptr = &keg->uk_lock;
zone->uz_flags |= UMA_ZONE_SECONDARY;
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
ZONE_LOCK(zone);
LIST_FOREACH(z, &keg->uk_zones, uz_link) {
if (LIST_NEXT(z, uz_link) == NULL) {
@@ -1622,7 +1620,7 @@ zone_ctor(void *mem, int size, void *udata, int flags)
}
}
ZONE_UNLOCK(zone);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
} else if (keg == NULL) {
if ((keg = uma_kcreate(zone, arg->size, arg->uminit, arg->fini,
arg->align, arg->flags)) == NULL)
@@ -1720,9 +1718,9 @@ zone_dtor(void *arg, int size, void *udata)
if (!(zone->uz_flags & UMA_ZFLAG_INTERNAL))
cache_drain(zone);
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_REMOVE(zone, uz_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
/*
* XXX there are some races here where
* the zone can be drained but zone lock
@@ -1744,9 +1742,9 @@ zone_dtor(void *arg, int size, void *udata)
* We only destroy kegs from non secondary zones.
*/
if (keg != NULL && (zone->uz_flags & UMA_ZONE_SECONDARY) == 0) {
- mtx_lock(&uma_mtx);
+ rw_wlock(&uma_rwlock);
LIST_REMOVE(keg, uk_link);
- mtx_unlock(&uma_mtx);
+ rw_wunlock(&uma_rwlock);
zone_free_item(kegs, keg, NULL, SKIP_NONE);
}
ZONE_LOCK_FINI(zone);
@@ -1768,12 +1766,12 @@ zone_foreach(void (*zfunc)(uma_zone_t))
uma_keg_t keg;
uma_zone_t zone;
- mtx_lock(&uma_mtx);
+ rw_rlock(&uma_rwlock);
LIST_FOREACH(keg, &uma_kegs, uk_link) {
LIST_FOREACH(zone, &keg->uk_zones, uz_link)
zfunc(zone);
}
- mtx_unlock(&uma_mtx);
+ rw_runlock(&uma_rwlock);
}
/* Public functions */
@@ -1789,7 +1787,7 @@ uma_startup(void *bootmem, int boot_pages)
#ifdef UMA_DEBUG
printf("Creating uma keg headers zone and keg.\n");
#endif
- mtx_init(&uma_mtx, "UMA lock", NULL, MTX_DEF);
+ rw_init(&uma_rwlock, "UMA lock");
/* "manually" create the initial zone */
memset(&args, 0, sizeof(args));
@@ -3364,12 +3362,12 @@ sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS)
int count;
count = 0;
- mtx_lock(&uma_mtx);
+ rw_rlock(&uma_rwlock);
LIST_FOREACH(kz, &uma_kegs, uk_link) {
LIST_FOREACH(z, &kz->uk_zones, uz_link)
count++;
}
- mtx_unlock(&uma_mtx);
+ rw_runlock(&uma_rwlock);
return (sysctl_handle_int(oidp, &count, 0, req));
}
@@ -3394,7 +3392,7 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS)
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
count = 0;
- mtx_lock(&uma_mtx);
+ rw_rlock(&uma_rwlock);
LIST_FOREACH(kz, &uma_kegs, uk_link) {
LIST_FOREACH(z, &kz->uk_zones, uz_link)
count++;
@@ -3470,7 +3468,7 @@ skip:
ZONE_UNLOCK(z);
}
}
- mtx_unlock(&uma_mtx);
+ rw_runlock(&uma_rwlock);
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
return (error);
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index 61c003b..c9ee890 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "opt_vm.h"
#include "opt_kstack_pages.h"
#include "opt_kstack_max_pages.h"
+#include "opt_kstack_usage_prof.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -98,6 +99,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_pager.h>
#include <vm/swap_pager.h>
+#include <machine/cpu.h>
+
#ifndef NO_SWAPPING
static int swapout(struct proc *);
static void swapclear(struct proc *);
@@ -486,6 +489,52 @@ kstack_cache_init(void *nulll)
SYSINIT(vm_kstacks, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, kstack_cache_init, NULL);
+#ifdef KSTACK_USAGE_PROF
+/*
+ * Track maximum stack used by a thread in kernel.
+ */
+static int max_kstack_used;
+
+SYSCTL_INT(_debug, OID_AUTO, max_kstack_used, CTLFLAG_RD,
+ &max_kstack_used, 0,
+ "Maxiumum stack depth used by a thread in kernel");
+
+void
+intr_prof_stack_use(struct thread *td, struct trapframe *frame)
+{
+ vm_offset_t stack_top;
+ vm_offset_t current;
+ int used, prev_used;
+
+ /*
+ * Testing for interrupted kernel mode isn't strictly
+ * needed. It optimizes the execution, since interrupts from
+ * usermode will have only the trap frame on the stack.
+ */
+ if (TRAPF_USERMODE(frame))
+ return;
+
+ stack_top = td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
+ current = (vm_offset_t)(uintptr_t)&stack_top;
+
+ /*
+ * Try to detect if interrupt is using kernel thread stack.
+ * Hardware could use a dedicated stack for interrupt handling.
+ */
+ if (stack_top <= current || current < td->td_kstack)
+ return;
+
+ used = stack_top - current;
+ for (;;) {
+ prev_used = max_kstack_used;
+ if (prev_used >= used)
+ break;
+ if (atomic_cmpset_int(&max_kstack_used, prev_used, used))
+ break;
+ }
+}
+#endif /* KSTACK_USAGE_PROF */
+
#ifndef NO_SWAPPING
/*
* Allow a thread's kernel stack to be paged out.
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 24b9f6d..ca9d7f9 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -76,6 +76,7 @@
__FBSDID("$FreeBSD$");
#include "opt_vm.h"
+#include "opt_kdtrace.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -89,6 +90,7 @@ __FBSDID("$FreeBSD$");
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
+#include <sys/sdt.h>
#include <sys/signalvar.h>
#include <sys/smp.h>
#include <sys/vnode.h>
@@ -133,6 +135,10 @@ static struct kproc_desc page_kp = {
SYSINIT(pagedaemon, SI_SUB_KTHREAD_PAGE, SI_ORDER_SECOND, kproc_start,
&page_kp);
+SDT_PROVIDER_DEFINE(vm);
+SDT_PROBE_DEFINE(vm, , , vm__lowmem_cache);
+SDT_PROBE_DEFINE(vm, , , vm__lowmem_scan);
+
#if !defined(NO_SWAPPING)
/* the kernel process "vm_daemon"*/
static void vm_daemon(void);
@@ -667,6 +673,7 @@ vm_pageout_grow_cache(int tries, vm_paddr_t low, vm_paddr_t high)
* may acquire locks and/or sleep, so they can only be invoked
* when "tries" is greater than zero.
*/
+ SDT_PROBE0(vm, , , vm__lowmem_cache);
EVENTHANDLER_INVOKE(vm_lowmem, 0);
/*
@@ -920,6 +927,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
/*
* Decrease registered cache sizes.
*/
+ SDT_PROBE0(vm, , , vm__lowmem_scan);
EVENTHANDLER_INVOKE(vm_lowmem, 0);
/*
* We do this explicitly after the caches have been
diff --git a/sys/x86/acpica/srat.c b/sys/x86/acpica/srat.c
index a275220..c4d205b 100644
--- a/sys/x86/acpica/srat.c
+++ b/sys/x86/acpica/srat.c
@@ -62,6 +62,8 @@ int num_mem;
static ACPI_TABLE_SRAT *srat;
static vm_paddr_t srat_physaddr;
+static int vm_domains[VM_PHYSSEG_MAX];
+
static void srat_walk_table(acpi_subtable_handler *handler, void *arg);
/*
@@ -247,7 +249,6 @@ check_phys_avail(void)
static int
renumber_domains(void)
{
- int domains[VM_PHYSSEG_MAX];
int i, j, slot;
/* Enumerate all the domains. */
@@ -255,17 +256,17 @@ renumber_domains(void)
for (i = 0; i < num_mem; i++) {
/* See if this domain is already known. */
for (j = 0; j < vm_ndomains; j++) {
- if (domains[j] >= mem_info[i].domain)
+ if (vm_domains[j] >= mem_info[i].domain)
break;
}
- if (j < vm_ndomains && domains[j] == mem_info[i].domain)
+ if (j < vm_ndomains && vm_domains[j] == mem_info[i].domain)
continue;
/* Insert the new domain at slot 'j'. */
slot = j;
for (j = vm_ndomains; j > slot; j--)
- domains[j] = domains[j - 1];
- domains[slot] = mem_info[i].domain;
+ vm_domains[j] = vm_domains[j - 1];
+ vm_domains[slot] = mem_info[i].domain;
vm_ndomains++;
if (vm_ndomains > MAXMEMDOM) {
vm_ndomains = 1;
@@ -280,15 +281,15 @@ renumber_domains(void)
* If the domain is already the right value, no need
* to renumber.
*/
- if (domains[i] == i)
+ if (vm_domains[i] == i)
continue;
/* Walk the cpu[] and mem_info[] arrays to renumber. */
for (j = 0; j < num_mem; j++)
- if (mem_info[j].domain == domains[i])
+ if (mem_info[j].domain == vm_domains[i])
mem_info[j].domain = i;
for (j = 0; j <= MAX_APIC_ID; j++)
- if (cpus[j].enabled && cpus[j].domain == domains[i])
+ if (cpus[j].enabled && cpus[j].domain == vm_domains[i])
cpus[j].domain = i;
}
KASSERT(vm_ndomains > 0,
@@ -368,4 +369,23 @@ srat_set_cpus(void *dummy)
}
}
SYSINIT(srat_set_cpus, SI_SUB_CPU, SI_ORDER_ANY, srat_set_cpus, NULL);
+
+/*
+ * Map a _PXM value to a VM domain ID.
+ *
+ * Returns the domain ID, or -1 if no domain ID was found.
+ */
+int
+acpi_map_pxm_to_vm_domainid(int pxm)
+{
+ int i;
+
+ for (i = 0; i < vm_ndomains; i++) {
+ if (vm_domains[i] == pxm)
+ return (i);
+ }
+
+ return (-1);
+}
+
#endif /* MAXMEMDOM > 1 */
diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h
index 0e7bb44..bf00bc5 100644
--- a/sys/x86/include/specialreg.h
+++ b/sys/x86/include/specialreg.h
@@ -382,6 +382,7 @@
#define MSR_BIOS_SIGN 0x08b
#define MSR_PERFCTR0 0x0c1
#define MSR_PERFCTR1 0x0c2
+#define MSR_PLATFORM_INFO 0x0ce
#define MSR_MPERF 0x0e7
#define MSR_APERF 0x0e8
#define MSR_IA32_EXT_CONFIG 0x0ee /* Undocumented. Core Solo/Duo only */
@@ -405,6 +406,8 @@
#define MSR_THERM_STATUS 0x19c
#define MSR_IA32_MISC_ENABLE 0x1a0
#define MSR_IA32_TEMPERATURE_TARGET 0x1a2
+#define MSR_TURBO_RATIO_LIMIT 0x1ad
+#define MSR_TURBO_RATIO_LIMIT1 0x1ae
#define MSR_DEBUGCTLMSR 0x1d9
#define MSR_LASTBRANCHFROMIP 0x1db
#define MSR_LASTBRANCHTOIP 0x1dc
@@ -438,6 +441,7 @@
#define MSR_MC4_STATUS 0x411
#define MSR_MC4_ADDR 0x412
#define MSR_MC4_MISC 0x413
+#define MSR_RAPL_POWER_UNIT 0x606
#define MSR_PKG_ENERGY_STATUS 0x611
#define MSR_DRAM_ENERGY_STATUS 0x619
#define MSR_PP0_ENERGY_STATUS 0x639
diff --git a/sys/x86/x86/dump_machdep.c b/sys/x86/x86/dump_machdep.c
index 940c519..4e048bf 100644
--- a/sys/x86/x86/dump_machdep.c
+++ b/sys/x86/x86/dump_machdep.c
@@ -275,10 +275,9 @@ dumpsys(struct dumperinfo *di)
size_t hdrsz;
int error;
- if (do_minidump) {
- minidumpsys(di);
- return (0);
- }
+ if (do_minidump)
+ return (minidumpsys(di));
+
bzero(&ehdr, sizeof(ehdr));
ehdr.e_ident[EI_MAG0] = ELFMAG0;
ehdr.e_ident[EI_MAG1] = ELFMAG1;
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 2aa18f5..e3228ce 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -1366,7 +1366,7 @@ apic_init(void *dummy __unused)
printf("APIC: Using the %s enumerator.\n",
best_enum->apic_name);
-#ifndef __amd64__
+#ifdef I686_CPU
/*
* To work around an errata, we disable the local APIC on some
* CPUs during early startup. We need to turn the local APIC back
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index a12775b8b..d0fd1d8 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -591,13 +591,18 @@ OLD_FILES+=usr/share/man/man1/ctm_smail.1.gz
OLD_FILES+=usr/share/man/man5/ctm.5.gz
.endif
-# devd(8) and gperf(1) not listed here on purpose
+# devd(8) not listed here on purpose
.if ${MK_CXX} == no
OLD_FILES+=usr/bin/CC
OLD_FILES+=usr/bin/c++
OLD_FILES+=usr/bin/c++filt
OLD_FILES+=usr/bin/g++
OLD_FILES+=usr/libexec/cc1plus
+.if ${MK_GCC} == no
+OLD_FILES+=usr/bin/gperf
+OLD_FILES+=usr/share/info/gperf.info.gz
+OLD_FILES+=usr/share/man/man1/gperf.1.gz
+.endif
.endif
.if ${MK_FMTREE} == no
diff --git a/tools/sched/schedgraph.py b/tools/sched/schedgraph.py
index e592514..007c9f4 100644
--- a/tools/sched/schedgraph.py
+++ b/tools/sched/schedgraph.py
@@ -80,8 +80,6 @@ eventcolors = [
("runq rem", "yellow"),
("thread exit", "grey"),
("proc exit", "grey"),
- ("callwheel idle", "grey"),
- ("callout running", "green"),
("lock acquire", "blue"),
("lock contest", "purple"),
("failed lock try", "red"),
@@ -903,7 +901,6 @@ class KTRFile:
self.timestamp_f = None
self.timestamp_l = None
self.locks = {}
- self.callwheels = {}
self.ticks = {}
self.load = {}
self.crit = {}
diff --git a/tools/tools/ath/athalq/ar9300_ds.c b/tools/tools/ath/athalq/ar9300_ds.c
index d303351..a554929 100644
--- a/tools/tools/ath/athalq/ar9300_ds.c
+++ b/tools/tools/ath/athalq/ar9300_ds.c
@@ -317,6 +317,80 @@ ar9300_decode_rxstatus(struct if_ath_alq_payload *a)
(unsigned int) be32toh(a->hdr.tstamp_sec),
(unsigned int) be32toh(a->hdr.tstamp_usec),
(unsigned long long) be64toh(a->hdr.threadid));
+
+ /* status1 */
+ /* .. and status5 */
+ printf(" RSSI %d/%d/%d / %d/%d/%d; combined: %d; rate=0x%02x\n",
+ MS(rxs.status1, AR_rx_rssi_ant00),
+ MS(rxs.status1, AR_rx_rssi_ant01),
+ MS(rxs.status1, AR_rx_rssi_ant02),
+ MS(rxs.status5, AR_rx_rssi_ant10),
+ MS(rxs.status5, AR_rx_rssi_ant11),
+ MS(rxs.status5, AR_rx_rssi_ant12),
+ MS(rxs.status5, AR_rx_rssi_combined),
+ MS(rxs.status1, AR_rx_rate));
+
+ /* status2 */
+ printf(" Len: %d; more=%d, delim=%d, upload=%d\n",
+ MS(rxs.status2, AR_data_len),
+ MF(rxs.status2, AR_rx_more),
+ MS(rxs.status2, AR_num_delim),
+ MS(rxs.status2, AR_hw_upload_data));
+
+ /* status3 */
+ printf(" RX timestamp: %d\n", rxs.status3);
+
+ /* status4 */
+ printf(" GI: %d, 2040: %d, parallel40: %d, stbc=%d\n",
+ MF(rxs.status4, AR_gi),
+ MF(rxs.status4, AR_2040),
+ MF(rxs.status4, AR_parallel40),
+ MF(rxs.status4, AR_rx_stbc));
+ printf(" Not sounding: %d, ness: %d, upload_valid: %d\n",
+ MF(rxs.status4, AR_rx_not_sounding),
+ MS(rxs.status4, AR_rx_ness),
+ MS(rxs.status4, AR_hw_upload_data_valid));
+ printf(" RX antenna: 0x%08x\n",
+ MS(rxs.status4, AR_rx_antenna));
+
+ /* EVM */
+ /* status6 - 9 */
+ printf(" EVM: 0x%08x; 0x%08x; 0x%08x; 0x%08x\n",
+ rxs.status6,
+ rxs.status7,
+ rxs.status8,
+ rxs.status9);
+
+ /* status10 - ? */
+
+ /* status11 */
+ printf(" RX done: %d, RX frame ok: %d, CRC error: %d\n",
+ MF(rxs.status11, AR_rx_done),
+ MF(rxs.status11, AR_rx_frame_ok),
+ MF(rxs.status11, AR_crc_err));
+ printf(" Decrypt CRC err: %d, PHY err: %d, MIC err: %d\n",
+ MF(rxs.status11, AR_decrypt_crc_err),
+ MF(rxs.status11, AR_phyerr),
+ MF(rxs.status11, AR_michael_err));
+ printf(" Pre delim CRC err: %d, uAPSD Trig: %d\n",
+ MF(rxs.status11, AR_pre_delim_crc_err),
+ MF(rxs.status11, AR_apsd_trig));
+ printf(" RXKeyIdxValid: %d, KeyIdx: %d, PHY error: %d\n",
+ MF(rxs.status11, AR_rx_key_idx_valid),
+ MS(rxs.status11, AR_key_idx),
+ MS(rxs.status11, AR_phy_err_code));
+ printf(" RX more Aggr: %d, RX aggr %d, post delim CRC err: %d\n",
+ MF(rxs.status11, AR_rx_more_aggr),
+ MF(rxs.status11, AR_rx_aggr),
+ MF(rxs.status11, AR_post_delim_crc_err));
+ printf(" hw upload data type: %d; position bit: %d\n",
+ MS(rxs.status11, AR_hw_upload_data_type),
+ MF(rxs.status11, AR_position_bit));
+ printf(" Hi RX chain: %d, RxFirstAggr: %d, DecryptBusy: %d, KeyMiss: %d\n",
+ MF(rxs.status11, AR_hi_rx_chain),
+ MF(rxs.status11, AR_rx_first_aggr),
+ MF(rxs.status11, AR_decrypt_busy_err),
+ MF(rxs.status11, AR_key_miss));
}
void
diff --git a/tools/tools/bootparttest/Makefile b/tools/tools/bootparttest/Makefile
index 46a8d70..c7de091 100644
--- a/tools/tools/bootparttest/Makefile
+++ b/tools/tools/bootparttest/Makefile
@@ -7,13 +7,14 @@ BINDIR?= /usr/bin
PROG= bootparttest
MAN=
-SRCS= bootparttest.c crc32.c malloc.c part.c
+SRCS= bootparttest.c crc32.c stub.c part.c disk.c
-CFLAGS= -I${.CURDIR}/../../../sys/boot/common -I. \
- -DLOADER_GPT_SUPPORT -DLOADER_MBR_SUPPORT -DPART_DEBUG
+CFLAGS= -I${.CURDIR}/../../../sys/boot/common \
+ -DLOADER_GPT_SUPPORT -DLOADER_MBR_SUPPORT -DPART_DEBUG \
+ -DDISK_DEBUG
-DPADD+= ${LIBGEOM} ${LIBUTIL}
-LDADD+= ${LIBGEOM} ${LIBUTIL}
-LDFLAGS+= -lgeom -lutil
+DPADD+= ${LIBGEOM}
+LDADD+= ${LIBGEOM}
+LDFLAGS+= -lgeom
.include <bsd.prog.mk>
diff --git a/tools/tools/bootparttest/bootparttest.c b/tools/tools/bootparttest/bootparttest.c
index f0fb8a9..0987652 100644
--- a/tools/tools/bootparttest/bootparttest.c
+++ b/tools/tools/bootparttest/bootparttest.c
@@ -33,140 +33,106 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <fcntl.h>
#include <libgeom.h>
-#include <libutil.h>
+#include <disk.h>
#include <part.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
+static int disk_strategy(void *devdata, int rw, daddr_t blk,
+ size_t size, char *buf, size_t *rsize);
+
+/* stub struct devsw */
+struct devsw {
+ const char dv_name[8];
+ int dv_type;
+ void *dv_init;
+ int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
+ size_t size, char *buf, size_t *rsize);
+ void *dv_open;
+ void *dv_close;
+ void *dv_ioctl;
+ void *dv_print;
+ void *dv_cleanup;
+} udisk = {
+ .dv_name = "disk",
+ .dv_strategy = disk_strategy
+};
+
struct disk {
- const char *name;
uint64_t mediasize;
uint16_t sectorsize;
int fd;
int file;
- off_t offset;
-};
+} disk;
static int
-diskread(void *arg, void *buf, size_t blocks, off_t offset)
+disk_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
+ size_t *rsize)
{
- struct disk *dp;
+ struct disk_devdesc *dev = devdata;
+ int ret;
- dp = (struct disk *)arg;
- printf("%s: read %lu blocks from the offset %jd [+%jd]\n", dp->name,
- blocks, offset, dp->offset);
- if (offset >= dp->mediasize / dp->sectorsize)
+ if (rw != 1 /* F_READ */)
return (-1);
-
- return (pread(dp->fd, buf, blocks * dp->sectorsize,
- (offset + dp->offset) * dp->sectorsize) != blocks * dp->sectorsize);
-}
-
-static const char*
-ptable_type2str(const struct ptable *table)
-{
-
- switch (ptable_gettype(table)) {
- case PTABLE_NONE:
- return ("None");
- case PTABLE_BSD:
- return ("BSD");
- case PTABLE_MBR:
- return ("MBR");
- case PTABLE_GPT:
- return ("GPT");
- case PTABLE_VTOC8:
- return ("VTOC8");
- };
- return ("Unknown");
-}
-
-#define PWIDTH 35
-static void
-ptable_print(void *arg, const char *pname, const struct ptable_entry *part)
-{
- struct ptable *table;
- struct disk *dp, bsd;
- char line[80], size[6];
-
- dp = (struct disk *)arg;
- sprintf(line, " %s%s: %s", dp->file ? "disk0": dp->name, pname,
- parttype2str(part->type));
- humanize_number(size, sizeof(size),
- (part->end - part->start + 1) * dp->sectorsize, "",
- HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
- printf("%-*s%s\n", PWIDTH, line, size);
- if (part->type == PART_FREEBSD) {
- sprintf(line, "%s%s", dp->file ? "disk0": dp->name, pname);
- bsd.name = line;
- bsd.fd = dp->fd;
- bsd.file = 0; /* to use dp->name in the next sprintf */
- bsd.offset = dp->offset + part->start;
- bsd.sectorsize = dp->sectorsize;
- bsd.mediasize = (part->end - part->start + 1) * dp->sectorsize;
- table = ptable_open(&bsd, bsd.mediasize / bsd.sectorsize,
- bsd.sectorsize, diskread);
- if (table == NULL)
- return;
- ptable_iterate(table, &bsd, ptable_print);
- ptable_close(table);
- }
-}
-#undef PWIDTH
-
-static void
-inspect_disk(struct disk *dp)
-{
- struct ptable *table;
-
- table = ptable_open(dp, dp->mediasize / dp->sectorsize,
- dp->sectorsize, diskread);
- if (table == NULL) {
- printf("ptable_open failed\n");
- return;
- }
- printf("Partition table detected: %s\n", ptable_type2str(table));
- ptable_iterate(table, dp, ptable_print);
- ptable_close(table);
+ if (rsize)
+ *rsize = 0;
+ printf("read %zu bytes from the block %lld [+%lld]\n", size,
+ (long long)blk, (long long)dev->d_offset);
+ ret = pread(disk.fd, buf, size,
+ (blk + dev->d_offset) * disk.sectorsize);
+ if (ret != size)
+ return (-1);
+ return (0);
}
int
main(int argc, char **argv)
{
+ struct disk_devdesc dev;
struct stat sb;
- struct disk d;
+ const char *p;
if (argc < 2)
errx(1, "Usage: %s <GEOM provider name> | "
"<disk image file name>", argv[0]);
- d.name = argv[1];
- if (stat(d.name, &sb) == 0 && S_ISREG(sb.st_mode)) {
- d.fd = open(d.name, O_RDONLY);
- if (d.fd < 0)
- err(1, "open %s", d.name);
- d.mediasize = sb.st_size;
- d.sectorsize = 512;
- d.file = 1;
+ memset(&disk, 0, sizeof(disk));
+ memset(&dev, 0, sizeof(dev));
+ dev.d_dev = &udisk;
+ dev.d_slice = -1;
+ dev.d_partition = -1;
+ if (stat(argv[1], &sb) == 0 && S_ISREG(sb.st_mode)) {
+ disk.fd = open(argv[1], O_RDONLY);
+ if (disk.fd < 0)
+ err(1, "open %s", argv[1]);
+ disk.mediasize = sb.st_size;
+ disk.sectorsize = 512;
+ disk.file = 1;
} else {
- d.fd = g_open(d.name, 0);
- if (d.fd < 0)
- err(1, "g_open %s", d.name);
- d.mediasize = g_mediasize(d.fd);
- d.sectorsize = g_sectorsize(d.fd);
- d.file = 0;
+ disk.fd = g_open(argv[1], 0);
+ if (disk.fd < 0)
+ err(1, "g_open %s", argv[1]);
+ disk.mediasize = g_mediasize(disk.fd);
+ disk.sectorsize = g_sectorsize(disk.fd);
+ p = strpbrk(argv[1], "0123456789");
+ if (p != NULL)
+ disk_parsedev(&dev, p, NULL);
}
- d.offset = 0;
- printf("%s \"%s\" opened\n", d.file ? "Disk image": "GEOM provider",
- d.name);
+ printf("%s \"%s\" opened\n", disk.file ? "Disk image": "GEOM provider",
+ argv[1]);
printf("Mediasize: %ju Bytes (%ju sectors)\nSectorsize: %u Bytes\n",
- d.mediasize, d.mediasize / d.sectorsize, d.sectorsize);
+ disk.mediasize, disk.mediasize / disk.sectorsize, disk.sectorsize);
- inspect_disk(&d);
+ if (disk_open(&dev, disk.mediasize, disk.sectorsize, 0) != 0)
+ errx(1, "disk_open failed");
+ printf("\tdisk0:\n");
+ disk_print(&dev, "\tdisk0", 1);
+ disk_close(&dev);
- if (d.file)
- close(d.fd);
+ if (disk.file)
+ close(disk.fd);
else
- g_close(d.fd);
+ g_close(disk.fd);
return (0);
}
diff --git a/tools/tools/bootparttest/malloc.c b/tools/tools/bootparttest/stub.c
index bc5d65f..dccf425 100644
--- a/tools/tools/bootparttest/malloc.c
+++ b/tools/tools/bootparttest/stub.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include <stdlib.h>
+#include <stdio.h>
void*
Malloc(size_t size, const char *file, int line)
@@ -42,3 +43,10 @@ Free(void *ptr, const char *file, int line)
return (free(ptr));
}
+
+void
+pager_output(const char *s)
+{
+
+ printf("%s", s);
+}
diff --git a/usr.bin/basename/Makefile b/usr.bin/basename/Makefile
index d647395..b392c3f 100644
--- a/usr.bin/basename/Makefile
+++ b/usr.bin/basename/Makefile
@@ -1,7 +1,13 @@
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= basename
MLINKS= basename.1 dirname.1
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/basename/tests/Makefile b/usr.bin/basename/tests/Makefile
new file mode 100644
index 0000000..32dedab
--- /dev/null
+++ b/usr.bin/basename/tests/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/basename
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/basename
+ATF_TESTS_SH= basename_test
+ATF_TESTS_SH_SRC_basename_test= t_basename.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/cmp/Makefile b/usr.bin/cmp/Makefile
index d93f54b..5b9fdfc 100644
--- a/usr.bin/cmp/Makefile
+++ b/usr.bin/cmp/Makefile
@@ -1,7 +1,13 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= cmp
SRCS= cmp.c link.c misc.c regular.c special.c
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/cmp/tests/Makefile b/usr.bin/cmp/tests/Makefile
new file mode 100644
index 0000000..1c054c6
--- /dev/null
+++ b/usr.bin/cmp/tests/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/cmp
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/cmp
+ATF_TESTS_SH= cmp_test
+ATF_TESTS_SH_SRC_cmp_test= t_cmp.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/cut/Makefile b/usr.bin/cut/Makefile
index 5be029a..21c1a1c 100644
--- a/usr.bin/cut/Makefile
+++ b/usr.bin/cut/Makefile
@@ -1,6 +1,12 @@
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= cut
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/cut/tests/Makefile b/usr.bin/cut/tests/Makefile
new file mode 100644
index 0000000..b324a78
--- /dev/null
+++ b/usr.bin/cut/tests/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/cut
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/cut
+ATF_TESTS_SH= cut_test
+ATF_TESTS_SH_SRC_cut_test= t_cut.sh
+
+FILESDIR= ${TESTSDIR}
+FILES= d_basic.out
+FILES+= d_cut.in
+FILES+= d_dflag.out
+FILES+= d_dsflag.out
+FILES+= d_latin1.in
+FILES+= d_sflag.out
+FILES+= d_utf8.in
+
+.include <bsd.test.mk>
diff --git a/usr.bin/dirname/Makefile b/usr.bin/dirname/Makefile
index fb0e660..be9193c 100644
--- a/usr.bin/dirname/Makefile
+++ b/usr.bin/dirname/Makefile
@@ -1,7 +1,13 @@
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= dirname
MAN=
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/dirname/tests/Makefile b/usr.bin/dirname/tests/Makefile
new file mode 100644
index 0000000..5b84c57
--- /dev/null
+++ b/usr.bin/dirname/tests/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/dirname
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/dirname
+ATF_TESTS_SH= dirname_test
+ATF_TESTS_SH_SRC_dirname_test= t_dirname.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
index 511edf2..32be74d 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -1506,7 +1506,7 @@ c_size(OPTION *option, char ***argvp)
scale = 0x40000000LL;
break;
case 'T': /* terabytes 1<<40 */
- scale = 0x1000000000LL;
+ scale = 0x10000000000LL;
break;
case 'P': /* petabytes 1<<50 */
scale = 0x4000000000000LL;
diff --git a/usr.bin/grep/Makefile b/usr.bin/grep/Makefile
index a4c614f..32941fd 100644
--- a/usr.bin/grep/Makefile
+++ b/usr.bin/grep/Makefile
@@ -85,4 +85,8 @@ DPADD+= ${LIBGNUREGEX}
CFLAGS+= -DWITHOUT_NLS
.endif
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/grep/tests/Makefile b/usr.bin/grep/tests/Makefile
new file mode 100644
index 0000000..59b948c
--- /dev/null
+++ b/usr.bin/grep/tests/Makefile
@@ -0,0 +1,41 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/grep
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/grep
+
+ATF_TESTS_SH= grep_test
+ATF_TESTS_SH_SRC_grep_test= t_grep.sh
+
+FILESDIR= ${TESTSDIR}
+FILES= d_basic.out
+FILES+= d_begin_end_a.out
+FILES+= d_begin_end_b.out
+FILES+= d_binary.out
+FILES+= d_context2_a.out
+FILES+= d_context2_b.out
+FILES+= d_context2_c.out
+FILES+= d_context_a.in
+FILES+= d_context_a.out
+FILES+= d_context_b.in
+FILES+= d_context_b.out
+FILES+= d_context_c.out
+FILES+= d_context_d.out
+FILES+= d_egrep.out
+FILES+= d_file_exp.in
+FILES+= d_file_exp.out
+FILES+= d_ignore_case.out
+FILES+= d_input
+FILES+= d_invert.in
+FILES+= d_invert.out
+FILES+= d_recurse.out
+FILES+= d_recurse_symlink.err
+FILES+= d_recurse_symlink.out
+FILES+= d_whole_line.out
+FILES+= d_word_regexps.out
+FILES+= d_zgrep.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/gzip/Makefile b/usr.bin/gzip/Makefile
index 7372435..a3722e7 100644
--- a/usr.bin/gzip/Makefile
+++ b/usr.bin/gzip/Makefile
@@ -28,4 +28,8 @@ LINKS+= ${BINDIR}/gzip ${BINDIR}/gunzip \
${BINDIR}/gzip ${BINDIR}/zcat \
${BINDIR}/zdiff ${BINDIR}/zcmp
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/gzip/tests/Makefile b/usr.bin/gzip/tests/Makefile
new file mode 100644
index 0000000..155d739
--- /dev/null
+++ b/usr.bin/gzip/tests/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/gzip
+.PATH: ${TESTSRC}
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.bin/gzip
+ATF_TESTS_SH= gzip_test
+ATF_TESTS_SH_SRC_gzip_test= t_gzip.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/mkimg/Makefile b/usr.bin/mkimg/Makefile
index 563ca58..28aac7d 100644
--- a/usr.bin/mkimg/Makefile
+++ b/usr.bin/mkimg/Makefile
@@ -6,7 +6,9 @@ PROG= mkimg
SRCS= format.c image.c mkimg.c scheme.c
MAN= mkimg.1
-MKIMG_VERSION=20141001
+MKIMG_VERSION=20141003
+mkimg.o: Makefile
+
CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION}
CFLAGS+=-DSPARSE_WRITE
diff --git a/usr.bin/mkimg/ebr.c b/usr.bin/mkimg/ebr.c
index 43601cc..28931ea 100644
--- a/usr.bin/mkimg/ebr.c
+++ b/usr.bin/mkimg/ebr.c
@@ -58,12 +58,14 @@ ebr_metadata(u_int where, lba_t blk)
}
static void
-ebr_chs(u_char *cyl, u_char *hd, u_char *sec, uint32_t lba __unused)
+ebr_chs(u_char *cylp, u_char *hdp, u_char *secp, lba_t lba)
{
+ u_int cyl, hd, sec;
- *cyl = 0xff; /* XXX */
- *hd = 0xff; /* XXX */
- *sec = 0xff; /* XXX */
+ mkimg_chs(lba, 1023, &cyl, &hd, &sec);
+ *cylp = cyl;
+ *hdp = hd;
+ *secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0);
}
static int
@@ -72,7 +74,7 @@ ebr_write(lba_t imgsz __unused, void *bootcode __unused)
u_char *ebr;
struct dos_partition *dp;
struct part *part, *next;
- lba_t block;
+ lba_t block, size;
int error;
ebr = malloc(secsz);
@@ -84,24 +86,26 @@ ebr_write(lba_t imgsz __unused, void *bootcode __unused)
error = 0;
STAILQ_FOREACH_SAFE(part, &partlist, link, next) {
block = part->block - nsecs;
+ size = round_track(part->size);
dp = (void *)(ebr + DOSPARTOFF);
ebr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect, nsecs);
dp->dp_typ = ALIAS_TYPE2INT(part->type);
ebr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect,
- part->block + part->size - 1);
+ part->block + size - 1);
le32enc(&dp->dp_start, nsecs);
- le32enc(&dp->dp_size, part->size);
+ le32enc(&dp->dp_size, size);
/* Add link entry */
if (next != NULL) {
+ size = round_track(next->size);
dp++;
ebr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
next->block - nsecs);
dp->dp_typ = DOSPTYP_EXT;
ebr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect,
- next->block + next->size - 1);
+ next->block + size - 1);
le32enc(&dp->dp_start, next->block - nsecs);
- le32enc(&dp->dp_size, next->size + nsecs);
+ le32enc(&dp->dp_size, size + nsecs);
}
error = image_write(block, ebr, 1);
diff --git a/usr.bin/mkimg/mbr.c b/usr.bin/mkimg/mbr.c
index e9c2aef..c1b7822 100644
--- a/usr.bin/mkimg/mbr.c
+++ b/usr.bin/mkimg/mbr.c
@@ -59,12 +59,14 @@ mbr_metadata(u_int where, lba_t blk)
}
static void
-mbr_chs(u_char *cyl, u_char *hd, u_char *sec, uint32_t lba __unused)
+mbr_chs(u_char *cylp, u_char *hdp, u_char *secp, lba_t lba)
{
+ u_int cyl, hd, sec;
- *cyl = 0xff; /* XXX */
- *hd = 0xff; /* XXX */
- *sec = 0xff; /* XXX */
+ mkimg_chs(lba, 1023, &cyl, &hd, &sec);
+ *cylp = cyl;
+ *hdp = hd;
+ *secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0);
}
static int
@@ -73,6 +75,7 @@ mbr_write(lba_t imgsz __unused, void *bootcode)
u_char *mbr;
struct dos_partition *dpbase, *dp;
struct part *part;
+ lba_t size;
int error;
mbr = malloc(secsz);
@@ -86,15 +89,16 @@ mbr_write(lba_t imgsz __unused, void *bootcode)
le16enc(mbr + DOSMAGICOFFSET, DOSMAGIC);
dpbase = (void *)(mbr + DOSPARTOFF);
STAILQ_FOREACH(part, &partlist, link) {
+ size = round_track(part->size);
dp = dpbase + part->index;
dp->dp_flag = (part->index == 0 && bootcode != NULL) ? 0x80 : 0;
mbr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
part->block);
dp->dp_typ = ALIAS_TYPE2INT(part->type);
mbr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect,
- part->block + part->size - 1);
+ part->block + size - 1);
le32enc(&dp->dp_start, part->block);
- le32enc(&dp->dp_size, part->size);
+ le32enc(&dp->dp_size, size);
}
error = image_write(0, mbr, 1);
free(mbr);
diff --git a/usr.bin/mkimg/mkimg.c b/usr.bin/mkimg/mkimg.c
index d054423..b55ee7e 100644
--- a/usr.bin/mkimg/mkimg.c
+++ b/usr.bin/mkimg/mkimg.c
@@ -340,6 +340,27 @@ sparse_write(int fd, const void *ptr, size_t sz)
#endif /* SPARSE_WRITE */
void
+mkimg_chs(lba_t lba, u_int maxcyl, u_int *cylp, u_int *hdp, u_int *secp)
+{
+ u_int hd, sec;
+
+ *cylp = *hdp = *secp = ~0U;
+ if (nsecs == 1 || nheads == 1)
+ return;
+
+ sec = lba % nsecs + 1;
+ lba /= nsecs;
+ hd = lba % nheads;
+ lba /= nheads;
+ if (lba > maxcyl)
+ return;
+
+ *cylp = lba;
+ *hdp = hd;
+ *secp = sec;
+}
+
+void
mkimg_uuid(struct uuid *uuid)
{
static uint8_t gen[sizeof(struct uuid)];
diff --git a/usr.bin/mkimg/mkimg.h b/usr.bin/mkimg/mkimg.h
index 7a78034..281beeb 100644
--- a/usr.bin/mkimg/mkimg.h
+++ b/usr.bin/mkimg/mkimg.h
@@ -87,6 +87,8 @@ round_track(lba_t n)
ssize_t sparse_write(int, const void *, size_t);
#endif
+void mkimg_chs(lba_t, u_int, u_int *, u_int *, u_int *);
+
struct uuid;
void mkimg_uuid(struct uuid *);
diff --git a/usr.bin/mkimg/pc98.c b/usr.bin/mkimg/pc98.c
index 56acb1e..2db0394 100644
--- a/usr.bin/mkimg/pc98.c
+++ b/usr.bin/mkimg/pc98.c
@@ -68,12 +68,14 @@ pc98_metadata(u_int where, lba_t blk)
}
static void
-pc98_chs(u_short *cyl, u_char *hd, u_char *sec, uint32_t lba __unused)
+pc98_chs(u_short *cylp, u_char *hdp, u_char *secp, lba_t lba)
{
+ u_int cyl, hd, sec;
- *cyl = 0xffff; /* XXX */
- *hd = 0xff; /* XXX */
- *sec = 0xff; /* XXX */
+ mkimg_chs(lba, 0xffff, &cyl, &hd, &sec);
+ le16enc(cylp, cyl);
+ *hdp = hd;
+ *secp = sec;
}
static int
@@ -82,6 +84,7 @@ pc98_write(lba_t imgsz __unused, void *bootcode)
struct part *part;
struct pc98_partition *dpbase, *dp;
u_char *buf;
+ lba_t size;
int error, ptyp;
buf = malloc(PC98_BOOTCODESZ);
@@ -95,6 +98,7 @@ pc98_write(lba_t imgsz __unused, void *bootcode)
le16enc(buf + PC98_MAGICOFS, PC98_MAGIC);
dpbase = (void *)(buf + secsz);
STAILQ_FOREACH(part, &partlist, link) {
+ size = round_track(part->size);
dp = dpbase + part->index;
ptyp = ALIAS_TYPE2INT(part->type);
dp->dp_mid = ptyp;
@@ -102,7 +106,7 @@ pc98_write(lba_t imgsz __unused, void *bootcode)
pc98_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
part->block);
pc98_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
- part->block + part->size - 1);
+ part->block + size - 1);
if (part->label != NULL)
memcpy(dp->dp_name, part->label, strlen(part->label));
}
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu
index ce9a989..c5c9257 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu
@@ -1,128 +1,128 @@
# $FreeBSD$
begin 644 img-63x255-4096-ebr.qcow.gz
-M'XL(",4S(E0``VEM9RTV,W@R-34M-#`Y-BUE8G(N<6-O=RYO=70`K9W);AS9
-M$47W^HK2+%%3142.&BC"@`UX9R]L;SO'=7V`X&\W);Z!C+Q7H7:WFFA04.=%
-MU>/A4=M]\'0^W_TXG5HY-=VI&4_[?+K]>?J0T[V?//PX??OGW_[^_OZ/;X_N
-MQN3\DZ?<S_NMS#W8^F^=T^]/+:?S^`MSMQ^"YNZ].OL=K^[>FSW.73VZ>[/X
-M.66#]F#PE.;.Z?4).;WFUU[?C7N[<G=Z?][;5?)VVU\;_(=[??J[8/FEU_<[
-MO[X='/RMO+X&/M6SN>'!W.7P=EOXU,CFII_"K.<./C6SN268Z^%3*YO;@KD!
-M/K7C.?G)U_9N;H1/"9M3.'<J<Q-\RMA<\V#NG.9NRMP,GR+?%^*XR]\7E;L%
-M/D6XDY"[%3Y%N).0NPT^1;B3D+L=/D6XDX@[P4\1[C3B3I"BE'&G$7>"C*R,
-M.XVX$^0[9=QIQ)T@WRGC3B/N!/E.&7<:<2?(=\JXTX@[0;Y3QIV&W"'?*>/.
-M0NZ0[XQQ9R%WR'?&N+.0.^0[8]Q9R!WRG3'N+.0.^<X8=Q9RAWQGC#L+N4.^
-M,\:=1=PI?HIPUT3<*?)=P[AK(NX4^:YAW#41=XI\US#NFH@[1;YK&'=-Q)TB
-MWS6,NR;B3I'O&L9=$W&GR'<-XZX)N4.^:QAW;<@=\EW+N&M#[I#O6L9=&W*'
-M?-<R[MJ0.^2[EG'7AMPAW[6,NS;D#OFN9=RU(7?(=RWCKHVX,_P4X:Z+N#/D
-MNXYQUT7<&?)=Q[CK(NX,^:YCW'41=X9\US'NNH@[0[[K&'==Q)TAWW6,NR[B
-MSI#O.L9=%W*'?-<Q[OJ0.^2[GG'7A]PAW_6,NS[D#OFN9]SU(7?(=SWCK@^Y
-M0[[K&7=]R!WR7<^XZT/ND.]ZQET?<=?@IPAW0\1=@WPW,.Z&B+L&^6Y@W`T1
-M=PWRW<"X&R+N&N2[@7$W1-PUR'<#XVZ(N&N0[P;&W1!QUR#?#8R[(>0.^6Y@
-MW.7_>Y[/(=^-C+LQY`[Y;F3<C2%WR'<CXVX,N4.^&QEW8\@=\MW(N!M#[I#O
-M1L;=&'*'?#<R[L:(NQ8_1;B;(NY:Y+N)<3=%W+7(=Q/C;HJX:Y'O)L;=%''7
-M(M]-C+LIXJY%OIL8=U/$78M\-S'NIHB[%OEN8MQ-(7?(=Q/C+O]G4CZ'?#<S
-M[N:0.^2[F7$WA]PAW\V,NSGD#OEN9MS-(7?(=S/C;@ZY0[Z;&7=SR!WRW<RX
-MFR/N.OP4X6Z)N.N0[Q;&W1)QUR'?+8R[)>*N0[Y;&'=+Q%V'?+<P[I:(NP[Y
-M;F'<+1%W'?+=PKA;(NXZY+N%<;>$W"'?+8R[->0.^6YEW*TA=\AW*^-N#;E#
-MOEL9=VO('?+=RKA;0^Z0[U;&W1IRAWRW,N[6D#ODNY5QMT;<]?@IPAT)A.[-
-M(=]MC+LMXJY'OML8=UO$78]\MS'NMHB['OEN8]QM$7<]\MW&N-LB[GKDNXUQ
-MMT7<]<AW&^-N"[E#OML8=WO('?+=SKC;0^Z0[W;&W1YRAWRW,^[VD#ODNYUQ
-MMX?<(=_MC+L]Y`[Y;F?<[2%WR'<[XVZ/N!OP4Y@[R9_P.>`[.1/NY!QQ-P#?
-MR9EP)^>(NP'X3E@?*+Z_.W`W`-\)Z^\D[.\&X#MA_9V$_=T`?">LOY.POQN`
-M[X3U=Q+V=P/PG;#^3L+^;@"^$];?2=C?#<!WPOH["?N[`?A.6'\G87\W`-\)
-MZ^\D[.\&X#MA_9V$_=T`?">LOY.POQN`[X3U=Q+V=R-^BG`7]G<C\AWK[R3L
-M[T;D.];?2=C?C<AWK+^3L+\;D>]8?R=A?S<BW['^3L+^;D2^8_V=A/W=B'S'
-M^CL)^[L1^8[U=Q+V=R/R'>OO).SO1N0[UM])V-^-R'>LOY.POQN1[UA_)V%_
-M-R+?L?Y.POYN1+YC_9V$_=V(?,?Z.PG[NPD_1;@+^[L)^8[U=Q+V=Q/R'>OO
-M).SO)N0[UM])V-]-R'>LOY.POYN0[UA_)V%_-R'?L?Y.POYN0KYC_9V$_=V$
-M?,?Z.PG[NPGYCO5W$O9W$_(=Z^\D[.\FY#O6WTG8WTW(=ZR_D["_FY#O6'\G
-M87\W(=^Q_D["_FY"OF/]G83]W8R?(MR%_=V,?,?Z.PG[NQGYCO5W$O9W,_(=
-MZ^\D[.]FY#O6WTG8W\W(=ZR_D["_FY'O6'\G87\W(]^Q_D["_FY&OF/]G83]
-MW8Q\Q_H["?N[&?F.]7<2]G<S\AWK[R3L[V;D.];?2=C?S<AWK+^3L+^;D>]8
-M?R=A?S<CW['^3L+^;L%/$>["_FY!OF/]G83]W8)\Q_H["?N[!?F.]7<2]G<+
-M\AWK[R3L[Q;D.];?2=C?+<AWK+^3L+];D.]8?R=A?[<@W['^3L+^;D&^8_V=
-MA/W=@GS'^CL)^[L%^8[U=Q+V=POR'>OO).SO%N0[UM])V-\MR'>LOY.POUN0
-M[UA_)V%_M^*G"'=A?[<BW['^3L+^;D6^8_V=A/W=BGS'^CL)^[L5^8[U=Q+V
-M=ROR'>OO).SO5N0[UM])V-^MR'>LOY.POUN1[UA_)V%_MR+?L?Y.POYN1;YC
-M_9V$_=V*?,?Z.PG[NQ7YCO5W$O9W*_(=Z^\D[.]6Y#O6WTG8WZW(=ZR_D["_
-MV_!3A+NPO]N0[UA_)V%_MR'?L?Y.POYN0[YC_9V$_=V&?,?Z.PG[NPWYCO5W
-M$O9W&_(=Z^\D[.\VY#O6WTG8WVW(=ZR_D["_VY#O6'\G87^W(=^Q_D["_FY#
-MOF/]G83]W89\Q_H["?N[#?F.]7<2]G<;\AWK[R3L[S;D.];?2=C?[?@IPEW8
-MW^W(=ZR_D["_VY'O6'\G87^W(]^Q_D["_FY'OF/]G83]W8Y\Q_H["?N['?F.
-M]7<2]G<[\AWK[R3L[W;D.];?2=C?[<AWK+^3L+_;D>]8?R=A?[<CW['^3L+^
-M;D>^8_V=A/W=CGS'^CL)^[L=^8[U=Q+V=SOR'>OO).KO[(R?PMQI_L3-G>H<
-M\-WM4Y@[=?U=ON_O="ISP'?*^CMU_=TI<7>Z*7/`=\KZ.W7]W2EQ=_JMS`'?
-M*>OOU/5WI\OA[(#OE/5WZOJ[<G9U#OA.67^GKK\#<\!WROH[=?T=F`.^4];?
-MJ>OO\MSC.@=\IZR_4]??/<YSE3O@.V7]G;K^[G'B[G'E#OA.67^GKK][G+A[
-M7+D#OE/6WZGK[QY?#F<'?*>LOU/7WY6SJW/`=\KZ.W7]'9@#OE/6WZGK[XYS
-MZ/X[9?V=NOXNSSVI<\AWK+]3U]\]R7.%.W3_G;+^3EU_]R1Q]Z1PA^Z_4];?
-MJ>OOGB3NGA3NT/UWROH[=?W=D\OA[)#O6'^GKK\K9U?GD.]8?Z>NOP-SR'>L
-MOU/7WX$YY#O6WZGK[_+<TSJ'?,?Z.W7]W=,\5[E#OF/]G;K^[FGB[FGE#OF.
-M]7?J^KNGB;NGE3OD.];?J>OOGEX.9X=\Q_H[=?U=.;LZAWS'^CMU_1V80[YC
-M_9VZ_NXXA^Z_4];?J>OO\MRS.H=\Q_H[=?W=LSQ7N$/WWRGK[]3U=\\2=\\*
-M=^C^.V7]G;K^[EGB[EGA#MU_IZR_4]??/;L<S@[YCO5WZOJ[<G9U#OF.]7?J
-M^CLPAWS'^CMU_1V80[YC_9VZ_B[//:]SR'>LOU/7WSW/<Y4[Y#O6WZGK[YXG
-M[IY7[I#O6'^GKK][GKA[7KE#OF/]G;K^[OGE<';(=ZR_4]??E;.K<\AWK+]3
-MU]^!.>0[UM^IZ^^.<^C^.V7]G;K^+L^]J'/(=ZR_4]??O<ASA3MT_YVR_DY=
-M?_<B<?>B<(?NOU/6WZGK[UXD[EX4[M#]=\KZ.W7]W8O+X>R0[UA_IZZ_*V=7
-MYY#O6'^GKK\#<\AWK+]3U]^!.>0[UM^IZ^_RW,LZAWS'^CMU_=W+/%>Y0[YC
-M_9VZ_NYEXNYEY0[YCO5WZOJ[EXF[EY4[Y#O6WZGK[UY>#F>'?,?Z.W7]73F[
-M.H=\Q_H[=?T=F$.^8_V=NO[N.(?NOU/6WZGK[_+<JSJ'?,?Z.W7]W:L\5[A#
-M]]\IZ^_4]7>O$G>O"G?H_CME_9VZ_NY5XNY5X0[=?Z>LOU/7W[VZ',X.^8[U
-M=^KZNW)V=0[YCO5WZOH[,(=\Q_H[=?T=F$.^8_V=NOXNS[VN<\AWK+]3U]^]
-MSG.5.^0[UM^IZ^]>)^Y>5^Z0[UA_IZZ_>YVX>UVY0[YC_9VZ_N[UY7!VR'>L
-MOU/7WY6SJW/(=ZR_4]??@3GD.];?J>OOCG/H_CME_9VZ_B[/7=4YY#O6WZGK
-M[Z[R7.$.W7^GK+]3U]]=)>ZN"G?H_CME_9VZ_NXJ<7=5N$/WWRGK[]3U=U>7
-MP]DAW['^3EU_5\ZNSB'?L?Y.77\'YI#O6'^GKK\#<\AWK+]3U]_EN3=U#OF.
-M]7?J^KLW>:YRAWS'^CMU_=V;Q-V;RAWR'>OOU/5W;Q)W;RIWR'>LOU/7W[VY
-M',X.^8[U=^KZNW)V=0[YCO5WZOH[,(=\Q_H[=?W=<0[=?Z>LOU/7W^6YMW4.
-M^8[U=^KZN[=YKG"'[K]3UM^IZ^_>)N[>%N[0_7?*^CMU_=W;Q-W;PAVZ_TY9
-M?Z>NOWM[.9P=\AWK[]3U=^7LZASR'>OOU/5W8`[YCO5WZOH[,(=\Q_H[=?U=
-MGGM7YY#O6'^GKK][E^<J=\AWK+]3U]^]2]R]J]PAW['^3EU_]RYQ]ZYRAWS'
-M^CMU_=V[R^'LD.]8?Z>NORMG5^>0[UA_IZZ_`W/(=ZR_4]??'>?0_7?*^CMU
-M_5V>>U_GD.]8?Z=1?V?H_CME_9U&_9VA^^^4]7<:]7>&[K]3UM]IU-\9NO].
-M67^G47]GZ/X[9?V=1OV=H?OOE/5W&O5WANZ_4];?*>GO/M0YY#O6WZGK[S[D
-MN<H=\AWK[]3U=Q\2=Q\J=\AWK+]3U]]]2-Q]J-PAW['^3EU_]^%R.#OD.];?
-MJ>OORMG5.>0[UM^IZ^_`'/(=Z^_4]7?'.73_G;+^SO(G;NY<YX#OC/5WM[_P
-M@+OLIW/A#MU_9ZR_,]??G=/>N7"'[K\SUM^9Z^_.B;MSX0[=?V>LOS/7WYTO
-MA[,#OC/6WYGK[\K9U3G@.V/]G;G^#LP!WQGK[\SU=V`.^,Y8?V>NO\MS4N>`
-M[XSU=^;Z.\ESE3O@.V/]G;G^3M++D\H=\)VQ_LY<?R>).ZG<`=\9Z^_,]7=R
-M.9P=\)VQ_LY<?U?.KLX!WQGK[\SU=V`.^,Y8?V>NOSO.H?OOC/5WYOJ[/*=U
-M#OF.]7?F^CO-<X4[=/^=L?[.7'^GB3LMW*'[[XSU=^;Z.TW<:>$.W7]GK+\S
-MU]_IY7!VR'>LOS/7WY6SJW/(=ZR_,]??@3GD.];?F>OOP!SR'>OOS/5W><[J
-M'/(=Z^_,]7>6YRIWR'>LOS/7WUGBSBIWR'>LOS/7WUGBSBIWR'>LOS/7W]GE
-M<';(=ZR_,]??E;.K<\AWK+\SU]^!.>0[UM^9Z^^.<^C^.V/]G;G^+L\U=0[Y
-MCO5WYOJ[)L\5[M#]=\;Z.W/]79.X:PIWZ/X[8_V=N?ZN2=PUA3MT_YVQ_LY<
-M?]=<#F>'?,?Z.W/]73F[.H=\Q_H[<_T=F$.^8_V=N?X.S"'?L?[.7'^7Y]HZ
-MAWS'^CMS_5V;YRIWR'>LOS/7W[6)N[9RAWS'^CMS_5V;N&LK=\AWK+\SU]^U
-ME\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0[UA_9ZZ_.\ZA^^^,]7?F^KL\U]4Y
-MY#O6WYGK[[H\5[A#]]\9Z^_,]7==XJXKW*'[[XSU=^;ZNRYQUQ7NT/UWQOH[
-M<_U==SF<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.^8[U=^;Z.S"'?,?Z.W/]79[K
-MZQSR'>OOS/5W?9ZKW"'?L?[.7'_7)^[ZRAWR'>OOS/5W?>*NK]PAW['^SEQ_
-MUU\.9X=\Q_H[<_U=.;LZAWS'^CMS_1V80[YC_9VY_NXXA^Z_,];?F>OO\MQ0
-MYY#O6']GKK\;\ESA#MU_9ZR_,]??#8F[H7"'[K\SUM^9Z^^&Q-U0N$/WWQGK
-M[\SU=\/E<';(=ZR_,]??E;.K<\AWK+\SU]^!.>0[UM^9Z^_`'/(=Z^_,]7=Y
-M;JQSR'>LOS/7WXUYKG*'?,?Z.W/]W9BX&RMWR'>LOS/7WXV)N[%RAWS'^CMS
-M_=UX.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOJ[XQRZ_\Y8?V>NO\MS
-M'^L<\AWK[\SU=Q_S7.$.W7]GK+\SU]]]3-Q]+-RA^^^,]7?F^KN/B;N/A3MT
-M_YVQ_LY<?_?Q<C@[Y#O6WYGK[\K9U3GD.];?F>OOP!SR'>OOS/5W8`[YCO5W
-MYOJ[//>ISB'?L?[.7'_W*<]5[I#O6']GKK_[E+C[5+E#OF/]G;G^[E/B[E/E
-M#OF.]7?F^KM/E\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0[UA_9ZZ_.\ZA^^^,
-M]7?F^KL\][G.(=^Q_LY<?_<YSQ7NT/UWQOH[<_W=Y\3=Y\(=NO_.6']GKK_[
-MG+C[7+A#]]\9Z^_,]7>?+X>S0[YC_9VY_JZ<79U#OF/]G;G^#LPAW['^SEQ_
-M!^:0[UA_9ZZ_RW-?ZASR'>OOS/5W7_)<Y0[YCO5WYOJ[+XF[+Y4[Y#O6WYGK
-M[[XD[KY4[I#O6']GKK_[<CF<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.^8[U=^;Z
-MN^,<NO_.6']GKK_+<]=U#OF.]7?F^KOK/%>X0_??&>OOS/5WUXF[Z\(=NO_.
-M6']GKK^[3MQ=%^[0_7?&^CMS_=WUY7!VR'>LOS/7WY6SJW/(=ZR_,]??@3GD
-M.];?F>OOP!SR'>OOS/5W>>YKG4.^8_V=N?[N:YZKW"'?L?[.7'_W-7'WM7*'
-M?,?Z.W/]W=?$W=?*'?(=Z^_,]7=?+X>S0[YC_9VY_JZ<79U#OF/]G;G^#LPA
-MW['^SEQ_=YAKSO@IS%V3/W%S-W4.^*YA_5WC^KN;/'<J<\!WMT]A[AK7W]TD
-M[FYNRASP7</ZN\;U=S>)NYO?RASP7</ZN\;U=S>7P]FA/V^[G#C]A6_OW8]O
-MCZY^#+;H&J)@<-_AX-W<]V^SVW_@]F-JTR>W'W<R2L\O4G]3?/CZ?K!R?7\.
-M_3'/?^CMHC^9^2>#;7N:IL/@O_+K0S<'_9'7U_WXGU*-GLX3^#O_A6]_>?_P
-MKSS8__C>;?M3TY[:[C3HK[["__SUW^#KVZ/OW?_O#=_-@>_=AW/Y!9??S@YS
-M7^_-V1U]=47N/76?N_N?WYN[?G_O]]L>?>_6N>^^VM`OT#?[)W_O]H?[(>]_
-MG7]<H6RG<_[/*>Y>TO+U/=77AWK\!V_W)Z_O='R[/_Y]H'_XS\N].0W>[NGA
-MW`]1W?MZ/O@2!J=W?7QUZ,^C_R-?C,,MA[_XG?M]Y.%W[MV<_KDB&'Z8Y?OO
-C8A/X._^%;_]X__"ON\$F#?YI)]C<TG<^/_H?-'D14%"H````
+M'XL("%[N+50``VEM9RTV,W@R-34M-#`Y-BUE8G(N<6-O=RYO=70`K9W9CE39
+M$47?^8IDAF+*B+@C0U7)DBWYS7ZP_=IW?,X/0/YV`W6&JKA[$[2[:=0"T7<K
+M\]3*1=N]=#B?[[Z=3JV<FN[4C*=]/GW[>?HNIWL_>?C]]/6??_O[^_O?OCZZ
+M&Y/S3YYR/^^W,O=@Z[]U3K\_M9S.XR_,??LN:.[>J[/?\>KNO=GCW-6CNS>+
+MGU,V:`\&3VGNG%Z?D--K?NWUW;JW*W>G]^>]725OM_VUP7^XUZ>_"Y9?>GV_
+M\^O;P<'?RNMKX%,]FQL>S%T.;[>%3XUL;OHIS'KNX%,SFUN"N1X^M;*Y+9@;
+MX%,[GI.??&WOYD;XE+`YA7.G,C?!IXS--0_FSFGNMLS-\"GRN1#'7?Y<5.X6
+M^!3A3D+N5O@4X4Y"[C;X%.%.0NYV^!3A3B+N!#]%N-.(.T&*4L:=1MP),K(R
+M[C3B3I#OE'&G$7>"?*>,.XVX$^0[9=QIQ)T@WRGC3B/N!/E.&7<:<H=\IXP[
+M"[E#OC/&G87<(=\9X\Y"[I#OC'%G(7?(=\:XLY`[Y#MCW%G('?*=,>XLY`[Y
+MSAAW%G&G^"G"71-QI\AW#>.NB;A3Y+N&<==$W"GR7<.X:R+N%/FN8=PU$7>*
+M?-<P[IJ(.T6^:QAW3<2=(M\UC+LFY`[YKF'<M2%WR'<MXZX-N4.^:QEW;<@=
+M\EW+N&M#[I#O6L9=&W*'?-<R[MJ0.^2[EG'7AMPAW[6,NS;BSO!3A+LNXLZ0
+M[SK&71=Q9\AW'>.NB[@SY+N.<==%W!GR7<>XZR+N#/FN8]QU$7>&?-<Q[KJ(
+M.T.^ZQAW7<@=\EW'N.M#[I#O>L9='W*'?-<S[OJ0.^2[GG'7A]PAW_6,NS[D
+M#OFN9]SU(7?(=SWCK@^Y0[[K&7=]Q%V#GR+<#1%W#?+=P+@;(NX:Y+N!<3=$
+MW#7(=P/C;HBX:Y#O!L;=$''7(-\-C+LAXJY!OAL8=T/$78-\-S#NAI`[Y+N!
+M<9?_[WD^AWPW,N[&D#ODNY%Q-X;<(=^-C+LQY`[Y;F3<C2%WR'<CXVX,N4.^
+M&QEW8\@=\MW(N!LC[EK\%.%NBKAKD>\FQMT4<=<BWTV,NRGBKD6^FQAW4\1=
+MBWPW,>ZFB+L6^6YBW$T1=RWRW<2XFR+N6N2[B7$WA=PAWTV,N_R?2?D<\MW,
+MN)M#[I#O9L;=''*'?#<S[N:0.^2[F7$WA]PAW\V,NSGD#OEN9MS-(7?(=S/C
+M;HZXZ_!3A+LEXJY#OEL8=TO$78=\MS#NEHB[#OEN8=PM$7<=\MW"N%LB[CKD
+MNX5QMT3<=<AW"^-NB;CKD.\6QMT2<H=\MS#NUI`[Y+N5<;>&W"'?K8R[->0.
+M^6YEW*TA=\AW*^-N#;E#OEL9=VO('?+=RKA;0^Z0[U;&W1IQU^.G"'<D$+HW
+MAWRW,>ZVB+L>^6YCW&T1=SWRW<:XVR+N>N2[C7&W1=SUR'<;XVZ+N.N1[S;&
+MW19QUR/?;8R[+>0.^6YCW.TA=\AW.^-N#[E#OML9=WO('?+=SKC;0^Z0[W;&
+MW1YRAWRW,^[VD#ODNYUQMX?<(=_MC+L]XF[`3V'N)/^`SP'?R9EP)^>(NP'X
+M3LZ$.SE'W`W`=\+Z0/']W8&[`?A.6'\G87\W`-\)Z^\D[.\&X#MA_9V$_=T`
+M?">LOY.POQN`[X3U=Q+V=P/PG;#^3L+^;@"^$];?2=C?#<!WPOH["?N[`?A.
+M6'\G87\W`-\)Z^\D[.\&X#MA_9V$_=T`?">LOY.POQOQ4X2[L+\;D>]8?R=A
+M?S<BW['^3L+^;D2^8_V=A/W=B'S'^CL)^[L1^8[U=Q+V=R/R'>OO).SO1N0[
+MUM])V-^-R'>LOY.POQN1[UA_)V%_-R+?L?Y.POYN1+YC_9V$_=V(?,?Z.PG[
+MNQ'YCO5W$O9W(_(=Z^\D[.]&Y#O6WTG8WTWX*<)=V-]-R'>LOY.POYN0[UA_
+M)V%_-R'?L?Y.POYN0KYC_9V$_=V$?,?Z.PG[NPGYCO5W$O9W$_(=Z^\D[.\F
+MY#O6WTG8WTW(=ZR_D["_FY#O6'\G87\W(=^Q_D["_FY"OF/]G83]W81\Q_H[
+M"?N["?F.]7<2]G<3\AWK[R3L[V;\%.$N[.]FY#O6WTG8W\W(=ZR_D["_FY'O
+M6'\G87\W(]^Q_D["_FY&OF/]G83]W8Q\Q_H["?N[&?F.]7<2]G<S\AWK[R3L
+M[V;D.];?2=C?S<AWK+^3L+^;D>]8?R=A?S<CW['^3L+^;D:^8_V=A/W=C'S'
+M^CL)^[L9^8[U=Q+V=PM^BG`7]G<+\AWK[R3L[Q;D.];?2=C?+<AWK+^3L+];
+MD.]8?R=A?[<@W['^3L+^;D&^8_V=A/W=@GS'^CL)^[L%^8[U=Q+V=POR'>OO
+M).SO%N0[UM])V-\MR'>LOY.POUN0[UA_)V%_MR#?L?Y.POYN0;YC_9V$_=V"
+M?,?Z.PG[NQ4_1;@+^[L5^8[U=Q+V=ROR'>OO).SO5N0[UM])V-^MR'>LOY.P
+MOUN1[UA_)V%_MR+?L?Y.POYN1;YC_9V$_=V*?,?Z.PG[NQ7YCO5W$O9W*_(=
+MZ^\D[.]6Y#O6WTG8WZW(=ZR_D["_6Y'O6'\G87^W(M^Q_D["_FY%OF/]G83]
+MW8:?(MR%_=V&?,?Z.PG[NPWYCO5W$O9W&_(=Z^\D[.\VY#O6WTG8WVW(=ZR_
+MD["_VY#O6'\G87^W(=^Q_D["_FY#OF/]G83]W89\Q_H["?N[#?F.]7<2]G<;
+M\AWK[R3L[S;D.];?2=C?;<AWK+^3L+_;D.]8?R=A?[<AW['^3L+^;L=/$>["
+M_FY'OF/]G83]W8Y\Q_H["?N['?F.]7<2]G<[\AWK[R3L[W;D.];?2=C?[<AW
+MK+^3L+_;D>]8?R=A?[<CW['^3L+^;D>^8_V=A/W=CGS'^CL)^[L=^8[U=Q+V
+M=SOR'>OO).SO=N0[UM])V-_MR'>LOY.PO]N1[UA_)U%_9V?\%.9.\P_<W*G.
+M`=]]>PISIZZ_R_?]G4YE#OA.67^GKK\[)>Y.MV4.^$Y9?Z>NOSLE[DZ_E3G@
+M.V7]G;K^[G0YG!WPG;+^3EU_5\ZNS@'?*>OOU/5W8`[X3EE_IZZ_`W/`=\KZ
+M.W7]79Y[7.>`[Y3U=^KZN\=YKG('?*>LOU/7WSU.W#VNW`'?*>OOU/5WCQ-W
+MCRMWP'?*^CMU_=WCR^'L@.^4]7?J^KMR=G4.^$Y9?Z>NOP-SP'?*^CMU_=UQ
+M#MU_IZR_4]??Y;DG=0[YCO5WZOJ[)WFN<(?NOU/6WZGK[YXD[IX4[M#]=\KZ
+M.W7]W9/$W9/"';K_3EE_IZZ_>W(YG!WR'>OOU/5WY>SJ'/(=Z^_4]7=@#OF.
+M]7?J^CLPAWS'^CMU_5V>>UKGD.]8?Z>NOWN:YRIWR'>LOU/7WSU-W#VMW"'?
+ML?Y.77_W-''WM'*'?,?Z.W7]W=/+X>R0[UA_IZZ_*V=7YY#O6'^GKK\#<\AW
+MK+]3U]\=Y]#]=\KZ.W7]79Y[5N>0[UA_IZZ_>Y;G"G?H_CME_9VZ_NY9XNY9
+MX0[=?Z>LOU/7WSU+W#TKW*'[[Y3U=^KZNV>7P]DAW['^3EU_5\ZNSB'?L?Y.
+M77\'YI#O6'^GKK\#<\AWK+]3U]_EN>=U#OF.]7?J^KOG>:YRAWS'^CMU_=WS
+MQ-WSRAWR'>OOU/5WSQ-WSRMWR'>LOU/7WSV_',X.^8[U=^KZNW)V=0[YCO5W
+MZOH[,(=\Q_H[=?W=<0[=?Z>LOU/7W^6Y%W4.^8[U=^KZNQ=YKG"'[K]3UM^I
+MZ^]>).Y>%.[0_7?*^CMU_=V+Q-V+PAVZ_TY9?Z>NOWMQ.9P=\AWK[]3U=^7L
+MZASR'>OOU/5W8`[YCO5WZOH[,(=\Q_H[=?U=GGM9YY#O6'^GKK][F><J=\AW
+MK+]3U]^]3-R]K-PAW['^3EU_]S)Q][)RAWS'^CMU_=W+R^'LD.]8?Z>NORMG
+M5^>0[UA_IZZ_`W/(=ZR_4]??'>?0_7?*^CMU_5V>>U7GD.]8?Z>NOWN5YPIW
+MZ/X[9?V=NO[N5>+N5>$.W7^GK+]3U]^]2MR]*MRA^^^4]7?J^KM7E\/9(=^Q
+M_DY=?U?.KLXAW['^3EU_!^:0[UA_IZZ_`W/(=ZR_4]??Y;G7=0[YCO5WZOJ[
+MUWFN<H=\Q_H[=?W=Z\3=Z\H=\AWK[]3U=Z\3=Z\K=\AWK+]3U]^]OAS.#OF.
+M]7?J^KMR=G4.^8[U=^KZ.S"'?,?Z.W7]W7$.W7^GK+]3U]_EN:LZAWS'^CMU
+M_=U5GBO<H?OOE/5WZOJ[J\3=5>$.W7^GK+]3U]]=)>ZN"G?H_CME_9VZ_N[J
+M<C@[Y#O6WZGK[\K9U3GD.];?J>OOP!SR'>OOU/5W8`[YCO5WZOJ[//>FSB'?
+ML?Y.77_W)L]5[I#O6'^GKK][D[A[4[E#OF/]G;K^[DWB[DWE#OF.]7?J^KLW
+ME\/9(=^Q_DY=?U?.KLXAW['^3EU_!^:0[UA_IZZ_.\ZA^^^4]7?J^KL\][;.
+M(=^Q_DY=?_<VSQ7NT/UWROH[=?W=V\3=V\(=NO].67^GKK][F[A[6[A#]]\I
+MZ^_4]7=O+X>S0[YC_9VZ_JZ<79U#OF/]G;K^#LPAW['^3EU_!^:0[UA_IZZ_
+MRW/OZASR'>OOU/5W[_)<Y0[YCO5WZOJ[=XF[=Y4[Y#O6WZGK[]XE[MY5[I#O
+M6'^GKK][=SF<'?(=Z^_4]7?E[.H<\AWK[]3U=V`.^8[U=^KZN^,<NO].67^G
+MKK_+<^_K'/(=Z^\TZN\,W7^GK+_3J+\S=/^=LOY.H_[.T/UWROH[C?H[0_??
+M*>OO-.KO#-U_IZR_TZB_,W3_G;+^3J/^SM#]=\KZ.R7]W8<ZAWS'^CMU_=V'
+M/%>Y0[YC_9VZ_NY#XNY#Y0[YCO5WZOJ[#XF[#Y4[Y#O6WZGK[SY<#F>'?,?Z
+M.W7]73F[.H=\Q_H[=?T=F$.^8_V=NO[N.(?NOU/6WUG^@9L[USG@.V/]W;=?
+M>,!=]M.Y<(?NOS/6WYGK[\YI[URX0_??&>OOS/5WY\3=N7"'[K\SUM^9Z^_.
+ME\/9`=\9Z^_,]7?E[.H<\)VQ_LY<?P?F@.^,]7?F^CLP!WQGK+\SU]_E.:ES
+MP'?&^CMS_9WDN<H=\)VQ_LY<?R?IY4GE#OC.6']GKK^3Q)U4[H#OC/5WYOH[
+MN1S.#OC.6']GKK\K9U?G@.^,]7?F^CLP!WQGK+\SU]\=Y]#]=\;Z.W/]79[3
+M.H=\Q_H[<_V=YKG"';K_SEA_9ZZ_T\2=%N[0_7?&^CMS_9TF[K1PA^Z_,];?
+MF>OO]'(X.^0[UM^9Z^_*V=4YY#O6WYGK[\`<\AWK[\SU=V`.^8[U=^;ZNSQG
+M=0[YCO5WYOH[RW.5.^0[UM^9Z^\L<6>5.^0[UM^9Z^\L<6>5.^0[UM^9Z^_L
+M<C@[Y#O6WYGK[\K9U3GD.];?F>OOP!SR'>OOS/5WQSET_YVQ_LY<?Y?GFCJ'
+M?,?Z.W/]79/G"G?H_CMC_9VY_JY)W#6%.W3_G;'^SEQ_UR3NFL(=NO_.6']G
+MKK]K+H>S0[YC_9VY_JZ<79U#OF/]G;G^#LPAW['^SEQ_!^:0[UA_9ZZ_RW-M
+MG4.^8_V=N?ZNS7.5.^0[UM^9Z^_:Q%U;N4.^8_V=N?ZN3=RUE3OD.];?F>OO
+MVLOA[)#O6']GKK\K9U?GD.]8?V>NOP-SR'>LOS/7WQWGT/UWQOH[<_U=GNOJ
+M'/(=Z^_,]7==GBO<H?OOC/5WYOJ[+G'7%>[0_7?&^CMS_5V7N.L*=^C^.V/]
+MG;G^KKL<S@[YCO5WYOJ[<G9U#OF.]7?F^CLPAWS'^CMS_1V80[YC_9VY_B[/
+M]74.^8[U=^;ZNS[/5>Z0[UA_9ZZ_ZQ-W?>4.^8[U=^;ZNSYQUU?ND.]8?V>N
+MO^LOA[-#OF/]G;G^KIQ=G4.^8_V=N?X.S"'?L?[.7']WG$/WWQGK[\SU=WEN
+MJ'/(=ZR_,]??#7FN<(?NOS/6WYGK[X;$W5"X0_??&>OOS/5W0^)N*-RA^^^,
+M]7?F^KOA<C@[Y#O6WYGK[\K9U3GD.];?F>OOP!SR'>OOS/5W8`[YCO5WYOJ[
+M/#?6.>0[UM^9Z^_&/%>Y0[YC_9VY_FY,W(V5.^0[UM^9Z^_&Q-U8N4.^8_V=
+MN?YNO!S.#OF.]7?F^KMR=G4.^8[U=^;Z.S"'?,?Z.W/]W7$.W7]GK+\SU]_E
+MN8]U#OF.]7?F^KN/>:YPA^Z_,];?F>OO/B;N/A;NT/UWQOH[<_W=Q\3=Q\(=
+MNO_.6']GKK_[>#F<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.^8[U=^;Z.S"'?,?Z
+M.W/]79[[5.>0[UA_9ZZ_^Y3G*G?(=ZR_,]???4K<?:K<(=^Q_LY<?_<I<?>I
+M<H=\Q_H[<_W=I\OA[)#O6']GKK\K9U?GD.]8?V>NOP-SR'>LOS/7WQWGT/UW
+MQOH[<_U=GOM<YY#O6']GKK_[G.<*=^C^.V/]G;G^[G/B[G/A#MU_9ZR_,]??
+M?4[<?2[<H?OOC/5WYOJ[SY?#V2'?L?[.7']7SJ[.(=^Q_LY<?P?FD.]8?V>N
+MOP-SR'>LOS/7W^6Y+W4.^8[U=^;ZNR]YKG*'?,?Z.W/]W9?$W9?*'?(=Z^_,
+M]7=?$G=?*G?(=ZR_,]???;D<S@[YCO5WYOJ[<G9U#OF.]7?F^CLPAWS'^CMS
+M_=UQ#MU_9ZR_,]??Y;GK.H=\Q_H[<_W==9XKW*'[[XSU=^;ZN^O$W77A#MU_
+M9ZR_,]??72?NK@MWZ/X[8_V=N?[N^G(X.^0[UM^9Z^_*V=4YY#O6WYGK[\`<
+M\AWK[\SU=V`.^8[U=^;ZNSQW4^>0[UA_9ZZ_N\ESE3OD.];?F>OO;A)W-Y4[
+MY#O6WYGK[VX2=S>5.^0[UM^9Z^]N+H>S0[YC_9VY_JZ<79U#OF/]G;G^#LPA
+MW['^SEQ_=YAKSO@IS%V3?^#F;NL<\%W#^KO&]7>W>>Y4YH#OOCV%N6M<?W>;
+MN+N]+7/`=PWK[QK7W]TF[FY_*W/`=PWK[QK7W]U>#F>'_KSM<N+T%[Z^=]^^
+M/KKZ,=BB:XBB08&#=W,_/F8_4KBI39Q\^^F=C-+SB]3?%.^_OIL[5J[OSZ$_
+MYOD/O5WT)S/_9+!M3]-T&/Q7?GWHYJ`_\OJZ'_]3JM'3>0)_Y[_P]2_O'_Z5
+M!_L?G]VV/S7MJ>U.@_[J*_S/7_\-OKX]^NS^?V_X;@Y\=A_.Y1=<?CL[S-W<
+MF_O^V=WO_9-GN??4?>[N__C>W/7[>[_?]NBS6^>^^VI#OT#?[)_\V>T/]T/>
+M_SK_N$+93N?\GU/<O:3EZWNJKP_U^`_>[D]>W^GX=G_\^T#_\)^7>W,:O-W3
+MP[FYF`5\"8/3NSZ^.O3GT?^1+\;AEL-?_.1^'WGXR;V;TS]7!,,/LWS_76P"
+A?^>_\/4?[Q_^=3?8I,$_[02;;_2=SX_^!PM'3SM0J```
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu
index 5e5f371..304b694 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu
@@ -1,22 +1,22 @@
# $FreeBSD$
begin 644 img-63x255-4096-ebr.qcow2.gz
-M'XL("+P[(U0``VEM9RTV,W@R-34M-#`Y-BUE8G(N<6-O=S(N;W5T`*V8R9+3
-M0`Q`[_F*9E@&!@ANJ;VQ)#`P5'&#`W!V%G]%BF_'3LMN6Y;<DY03ERNIMEZI
-MW4_RDB3^8TQJC<N,*TV],\U_VL`,_HPW<_KU_<=Z^#FM/,PF2I0PD!][W(CU
-M+^!`PR5V.F!EW"`[%'#014U!,9Q3LYL;$'!WJ_.I.R]&P2+P&J#'J8MQ57[@
-M\^,1[LK\8.G\4#Y_:1?'![+Y_-#GQZ-R#5=$<2!$E1JNBN)0B-IIN'T4YX2H
-M@X93*G>`2X6H6L'9B"H-+A.BK(:#*"X7HE##N2BN$*(T[VS<NU*(TKRS<>\J
-M(4KSSL:]VPE1FG<V[MU>B-*\LW'O#D*4YATHWIF`.PI1FG?`O'M"N)N`JX4H
-MS3M@WCTEW+,>9Z4HS3M@WCTGW(N`$_H=:-X!\^Z6<"\#3NAWH'D'S+M7A+L+
-M.*'?@>8=,.]>$^Y-P`G]#C3O@'GW=N*=%?H=:-XA\^X=L9*`$_H=:MXA\\X2
-M#@).Z'>H>8?,.R2<"SBAWZ'F'3+O4L)E`2?T.]2\0^9=3K@BX(1^AYIWR+PK
-M"?<^X(1^AYIWR+S[0+B/`2?T.]2\0^;=)\)M`D[H=ZAYYYAW6\)]#CBAWSG-
-M.\>\^T*X^X`3^IW3O'/,NZ^$^];C0(KJO4L2>2/<PZ1F8=G[3Q?NCZVPUP=F
-M@,4EP+D,/:Y<=,*IKXW+@'6MY9?ZVF@.:+8JI1_-YGVF^+T-53'.;TN5$7"'
-MI:=;7P9,4U-5$^#O+C^83>/R_/)C.]Q6927L]8'3_7K\[8"%?SN0MT669J:`
-MQV;X]^&/L+[%<@]\'J>_':"!+N&^(TYPVP$.O7V!,BBKD7?#WP/<9ATZ<X.;
-M?3O0/O(<I0%ULNFRLA1];^EM':QS>Z?=/A!U%UMVI]ROKPGY";T%1M.=R<],
-MI]M>Q/N';;8>+0XBTS5CW+E1#=9SM(21L[>99K=?>#$LKXQ'5FX+&5>NQ\&R
-FC:`\=Y;&P.:HZ5X?./U<C[\>Z`BXV!ET67OM7?T'9%>AF-(4````
+M'XL("%[N+50``VEM9RTV,W@R-34M-#`Y-BUE8G(N<6-O=S(N;W5T`*V8VY+3
+M,`R&[_<IS!D6*+'DI`F'%A:6&>[@`KA.3T_1X=FI:R5V%"G>=M)V,NVX_S=R
+M_%E-6A3A84QIC:N,:\QA8TZ?Z04F^3!\F>.O[S\6Z>-X$V"V4%+"P'+?XP:L
+M?Q$'&JZPXP$KXY+J4,!!EQJ#<CBG5C<U(.!N;\ZG[KP8-4O@-<"`4Q?CJOH@
+MU,<3[LKZ8.[Z4#Y_99?C`]5T?1CJXZFEAJNS.!!2C89KLS@44AL-M\WBG)#:
+M:3AEYR:X4D@=%)S-J'+"54+*:CC(XI9""C6<R^)J(:5Y9_/>-4)*\\[FO6N%
+ME.:=S7NW$5*:=S;OW59(:=[9O'<[(:5Y!XIW)N+V0DKS#IAWCPCW..(.0DKS
+M#IAW3PCWM,=9*:5Y!\R[9X1['G%"OP/-.V#>O2#<RX@3^AUHW@'S[A7A;B-.
+MZ'>@>0?,N]>$>Q-Q0K\#S3M@WKT=>6>%?@>:=\B\>T>L(N*$?H>:=\B\LX2#
+MB!/Z'6K>(?,."><B3NAWJ'F'S+N2<%7$"?T.->^0>;<D7!UQ0K]#S3MDWC6$
+M>Q]Q0K]#S3MDWGT@W,>($_H=:MXA\^X3X581)_0[U+QSS+LUX3Y'G-#OG.:=
+M8]Y](=Q=Q`G]SFG>.>;=5\)]ZW$@I7KOBD)^$>Y^M&=AWNM/%Z^/K7#4!R:`
+M]27`J0H#KIEUPF78&Q<"Y0D'G-\;83)MV9ELR6?*;VW<%6E]ZV#S*L7MYI[N
+MX3)@69JV'0%_=_7!9!F7U[?<^V&_*UOAJ`\<[Q;#9P>LP[\#2[_)RLK4\-`*
+M_][_$=:WGN^&+^#T?P=HH"NX[X@CW#K!^0N,0_+-=%L-O$O?)[C5(G;F$V[R
+MWP%_R[.7!M3)EO/*4O>]I;<U66=_I>UOB+H?6W:EW*^OB?4)O04&TYVHSXRG
+MZW_$^YMMMAX>!YGIFB%NTW<680DS9V\UKFX[\V)8OC,>N',]9+AS`P[F;03-
+DN;.<##Q]:WS4!XX_%\-G`#H"SG8&7>5_>V_^`UMI__/2%```
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu
index a874b5b..024a0b2 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu
@@ -1,12 +1,12 @@
# $FreeBSD$
begin 644 img-63x255-4096-ebr.raw.gz
-M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N<F%W+F]U=`"ME,T.PB`,
-MQ^][BIX]+,"&P\N6F'CWHIYQ;D^QA[>,35MA'R;P%9+"+__24B%\`\`9'<N&
-M(?]I0W;(1II\_@WL^RC0XUJ\A0=P6#UM<!0]P;42BBZJKW%+37&OU.[V_P&U
-M!FL#X&W6IQ*'H^J<N50@;&1=-@SGG/<9:,:$T164&O01C-JK\'&Y1^)KA$SE
-ML,>I+=PLV&=0#-<07.&S[TN1Y!;-.[HGN-K/&5>NJ<.7$%W,L.BL3ILL!CN_
-M1^,,L@-9@#"337'@)[[PU7<*92CF[HH^"-VU#E?Q\Y+@U(:[P'%CH2+Q9"'<
-M>+TZ5-<F#H;\_1D[?ZZ#\)_K<2IM(3B-E04S$$^%Z[)AN.:\>V`Y`9.]H*M\
-+0F1O]"SVO.4&````
+M'XL("%[N+50``VEM9RTV,W@R-34M-#`Y-BUE8G(N<F%W+F]U=`"ME,T.@R`,
+MQ^\^1<\[&$"9[*+)DMUWV79&IT_APZ\5=2#XE4"%2`J__$L+C)D&@#WXK3OZ
+M=-'ZY)(,-%Z?!_(@T.`:VL5IF98T9AU-:9QQ#<[;@+X*#5MIX[ZQP^W.`:4$
+MK3W@:](G(J>C:,F="V`Z,*X[^GOJV@140\'(`G()\@I*'%7X>;P#^56,QPK8
+MX,0>;A)L*BB$JRQ<AL[.6FDJ<=QEUYW];^%*TR=<OJ4.3X*U(<=JL#)NL2@T
+M=Y^=9^`M\`R8&GW"!<[YA;^^FR]#..%NZ`,_7$VXPEW/+9S8"1=<7#V_+($4
+M[IQ>Z:MK(B>#+V_&P9M+$/?F&IR(^Q#<AI<%*Q!7^>.ZHW^FKAE@/@*CG2"]
+,?(PE/\L2J-?E!@``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
index c00d389..4a2ad29 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-4096-ebr.vhd.gz
-M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD+F]U=`"ME\%NG#`0
-MAN_[%"/UE@,R@VW(92-%3<^1HK1G+X$HAS91MX<<>/AXL+W8@-EL,\`BK\;S
-M^1_/V,A"N`M`5Z![T!UH1>U:@KZ&N@&P1O_@^"[]7QC:US]=^^_EO?#7L'.P
-M4L1>J3OY8P72#E(#&AI$/U$;AH`IOMT]7[W\?@XX]+@PL-0@$92%R,4XC3BI
-M(]*/VX?O<W754MWDY<;I>ZCZJ$<5JRN*FQ@GK9?M3X^&7HXRPY/\20PQ+E&G
-MQ,PKDKDVJ5&P:SB]Y74)[FKG<^%*Q19&;=\"=`DU4MN639B'Q6-+Y?WX9OX>
-MNYD^S)2*CI(QM\E\N.A+!4-GKT"2P*UP8:0<Y[B54OG2[.G43_J&G02A@@''
-M\-/9FU`0Z].EV)CS?#*R^LQF7/\1\.%P,3"CT.':4\!&31&YM>K]VQ*J;E7?
-MN&SW,>Z).]S^,J!28,P"^!CTM<SI:!HRV[U3F)5WWC#<%NE]`HX%HVK:SI6&
-M!C^K\-?=SY7\-B:S'5P>L,/A.5P0'._V*>XFPE6N^B9*M#DE=1>W(]S>_0).
-M;JFC/:%;,V2#5<S%8IJ97YQG*#LH*Q"-MV$*/.47)GW72QF8A+NA#Y;A&L+5
-M:?\RPN&9<"'%'?QW-_1,4GAF]O9+=2US,@[SE?')E4N0=.4Z'/)N!&;<66P%
-MVE[+=]XPW!?I[8#H/T5LWS;TFRF;0NF!;`HML&-6:'B_']HK9#HH$([QH$`X
-BQH,"X1@/"H1C/"@0CO&@0#C6@X*V1T`A=A\#O(;Y70X`````
+M'XL("%_N+50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD+F]U=`"METUOXR`0
+MAN_Y%2/UUH.%QX#=2R)5S9Y7JMJ>L6M7/>R'FCWDX!^_C(%D\%>:EI@@K&$>
+MWH$!"R'<#T`7H#O0+6A%[5*"OH.R`K!&7W"H<_\*??/G=]O\>S]F_M=O'"P7
+MW"MV)W\L0-I!2D!#@^A7:D,?,-G-_NWV_==;P*''A8&E!HF@+$1.QJG$21V1
+M?MP_/HS5%5-U9R\W3M=!T;$>!5>793N.D];+]J>BH9.#S%"BE\C`<9$Z)49>
+M3.;<I+)@YW!ZS>L:W.W&KX5+%9L8I:T%Z!Q*I+9-FS`/DV)3Y7CX:SX.[4@?
+M+J2*9HLQMLGE<-&G"H;.7H$D@6OAPD`YC'$SJ?*MV=.QG_0-.PE"!0,.X<>S
+M=T8!UZ=SL3+GRXNQJ,^LQO6%@.OZ>N#*[J@;OSL$&$4U[=+<[U7OW]CW=D;?
+MSFW;+<>]I@ZWNPZH%!@S`3X%?4WBY:@J,MNS4YB9>MG0WV?Q<P(.":-*.LZ5
+MA@H_J_!E_SRSOI59.`ZN#]CA\!(N".:G?8S;,5SAMAM/U;,7SSO>9KBM^P><
+M7%-'9T([9U@,5B5.%E.-_/@Z0]Y"7H"HO`UCX&E]X:SO;BH#HW!7],$T7$.X
+M,NZ?,QQ>"!=B7'TZ66:6\,+L;:?JFL2+48]WQB=W+D'BG>MPF/8@,,/)8C/0
+M]IK6RX;^9Q8_#HC^4Y3LVX;^,$VF4'I@,H46V"96:-)^/[17F.BB0+B$%P7"
+D);PH$"[A18%P"2\*A$MX42!<THN"ME=`(3;_`?39ZI==#@``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu
index b2dd812..c48c7d2 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu
@@ -1,15 +1,15 @@
# $FreeBSD$
begin 644 img-63x255-4096-ebr.vhdf.gz
-M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD9BYO=70`K94[;\,@
-M$(#W_(J3NF6(``,FBR-%3>=*5=O9=7"4H>W2H8-_?,$8FS,XCPJ#$=;!YWMQ
-M$.(>`/,F^[*@V\R>;K5>]33Z<3>P;9-`AVO,+K/`]%H,$].+-L`U%`J=U&]G
-MARK$'7.;V]X'%`+J.@*^>OU8YG"4VHHY`U(GQF5!M]_@YH&J3QA1`A<@)"AV
-MJX;OA[=$?!6AN0QV.'8-YQ5V&93"[0)<X;)OHM!@5YAWX3S`5>[U.'Y).^,)
-MHE."16-%WF11IN%]89R!:J`%$#7(&`:.\85)OVVL!D/F7M`/8G-KBROQ>AK@
-MV!5S`>/Z0A7$$X7PBO>J6+LF<S#H_&3<>'(M!)]<AV-Y"\&VKRPF`\VJ>%P6
-M=,\;W!R0#\!L'E3#W28+D"U(#5+8><E!;J%4(9#A3.J:[R_=_)Q_PPA;'!VO
-MHKC;_:RPIT66P&K[$WFT\T"_A\-I??X\>9PO5?['7%JG"P/AD;D*F_NT?WF<
-M:U?$3E+(>W2Z.$?#D?=V(8Z/QFK=ET`Z=?2!!,E297&"S';]-[8.)S.GBKEW
-*5W]/U6F<$`D`````
+M'XL("%_N+50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD9BYO=70`K94[;\,@
+M$(#W_(J3NF6(``,F2R)%3>=*5=O9<7&4H>W2H8-_?#EC',[&>508C$`'G^_%
+MF3'_`+@WV><%[6KTM(OEHJ/QP_U`G@1Z7(VG.&ZK%(Y%@TL<!USMUC:AW]8U
+M]VQBW$=N<YO[@$I!54V`KT$_D3D<I46Q%,"JQ#@O:'<KV@+0=`FC2I`*E`8C
+M;M7P??^6B*]A/)?!'B>NX8+"/H-2N&V$*YRPB7;Z3.Q/Q7D7SR/<QK\!)R]I
+MYSS!;$HP:ZS*FRS&-7HNCC-P"[P`9GJ9H,`AOG#6;SU50Q!S+^@'4W,KQ)5T
+M/X]PXHJY0'&'H;(D0GC%>YNI=G7F8/#QS;CQYB*$WER/$WD+P;JK+"X#W:[I
+M."]HGU>T>:#L@=D\:/I_FRY`-Z`M:(7S4H)>0VEBH*"9U-;?7[;^.?W&$48<
+M]\4@V?&\*/"VZ!)$A1_1'SB/]'O8'Y>GSV/`A5(5/BPU.ETYB)R8:ZBY3[N7
+MQ[%VQ=1)AGB/HYYQV7.&$^]M8YP<C+6V*X'\W,F"")*E"G&*C4[]-[8>IS.G
+.BOOO+OX`/$*Q[A`)````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu
index 92bef31..3ad6aa6 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu
@@ -1,6 +1,6 @@
# $FreeBSD$
begin 644 img-63x255-4096-ebr.vmdk.gz
-M'XL("`+&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FUD:RYO=70`K5S1;N3&
+M'XL("%_N+50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FUD:RYO=70`K5S1;N3&
M$7SW5PSDMSPL6,LEN7PX.W'.`8(@@!$[]FO(Y3`68M\==$*0`_3QX9!3HR)%
M'FFK=:L#^]A=V]U#M735!679].'<I767B[MTKBA=!C?\T_1R6?YL#*]+NO'T
MM[=___'$CS^>3D]?3&`(41*"3.'$F+W/TVGQ0;CSYZ)F-X;7>1<N#U'MB\`(
@@ -73,12 +73,12 @@ M(9'6Y29R2*1UN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6YB1P2:5UN(H=$6I>;
MR"&1UN4F<DBD=;F)'!)<E]O((<%UN8T<$MY4#@EO*H>$-Y5#PIO*(>%-Y9#P
MIG)(>%,Y)+RI'!+>5`X);RJ'A#>50\*;RB'A3>60\*9R2/199BB'1&\JAT1O
M*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\J
-MAT1O*H=$;RJ'/&=99BB'/&>F<LCSRU]-?`SN9;&3W/""]C<#]OUF]RX(3][@
-M,+R:(EX,K[P7N!M<[E?S^SK\]97"==;E]K\-L"A<T[P`_"?S.W\VC=^>7S7^
-M[V+Z5;(O_]Z^\?3-:?Z'@-?Q<2ZJ\%MQB])=ST<S_.G;'Q<93G!F<M<);O=Q
-M3J1EOP7WM<#ET]/WC**_N%N?.[T6N*^F3\)=/I>=[I..%6O\F[:OV741I^<<
-MODT$]H[_*3O/`=/YNN?\ZI=IG&?E?B8_][+<\"U2?]>LGL=LJFZ4Z^9PXZ"2
-M\YP=X4[WOGJ9W<WX,+#\RCCXE1M`YE^Y$]S9=A#4XV291!HO_]Z^\?3=:?YG
-6`KQ$0+,.7L+O$<F^^#]5"_Y['F``````
+MAT1O*H=$;RJ'/&=99BB'/&>F<LCSRU]-?`SN9;&3W/""]K<#8K-[%XQ/WDA6
+M->-_X?(^F'DO<+?!]BOY?3W\&3Z^4KC.NMS^MP$6A6N:%X#_9'[GSZ;QV_.K
+MQO]=3+]*]N7?VS>>OCG-_Q#P.C[.115^*VY1NNOY:(8_??OC(L,)SDSN.L'M
+M/LZ)M.RWX+X6N/#MNQ?/V2_NUN=.KP7NJ^F3<)?/9:?[I&/%&O^F[6MV7<3I
+M.8=O$X&]XW_*SG/`=+[N.;_Z91KG6;F?R<^]+#=\B]3?-:OG,9NJ&^6Z.5R;
+M)LO*$>YT[ZN7V=V,#P/+KXR#7[D!9/Z5.\&=;0=!/4Z62:3Q\N_M&T_?G>9_
+7)L!+!#3KX"7\'I'LB_\#:C6@$!Y@````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu
index 003299f..2a4ea04 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu
@@ -1,128 +1,128 @@
# $FreeBSD$
begin 644 img-63x255-4096-mbr.qcow.gz
-M'XL(",@S(E0``VEM9RTV,W@R-34M-#`Y-BUM8G(N<6-O=RYO=70`K9W);EQ7
-MLD7G_HI4+U%=1L1MU9!$`:^`FM4;O*JI;SO.#Q#JVXL63T/&W5LA/TLF#`KT
-MW<@\7%HR[(6C\_G^Q^G4RJGI3LUXVN?3W<_3AYP>_.3QQ^G;__[]'Q\>_OCV
-MV_V8G'_PE/MYOY6Y1UO_J7/ZQU/+Z3S^Q-S=AZ"Y!Z_._L2K>_!FCW-7O]V_
-M6?R<LD%[-'A*<^?T^H2<7O-SK^_6O5VY/[U?]W:5O-WVYP;_Z5Z?_BE8?NKU
-M_<GO;P<'?R^OKX%/]6QN>#1W.;S=%CXULKGIAS#KN8-/S6QN">9Z^-3*YK9@
-M;H!/[7A.?O"]O9\;X5/"YA3.G<K<!)\R-M<\FCNGN=LR-\.GR*\+<=SE7Q>5
-MNP4^1;B3D+L5/D6XDY"[#3Y%N).0NQT^1;B3B#O!3Q'N-.).D**4<:<1=X*,
-MK(P[C;@3Y#MEW&G$G2#?*>-.(^X$^4X9=QIQ)\AWRKC3B#M!OE/&G8;<(=\I
-MX\Y"[I#OC'%G(7?(=\:XLY`[Y#MCW%G('?*=,>XLY`[YSAAW%G*'?&>,.PNY
-M0[XSQIU%W"E^BG#71-PI\EW#N&LB[A3YKF'<-1%WBGS7,.Z:B#M%OFL8=TW$
-MG2+?-8R[)N).D>\:QET3<:?(=PWCK@FY0[YK&'=MR!WR7<NX:T/ND.]:QET;
-M<H=\US+NVI`[Y+N6<=>&W"'?M8R[-N0.^:YEW+4A=\AW+>.NC;@S_!3AKHNX
-M,^2[CG'71=P9\EW'N.LB[@SYKF/<=1%WAGS7,>ZZB#M#ONL8=UW$G2'?=8R[
-M+N+.D.\ZQET7<H=\US'N^I`[Y+N><=>'W"'?]8R[/N0.^:YGW/4A=\AW/>.N
-M#[E#ONL9=WW('?)=S[CK0^Z0[WK&71]QU^"G"'=#Q%V#?#<P[H:(NP;Y;F#<
-M#1%W#?+=P+@;(NX:Y+N!<3=$W#7(=P/C;HBX:Y#O!L;=$''7(-\-C+LAY`[Y
-M;F#<Y?\\S^>0[T;&W1ARAWPW,N[&D#ODNY%Q-X;<(=^-C+LQY`[Y;F3<C2%W
-MR'<CXVX,N4.^&QEW8\1=BY\BW$T1=RWRW<2XFR+N6N2[B7$W1=RUR'<3XVZ*
-MN&N1[R;&W11QUR+?38R[*>*N1;Z;&'=3Q%V+?#<Q[J:0.^2[B7&7_S<IGT.^
-MFQEW<\@=\MW,N)M#[I#O9L;=''*'?#<S[N:0.^2[F7$WA]PAW\V,NSGD#OEN
-M9MS-$7<=?HIPMT3<=<AW"^-NB;CKD.\6QMT2<=<AWRV,NR7BKD.^6QAW2\1=
-MAWRW,.Z6B+L.^6YAW"T1=QWRW<*X6T+ND.\6QMT:<H=\MS+NUI`[Y+N5<;>&
-MW"'?K8R[->0.^6YEW*TA=\AW*^-N#;E#OEL9=VO('?+=RKA;(^YZ_!3AC@1"
-M#^:0[S;&W19QUR/?;8R[+>*N1[[;&'=;Q%V/?+<Q[K:(NQ[Y;F/<;1%W/?+=
-MQKC;(NYZY+N-<;>%W"'?;8R[/>0.^6YGW.TA=\AW.^-N#[E#OML9=WO('?+=
-MSKC;0^Z0[W;&W1YRAWRW,^[VD#ODNYUQMT?<#?@IS)WD3_@<\)V<"7=RCK@;
-M@._D3+B3<\3=`'PGK`\4W]\=N!N`[X3U=Q+V=P/PG;#^3L+^;@"^$];?2=C?
-M#<!WPOH["?N[`?A.6'\G87\W`-\)Z^\D[.\&X#MA_9V$_=T`?">LOY.POQN`
-M[X3U=Q+V=P/PG;#^3L+^;@"^$];?2=C?#<!WPOH["?N[$3]%N`O[NQ'YCO5W
-M$O9W(_(=Z^\D[.]&Y#O6WTG8WXW(=ZR_D["_&Y'O6'\G87\W(M^Q_D["_FY$
-MOF/]G83]W8A\Q_H["?N[$?F.]7<2]G<C\AWK[R3L[T;D.];?2=C?C<AWK+^3
-ML+\;D>]8?R=A?S<BW['^3L+^;D2^8_V=A/W=A)\BW(7]W81\Q_H["?N["?F.
-M]7<2]G<3\AWK[R3L[R;D.];?2=C?3<AWK+^3L+^;D.]8?R=A?S<AW['^3L+^
-M;D*^8_V=A/W=A'S'^CL)^[L)^8[U=Q+V=Q/R'>OO).SO)N0[UM])V-]-R'>L
-MOY.POYN0[UA_)V%_-R'?L?Y.POYNQD\1[L+^;D:^8_V=A/W=C'S'^CL)^[L9
-M^8[U=Q+V=S/R'>OO).SO9N0[UM])V-_-R'>LOY.POYN1[UA_)V%_-R/?L?Y.
-MPOYN1KYC_9V$_=V,?,?Z.PG[NQGYCO5W$O9W,_(=Z^\D[.]FY#O6WTG8W\W(
-M=ZR_D["_FY'O6'\G87^WX*<(=V%_MR#?L?Y.POYN0;YC_9V$_=V"?,?Z.PG[
-MNP7YCO5W$O9W"_(=Z^\D[.\6Y#O6WTG8WRW(=ZR_D["_6Y#O6'\G87^W(-^Q
-M_D["_FY!OF/]G83]W8)\Q_H["?N[!?F.]7<2]G<+\AWK[R3L[Q;D.];?2=C?
-M+<AWK+^3L+];\5.$N["_6Y'O6'\G87^W(M^Q_D["_FY%OF/]G83]W8I\Q_H[
-M"?N[%?F.]7<2]G<K\AWK[R3L[U;D.];?2=C?K<AWK+^3L+];D>]8?R=A?[<B
-MW['^3L+^;D6^8_V=A/W=BGS'^CL)^[L5^8[U=Q+V=ROR'>OO).SO5N0[UM])
-MV-]M^"G"7=C?;<AWK+^3L+_;D.]8?R=A?[<AW['^3L+^;D.^8_V=A/W=AGS'
-M^CL)^[L-^8[U=Q+V=QOR'>OO).SO-N0[UM])V-]MR'>LOY.PO]N0[UA_)V%_
-MMR'?L?Y.POYN0[YC_9V$_=V&?,?Z.PG[NPWYCO5W$O9W&_(=Z^\D[.]V_!3A
-M+NSO=N0[UM])V-_MR'>LOY.PO]N1[UA_)V%_MR/?L?Y.POYN1[YC_9V$_=V.
-M?,?Z.PG[NQWYCO5W$O9W._(=Z^\D[.]VY#O6WTG8W^W(=ZR_D["_VY'O6'\G
-M87^W(]^Q_D["_FY'OF/]G83]W8Y\Q_H["?N['?F.]7<2]7=VQD]A[C1_XN9.
-M=0[X[NXIS)VZ_B[?]W<ZE3G@.V7]G;K^[I2X.]V6.>`[9?V=NO[NE+@[_5[F
-M@.^4]7?J^KO3Y7!VP'?*^CMU_5TYNSH'?*>LOU/7WX$YX#ME_9VZ_@[,`=\I
-MZ^_4]7=Y[DF=`[Y3UM^IZ^^>Y+G*'?"=LOY.77_W)''WI'('?*>LOU/7WSU)
-MW#VIW`'?*>OOU/5W3RZ'LP.^4];?J>OORMG5.>`[9?V=NOX.S`'?*>OOU/5W
-MQSET_YVR_DY=?Y?GGM8YY#O6WZGK[Y[FN<(=NO].67^GKK][FKA[6KA#]]\I
-MZ^_4]7=/$W=/"W?H_CME_9VZ_N[IY7!VR'>LOU/7WY6SJW/(=ZR_4]??@3GD
-M.];?J>OOP!SR'>OOU/5W>>Y9G4.^8_V=NO[N69ZKW"'?L?Y.77_W+''WK'*'
-M?,?Z.W7]W;/$W;/*'?(=Z^_4]7?/+H>S0[YC_9VZ_JZ<79U#OF/]G;K^#LPA
-MW['^3EU_=YQ#]]\IZ^_4]7=Y[GF=0[YC_9VZ_NYYGBO<H?OOE/5WZOJ[YXF[
-MYX4[=/^=LOY.77_W/''WO'"'[K]3UM^IZ^^>7PYGAWS'^CMU_5TYNSJ'?,?Z
-M.W7]'9A#OF/]G;K^#LPAW['^3EU_E^=>U#GD.];?J>OO7N2YRAWR'>OOU/5W
-M+Q)W+RIWR'>LOU/7W[U(W+VHW"'?L?Y.77_WXG(X.^0[UM^IZ^_*V=4YY#O6
-MWZGK[\`<\AWK[]3U=\<Y=/^=LOY.77^7YU[6.>0[UM^IZ^]>YKG"';K_3EE_
-MIZZ_>YFX>UFX0_??*>OOU/5W+Q-W+PMWZ/X[9?V=NO[NY>5P=LAWK+]3U]^5
-MLZMSR'>LOU/7WX$YY#O6WZGK[\`<\AWK[]3U=WGN59U#OF/]G;K^[E6>J]PA
-MW['^3EU_]RIQ]ZIRAWS'^CMU_=VKQ-VKRAWR'>OOU/5WKRZ'LT.^8_V=NOZN
-MG%V=0[YC_9VZ_@[,(=^Q_DY=?W><0_??*>OOU/5W>>YUG4.^8_V=NO[N=9XK
-MW*'[[Y3U=^KZN]>)N]>%.W3_G;+^3EU_]SIQ][IPA^Z_4];?J>OO7E\.9X=\
-MQ_H[=?U=.;LZAWS'^CMU_1V80[YC_9VZ_@[,(=^Q_DY=?Y?GWM0YY#O6WZGK
-M[][DN<H=\AWK[]3U=V\2=V\J=\AWK+]3U]^]2=R]J=PAW['^3EU_]^9R.#OD
-M.];?J>OORMG5.>0[UM^IZ^_`'/(=Z^_4]7?'.73_G;+^3EU_E^>NZASR'>OO
-MU/5W5WFN<(?NOU/6WZGK[ZX2=U>%.W3_G;+^3EU_=Y6XNRK<H?OOE/5WZOJ[
-MJ\OA[)#O6'^GKK\K9U?GD.]8?Z>NOP-SR'>LOU/7WX$YY#O6WZGK[_+<VSJ'
-M?,?Z.W7]W=L\5[E#OF/]G;K^[FWB[FWE#OF.]7?J^KNWB;NWE3OD.];?J>OO
-MWEX.9X=\Q_H[=?U=.;LZAWS'^CMU_1V80[YC_9VZ_NXXA^Z_4];?J>OO\MR[
-M.H=\Q_H[=?W=NSQ7N$/WWRGK[]3U=^\2=^\*=^C^.V7]G;K^[EWB[EWA#MU_
-MIZR_4]??O;L<S@[YCO5WZOJ[<G9U#OF.]7?J^CLPAWS'^CMU_1V80[YC_9VZ
-M_B[/O:]SR'>LOU/7W[W/<Y4[Y#O6WZGK[]XG[MY7[I#O6'^GKK][G[A[7[E#
-MOF/]G;K^[OWE<';(=ZR_4]??E;.K<\AWK+]3U]^!.>0[UM^IZ^^.<^C^.V7]
-MG;K^+L]]J'/(=ZR_TZB_,W3_G;+^3J/^SM#]=\KZ.XWZ.T/WWRGK[S3J[PS=
-M?Z>LO].HOS-T_YVR_DZC_L[0_7?*^CN-^CM#]]\IZ^^4]'<?ZQSR'>OOU/5W
-M'_-<Y0[YCO5WZOJ[CXF[CY4[Y#O6WZGK[SXF[CY6[I#O6'^GKK_[>#F<'?(=
-MZ^_4]7?E[.H<\AWK[]3U=V`.^8[U=^KZN^,<NO].67]G^1,W=ZYSP'?&^KN[
-M+SSB+OOI7+A#]]\9Z^_,]7?GM'<NW*'[[XSU=^;ZNW/B[ERX0_??&>OOS/5W
-MY\OA[(#OC/5WYOJ[<G9U#OC.6']GKK\#<\!WQOH[<_T=F`.^,];?F>OO\IS4
-M.>`[8_V=N?Y.\ESE#OC.6']GKK^3]/*D<@=\9ZR_,]??2>).*G?`=\;Z.W/]
-MG5P.9P=\9ZR_,]??E;.K<\!WQOH[<_T=F`.^,];?F>OOCG/H_CMC_9VY_B[/
-M:9U#OF/]G;G^3O-<X0[=?V>LOS/7WVGB3@MWZ/X[8_V=N?Y.$W=:N$/WWQGK
-M[\SU=WHYG!WR'>OOS/5WY>SJ'/(=Z^_,]7=@#OF.]7?F^CLPAWS'^CMS_5V>
-MLSJ'?,?Z.W/]G>6YRAWR'>OOS/5WEKBSRAWR'>OOS/5WEKBSRAWR'>OOS/5W
-M=CF<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.^8[U=^;ZN^,<NO_.6']GKK_+<TV=
-M0[YC_9VY_J[)<X4[=/^=L?[.7'_7).Z:PAVZ_\Y8?V>NOVL2=TWA#MU_9ZR_
-M,]??-9?#V2'?L?[.7']7SJ[.(=^Q_LY<?P?FD.]8?V>NOP-SR'>LOS/7W^6Y
-MMLXAW['^SEQ_U^:YRAWR'>OOS/5W;>*NK=PAW['^SEQ_UR;NVLH=\AWK[\SU
-M=^WE<';(=ZR_,]??E;.K<\AWK+\SU]^!.>0[UM^9Z^^.<^C^.V/]G;G^+L]U
-M=0[YCO5WYOJ[+L\5[M#]=\;Z.W/]79>XZPIWZ/X[8_V=N?ZN2]QUA3MT_YVQ
-M_LY<?]==#F>'?,?Z.W/]73F[.H=\Q_H[<_T=F$.^8_V=N?X.S"'?L?[.7'^7
-MY_HZAWS'^CMS_5V?YRIWR'>LOS/7W_6)N[YRAWS'^CMS_5V?N.LK=\AWK+\S
-MU]_UE\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0[UA_9ZZ_.\ZA^^^,]7?F^KL\
-M-]0YY#O6WYGK[X8\5[A#]]\9Z^_,]7=#XFXHW*'[[XSU=^;ZNR%Q-Q3NT/UW
-MQOH[<_W=<#F<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.^8[U=^;Z.S"'?,?Z.W/]
-M79X;ZQSR'>OOS/5W8YZKW"'?L?[.7'\W)N[&RAWR'>OOS/5W8^)NK-PAW['^
-MSEQ_-UX.9X=\Q_H[<_U=.;LZAWS'^CMS_1V80[YC_9VY_NXXA^Z_,];?F>OO
-M\MRG.H=\Q_H[<_W=ISQ7N$/WWQGK[\SU=Y\2=Y\*=^C^.V/]G;G^[E/B[E/A
-M#MU_9ZR_,]???;H<S@[YCO5WYOJ[<G9U#OF.]7?F^CLPAWS'^CMS_1V80[YC
-M_9VY_B[/?:YSR'>LOS/7WWW.<Y4[Y#O6WYGK[SXG[CY7[I#O6']GKK_[G+C[
-M7+E#OF/]G;G^[O/E<';(=ZR_,]??E;.K<\AWK+\SU]^!.>0[UM^9Z^^.<^C^
-M.V/]G;G^+L]]J7/(=ZR_,]???<ESA3MT_YVQ_LY<?_<E<?>E<(?NOS/6WYGK
-M[[XD[KX4[M#]=\;Z.W/]W9?+X>R0[UA_9ZZ_*V=7YY#O6']GKK\#<\AWK+\S
-MU]^!.>0[UM^9Z^_RW-<ZAWS'^CMS_=W7/%>Y0[YC_9VY_NYKXNYKY0[YCO5W
-MYOJ[KXF[KY4[Y#O6WYGK[[Y>#F>'?,?Z.W/]73F[.H=\Q_H[<_T=F$.^8_V=
-MN?[N.(?NOS/6WYGK[_+<=9U#OF/]G;G^[CK/%>[0_7?&^CMS_=UUXNZZ<(?N
-MOS/6WYGK[ZX3=]>%.W3_G;'^SEQ_=WTYG!WR'>OOS/5WY>SJ'/(=Z^_,]7=@
-M#OF.]7?F^CLPAWS'^CMS_5V>NZESR'>LOS/7W]WDN<H=\AWK[\SU=S>)NYO*
-M'?(=Z^_,]7<WB;N;RAWR'>OOS/5W-Y?#V2'?L?[.7']7SJ[.(=^Q_LY<?P?F
-MD.]8?V>NOSO,-6?\%.:NR9^XN=LZ!WS7L/ZN<?W=;9X[E3G@N[NG,'>-Z^]N
-M$W>WMV4.^*YA_5WC^KO;Q-WM[V4.^*YA_5WC^KO;R^'LT)^W74Z<?N';!_?C
-MVV]7WP?;[]_;1D_G"?R=?^';WSX\_JL,?K_7Z$\,WKWA?3\,YC?<?K_7Z.X?
-MN/N8VO3)W<>]W=+;6Z3^+OOX#=\4\^4Y].=&_Y7S0U<1_6BP;4_3=!C\O_SZ
-MT%5$?^7U==LO_O[VWX%I^U/3GMKN-.C/OL)__\^_W"N\GP,R^/^]X?LY((/'
-M<_D%E]\?#W,W#^;LGKZZ(@^>>LC=P\\?S%U_>/`;>(]D4.?^$."&OD#?["^6
-M07^X</+A]_G[G<QV.N?_/^,N.BW?WU-]?2CP?_1V?_#Z3L>W^_U?,/K'_[P\
-MF-/@[9X>SWW_%XP'W\]'W\+@]*Z/KP[]`?=_Y9MQN#;Q)W_E_C'R^%?N_9S^
-K6A$,W\WRQV^+$_@[_\*W?WYX_-?]8),&?]D)-G?TG<^__1>$>8]XH:@`````
+M'XL("&'N+50``VEM9RTV,W@R-34M-#`Y-BUM8G(N<6-O=RYO=70`K9W)CE79
+M$47G]16/'I+N1<1M:3)3EFS),WM@>UJW';\/0/YV`WF:S+A[$Y0+0*5$67?K
+MO9.+1:E8.IS/=]].IU9.37=JQM,^G[[^//V0T[V?//QQ^O+/O_W]W?UO7WZ[
+M&Y/S#YYR/^^W,O=@Z[]U3K\]M9S.XT_,??TA:.[>J[,_\.KNO=GCW-5O=V\6
+M/Z=LT!X,GM+<.;T^(:?7_-SKNW5O5^Y.[]>]725OM_VYP7^XUZ=_"):?>GU_
+M\.O;P<'?R^MKX%,]FQL>S%T.;[>%3XUL;OHAS'KNX%,SFUN"N1X^M;*Y+9@;
+MX%,[GI,??&WOYD;XE+`YA7.G,C?!IXS--0_FSFGNMLS-\"GRZT(<=_G71>5N
+M@4\1[B3D;H5/$>XDY&Z#3Q'N).1NAT\1[B3B3O!3A#N-N!.D*&7<:<2=(",K
+MXTXC[@3Y3AEW&G$GR'?*N-.(.T&^4\:=1MP)\ITR[C3B3I#OE'&G(7?(=\JX
+MLY`[Y#MCW%G('?*=,>XLY`[YSAAW%G*'?&>,.PNY0[XSQIV%W"'?&>/.0NZ0
+M[XQQ9Q%WBI\BW#41=XI\US#NFH@[1;YK&'=-Q)TBWS6,NR;B3I'O&L9=$W&G
+MR'<-XZZ)N%/DNX9QUT3<*?)=P[AK0NZ0[QK&71MRAWS7,N[:D#ODNY9QUX;<
+M(=^UC+LVY`[YKF7<M2%WR'<MXZX-N4.^:QEW;<@=\EW+N&LC[@P_1;CK(NX,
+M^:YCW'41=X9\US'NNH@[0[[K&'==Q)TAWW6,NR[BSI#O.L9=%W%GR'<=XZZ+
+MN#/DNXYQUX7<(=]UC+L^Y`[YKF?<]2%WR'<]XZX/N4.^ZQEW?<@=\EW/N.M#
+M[I#O>L9='W*'?-<S[OJ0.^2[GG'71]PU^"G"W1!QUR#?#8R[(>*N0;X;&'=#
+MQ%V#?#<P[H:(NP;Y;F#<#1%W#?+=P+@;(NX:Y+N!<3=$W#7(=P/C;@BY0[X;
+M&'?Y?\_S.>2[D7$WAMPAWXV,NS'D#OEN9-R-(7?(=R/C;@RY0[X;&7=CR!WR
+MW<BX&T/ND.]&QMT8<=?BIPAW4\1=BWPW,>ZFB+L6^6YBW$T1=RWRW<2XFR+N
+M6N2[B7$W1=RUR'<3XVZ*N&N1[R;&W11QUR+?38R[*>0.^6YBW.4_)N5SR'<S
+MXVX.N4.^FQEW<\@=\MW,N)M#[I#O9L;=''*'?#<S[N:0.^2[F7$WA]PAW\V,
+MNSGBKL-/$>Z6B+L.^6YAW"T1=QWRW<*X6R+N.N2[A7&W1-QUR'<+XVZ)N.N0
+M[Q;&W1)QUR'?+8R[)>*N0[Y;&'=+R!WRW<*X6T/ND.]6QMT:<H=\MS+NUI`[
+MY+N5<;>&W"'?K8R[->0.^6YEW*TA=\AW*^-N#;E#OEL9=VO$78^?(MR10.C>
+M'/+=QKC;(NYZY+N-<;=%W/7(=QOC;HNXZY'O-L;=%G'7(]]MC+LMXJY'OML8
+M=UO$78]\MS'NMI`[Y+N-<;>'W"'?[8R[/>0.^6YGW.TA=\AW.^-N#[E#OML9
+M=WO('?+=SKC;0^Z0[W;&W1YRAWRW,^[VB+L!/X6YD_P!GP.^DS/A3LX1=P/P
+MG9P)=W*.N!N`[X3U@>+[NP-W`_"=L/Y.POYN`+X3UM])V-\-P'?"^CL)^[L!
+M^$Y8?R=A?S<`WPGK[R3L[P;@.V']G83]W0!\)ZR_D["_&X#OA/5W$O9W`_"=
+ML/Y.POYN`+X3UM])V-\-P'?"^CL)^[L!^$Y8?R=A?S?BIPAW87\W(M^Q_D["
+M_FY$OF/]G83]W8A\Q_H["?N[$?F.]7<2]G<C\AWK[R3L[T;D.];?2=C?C<AW
+MK+^3L+\;D>]8?R=A?S<BW['^3L+^;D2^8_V=A/W=B'S'^CL)^[L1^8[U=Q+V
+M=R/R'>OO).SO1N0[UM])V-^-R'>LOY.POYOP4X2[L+^;D.]8?R=A?S<AW['^
+M3L+^;D*^8_V=A/W=A'S'^CL)^[L)^8[U=Q+V=Q/R'>OO).SO)N0[UM])V-]-
+MR'>LOY.POYN0[UA_)V%_-R'?L?Y.POYN0KYC_9V$_=V$?,?Z.PG[NPGYCO5W
+M$O9W$_(=Z^\D[.\FY#O6WTG8W\WX*<)=V-_-R'>LOY.POYN1[UA_)V%_-R/?
+ML?Y.POYN1KYC_9V$_=V,?,?Z.PG[NQGYCO5W$O9W,_(=Z^\D[.]FY#O6WTG8
+MW\W(=ZR_D["_FY'O6'\G87\W(]^Q_D["_FY&OF/]G83]W8Q\Q_H["?N[&?F.
+M]7<2]G<S\AWK[R3L[Q;\%.$N[.\6Y#O6WTG8WRW(=ZR_D["_6Y#O6'\G87^W
+M(-^Q_D["_FY!OF/]G83]W8)\Q_H["?N[!?F.]7<2]G<+\AWK[R3L[Q;D.];?
+M2=C?+<AWK+^3L+];D.]8?R=A?[<@W['^3L+^;D&^8_V=A/W=@GS'^CL)^[L%
+M^8[U=Q+V=RM^BG`7]G<K\AWK[R3L[U;D.];?2=C?K<AWK+^3L+];D>]8?R=A
+M?[<BW['^3L+^;D6^8_V=A/W=BGS'^CL)^[L5^8[U=Q+V=ROR'>OO).SO5N0[
+MUM])V-^MR'>LOY.POUN1[UA_)V%_MR+?L?Y.POYN1;YC_9V$_=V*?,?Z.PG[
+MNPT_1;@+^[L-^8[U=Q+V=QOR'>OO).SO-N0[UM])V-]MR'>LOY.PO]N0[UA_
+M)V%_MR'?L?Y.POYN0[YC_9V$_=V&?,?Z.PG[NPWYCO5W$O9W&_(=Z^\D[.\V
+MY#O6WTG8WVW(=ZR_D["_VY#O6'\G87^W(=^Q_D["_FY#OF/]G83]W8Z?(MR%
+M_=V.?,?Z.PG[NQWYCO5W$O9W._(=Z^\D[.]VY#O6WTG8W^W(=ZR_D["_VY'O
+M6'\G87^W(]^Q_D["_FY'OF/]G83]W8Y\Q_H["?N['?F.]7<2]G<[\AWK[R3L
+M[W;D.];?2=C?[<AWK+^3L+_;D>]8?R=A?[<CW['^3J+^SL[X*<R=Y@_<W*G.
+M`=]]?0ISIZZ_R_?]G4YE#OA.67^GKK\[)>Y.MV4.^$Y9?Z>NOSLE[DZ_ESG@
+M.V7]G;K^[G0YG!WPG;+^3EU_5\ZNS@'?*>OOU/5W8`[X3EE_IZZ_`W/`=\KZ
+M.W7]79Y[5.>`[Y3U=^KZNT=YKG('?*>LOU/7WSU*W#VJW`'?*>OOU/5WCQ)W
+MCRIWP'?*^CMU_=VCR^'L@.^4]7?J^KMR=G4.^$Y9?Z>NOP-SP'?*^CMU_=UQ
+M#MU_IZR_4]??Y;G'=0[YCO5WZOJ[QWFN<(?NOU/6WZGK[QXG[AX7[M#]=\KZ
+M.W7]W>/$W>/"';K_3EE_IZZ_>WPYG!WR'>OOU/5WY>SJ'/(=Z^_4]7=@#OF.
+M]7?J^CLPAWS'^CMU_5V>>U+GD.]8?Z>NOWN2YRIWR'>LOU/7WSU)W#VIW"'?
+ML?Y.77_W)''WI'*'?,?Z.W7]W9/+X>R0[UA_IZZ_*V=7YY#O6'^GKK\#<\AW
+MK+]3U]\=Y]#]=\KZ.W7]79Y[6N>0[UA_IZZ_>YKG"G?H_CME_9VZ_NYIXNYI
+MX0[=?Z>LOU/7WSU-W#TMW*'[[Y3U=^KZNZ>7P]DAW['^3EU_5\ZNSB'?L?Y.
+M77\'YI#O6'^GKK\#<\AWK+]3U]_EN6=U#OF.]7?J^KMG>:YRAWS'^CMU_=VS
+MQ-VSRAWR'>OOU/5WSQ)WSRIWR'>LOU/7WSV[',X.^8[U=^KZNW)V=0[YCO5W
+MZOH[,(=\Q_H[=?W=<0[=?Z>LOU/7W^6YYW4.^8[U=^KZN^=YKG"'[K]3UM^I
+MZ^^>)^Z>%^[0_7?*^CMU_=WSQ-WSPAVZ_TY9?Z>NOWM^.9P=\AWK[]3U=^7L
+MZASR'>OOU/5W8`[YCO5WZOH[,(=\Q_H[=?U=GGM1YY#O6'^GKK][D><J=\AW
+MK+]3U]^]2-R]J-PAW['^3EU_]R)Q]Z)RAWS'^CMU_=V+R^'LD.]8?Z>NORMG
+M5^>0[UA_IZZ_`W/(=ZR_4]??'>?0_7?*^CMU_5V>>UGGD.]8?Z>NOWN9YPIW
+MZ/X[9?V=NO[N9>+N9>$.W7^GK+]3U]^]3-R]+-RA^^^4]7?J^KN7E\/9(=^Q
+M_DY=?U?.KLXAW['^3EU_!^:0[UA_IZZ_`W/(=ZR_4]??Y;E7=0[YCO5WZOJ[
+M5WFN<H=\Q_H[=?W=J\3=J\H=\AWK[]3U=Z\2=Z\J=\AWK+]3U]^]NAS.#OF.
+M]7?J^KMR=G4.^8[U=^KZ.S"'?,?Z.W7]W7$.W7^GK+]3U]_EN:LZAWS'^CMU
+M_=U5GBO<H?OOE/5WZOJ[J\3=5>$.W7^GK+]3U]]=)>ZN"G?H_CME_9VZ_N[J
+M<C@[Y#O6WZGK[\K9U3GD.];?J>OOP!SR'>OOU/5W8`[YCO5WZOJ[//>ZSB'?
+ML?Y.77_W.L]5[I#O6'^GKK][G;A[7;E#OF/]G;K^[G7B[G7E#OF.]7?J^KO7
+ME\/9(=^Q_DY=?U?.KLXAW['^3EU_!^:0[UA_IZZ_.\ZA^^^4]7?J^KL\]Z;.
+M(=^Q_DY=?_<FSQ7NT/UWROH[=?W=F\3=F\(=NO].67^GKK][D[A[4[A#]]\I
+MZ^_4]7=O+H>S0[YC_9VZ_JZ<79U#OF/]G;K^#LPAW['^3EU_!^:0[UA_IZZ_
+MRW-OZQSR'>OOU/5W;_-<Y0[YCO5WZOJ[MXF[MY4[Y#O6WZGK[]XF[MY6[I#O
+M6'^GKK][>SF<'?(=Z^_4]7?E[.H<\AWK[]3U=V`.^8[U=^KZN^,<NO].67^G
+MKK_+<^_J'/(=Z^\TZN\,W7^GK+_3J+\S=/^=LOY.H_[.T/UWROH[C?H[0_??
+M*>OO-.KO#-U_IZR_TZB_,W3_G;+^3J/^SM#]=\KZ.R7]W?LZAWS'^CMU_=W[
+M/%>Y0[YC_9VZ_NY]XNY]Y0[YCO5WZOJ[]XF[]Y4[Y#O6WZGK[]Y?#F>'?,?Z
+M.W7]73F[.H=\Q_H[=?T=F$.^8_V=NO[N.(?NOU/6WUG^P,V=ZQSPG;'^[NLG
+M'G"7_70NW*'[[XSU=^;ZNW/:.Q?NT/UWQOH[<_W=.7%W+MRA^^^,]7?F^KOS
+MY7!VP'?&^CMS_5TYNSH'?&>LOS/7WX$YX#MC_9VY_@[,`=\9Z^_,]7=Y3NH<
+M\)VQ_LY<?R=YKG('?&>LOS/7WTEZ>5*Y`[XSUM^9Z^\D<2>5.^`[8_V=N?Y.
+M+H>S`[XSUM^9Z^_*V=4YX#MC_9VY_@[,`=\9Z^_,]7?'.73_G;'^SEQ_E^>T
+MSB'?L?[.7'^G>:YPA^Z_,];?F>OO-'&GA3MT_YVQ_LY<?Z>).RW<H?OOC/5W
+MYOH[O1S.#OF.]7?F^KMR=G4.^8[U=^;Z.S"'?,?Z.W/]'9A#OF/]G;G^+L]9
+MG4.^8_V=N?[.\ESE#OF.]7?F^CM+W%GE#OF.]7?F^CM+W%GE#OF.]7?F^CN[
+M',X.^8[U=^;ZNW)V=0[YCO5WYOH[,(=\Q_H[<_W=<0[=?V>LOS/7W^6YILXA
+MW['^SEQ_U^2YPAVZ_\Y8?V>NOVL2=TWA#MU_9ZR_,]??-8F[IG"'[K\SUM^9
+MZ^^:R^'LD.]8?V>NORMG5^>0[UA_9ZZ_`W/(=ZR_,]??@3GD.];?F>OO\EQ;
+MYY#O6']GKK]K\USE#OF.]7?F^KLV<==6[I#O6']GKK]K$W=MY0[YCO5WYOJ[
+M]G(X.^0[UM^9Z^_*V=4YY#O6WYGK[\`<\AWK[\SU=\<Y=/^=L?[.7'^7Y[HZ
+MAWS'^CMS_5V7YPIWZ/X[8_V=N?ZN2]QUA3MT_YVQ_LY<?]<E[KK"';K_SEA_
+M9ZZ_ZRZ'LT.^8_V=N?ZNG%V=0[YC_9VY_@[,(=^Q_LY<?P?FD.]8?V>NO\MS
+M?9U#OF/]G;G^KL]SE3OD.];?F>OO^L1=7[E#OF/]G;G^KD_<]94[Y#O6WYGK
+M[_K+X>R0[UA_9ZZ_*V=7YY#O6']GKK\#<\AWK+\SU]\=Y]#]=\;Z.W/]79X;
+MZASR'>OOS/5W0YXKW*'[[XSU=^;ZNR%Q-Q3NT/UWQOH[<_W=D+@;"G?H_CMC
+M_9VY_FZX',X.^8[U=^;ZNW)V=0[YCO5WYOH[,(=\Q_H[<_T=F$.^8_V=N?XN
+MSXUU#OF.]7?F^KLQSU7ND.]8?V>NOQL3=V/E#OF.]7?F^KLQ<3=6[I#O6']G
+MKK\;+X>S0[YC_9VY_JZ<79U#OF/]G;G^#LPAW['^SEQ_=YQ#]]\9Z^_,]7=Y
+M[D.=0[YC_9VY_NY#GBO<H?OOC/5WYOJ[#XF[#X4[=/^=L?[.7'_W(7'WH7"'
+M[K\SUM^9Z^\^7`YGAWS'^CMS_5TYNSJ'?,?Z.W/]'9A#OF/]G;G^#LPAW['^
+MSEQ_E^<^UCGD.];?F>OO/N:YRAWR'>OOS/5W'Q-W'RMWR'>LOS/7WWU,W'VL
+MW"'?L?[.7'_W\7(X.^0[UM^9Z^_*V=4YY#O6WYGK[\`<\AWK[\SU=\<Y=/^=
+ML?[.7'^7YS[5.>0[UM^9Z^\^Y;G"';K_SEA_9ZZ_^Y2X^U2X0_??&>OOS/5W
+MGQ)WGPIWZ/X[8_V=N?[NT^5P=LAWK+\SU]^5LZMSR'>LOS/7WX$YY#O6WYGK
+M[\`<\AWK[\SU=WGN<YU#OF/]G;G^[G.>J]PAW['^SEQ_]SEQ][ERAWS'^CMS
+M_=WGQ-WGRAWR'>OOS/5WGR^'LT.^8_V=N?ZNG%V=0[YC_9VY_@[,(=^Q_LY<
+M?W><0_??&>OOS/5W>>ZZSB'?L?[.7']WG><*=^C^.V/]G;G^[CIQ=UVX0_??
+M&>OOS/5WUXF[Z\(=NO_.6']GKK^[OAS.#OF.]7?F^KMR=G4.^8[U=^;Z.S"'
+M?,?Z.W/]'9A#OF/]G;G^+L_=U#GD.];?F>OO;O)<Y0[YCO5WYOJ[F\3=3>4.
+M^8[U=^;ZNYO$W4WE#OF.]7?F^KN;R^'LD.]8?V>NORMG5^>0[UA_9ZZ_`W/(
+M=ZR_,]??'>::,WX*<]?D#]S<;9T#OFM8?]>X_NXVSYW*'/#=UZ<P=XWK[VX3
+M=[>W90[XKF']7>/ZN]O$W>WO90[XKF']7>/ZN]O+X>S0W[==3IQ^XLL[]^W+
+M;U??!]OO7]M&3^<)_)-_XLM?WCW\7@:_WVOT!P:_O6$Y#.8WW-[=:_2]K9O:
+M!-[7G][9+;V]1>KOLO??\,T=?-?O[LVAOS?ZSYP?NHKH1X-M>YJFP^"_\NM#
+M5Q']F=?7;;_XZ]M_!Z;M3TU[:KO3H#_["O_SUW^[5W@W!V3P_[WANSD@@X=S
+M^067WQ\/<S?WYK[)8+_W;Y[EWE/WN;O_\;VYZW?W?@/OD0SJW#<!;N@3],W^
+M8AGTAPLG[W^=O]_);*=S_O,9=]%I^?J>ZNM#@?^#M_N#UW<ZOMWO_X'1/_SW
+MY=Z<!F_W]'!N+F8!7\+@]*Z/KP[]!?=_YHMQN#;Q)W_E?AMY^"OW;DY_K0B&
+H[V;Y]MOB!/[)/_'E'^\>?K\;;-+@+SO!YBM]Y_-O_P.[1]$3H:@`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu
index 8d3e191..4524f2b 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu
@@ -1,23 +1,22 @@
# $FreeBSD$
begin 644 img-63x255-4096-mbr.qcow2.gz
-M'XL(",`[(U0``VEM9RTV,W@R-34M-#`Y-BUM8G(N<6-O=S(N;W5T`*V8VY+3
-M,`Q`W_<KS!T6*+'DI`F7%A:6&=[@`7A.;U_1X=M):C5*%"G>=M)F,NVX.B/;
-M1VJ2+(LOYW+O0N%"Y0X;UWRG`USOR_!PQU_??RSZK^--A/G,B%(&EOL.-V#]
-M8QQ8N,R/![R.ZV6'"@[.46-0"A?,[*8&%-SMS6GI3IM1B@B\!AAQYF9<E1_$
-M_&1$N#(_F#L_U-<O/\?)@6(Z/XSYR:BEA2N3.%"B*@M7)W&H1&TLW#:)"TK4
-MSL(9E=O#Y4K4P<#YA"H-KE"BO(6#)&ZI1*&%"TE<J419WOFT=Y4297GGT][5
-M2I3EG4][MU&B+.]\VKNM$F5YY]/>[90HRSLPO'.,VRM1EG<@O'M$N,>,.RA1
-MEG<@O'M"N*<=SFM1EG<@O'M&N.>,4_H=6-Z!\.X%X5XR3NEW8'D'PKM7A+ME
-MG-+OP/(.A'>O"?>&<4J_`\L[$-Z]'7GGE7X'EG<HO'M'K(QQ2K]#RSL4WGG"
-M`>.4?H>6=RB\0\(%QBG]#BWO4'B7$ZY@G-+OT/(.A7=+PI6,4_H=6MZA\*XB
-MW'O&*?T.+>]0>/>!<!\9I_0[M+Q#X=TGPJT8I_0[M+P+PKLUX3XS3NEWP?(N
-M".^^$.Z.<4J_"Y9W07CWE7#?.AQH49UW6:8?A+L?U2S,>_T9^/K8*V=[8`)8
-M7@*<RC#BJEDGG,<)MQK4RMD>.-XMAN\.>"JV"X#-^AP.(R!-.(_%UOR@.>J<
-M/C1'+!":WM9SF0TGO*928]QNYO4[U<<%P#QW=3T"_C[G!Y-I7)[?<C_S_I;Q
-M<<.RK=J\<"4\-,._]W_&0C>XV2HXXNS'#31P3KAKL2/<NH?#:!]3>G4Z\*[_
-MN8=;+;C5-[C)QPWM/=1>&S`GF\\K2]DUJ\[6WCZWE^[M'=;YWUM<>G?[ZS@_
-MI5G!8+H3^;GQ=-NK@N[N7>Q'BX/$=-T0US:J_GX.MC"Q>JMQ=MN9-\/+RGA@
-MY;:08>5&',S;"*I39VD,;'XU/ML#QY^+X3L"`P%G6\%0M/]M-_\!8,LR/2,5
-"````
+M'XL("&+N+50``VEM9RTV,W@R-34M-#`Y-BUM8G(N<6-O=S(N;W5T`*V8VY+3
+M,`Q`W_<KS!T6*+'DW+BTL+#,\`8/P'-Z^XH.WTY2*[&C2/&VDS:3:<?5&=D^
+M4I-DF7\9DUOC"N-J<]R:]CL=8*(OX\.<?GW_L8I?IQL/LYD2)0R4AP$W8OT+
+M.-!PF9T.6!D798<"#OJH*2B%<VIV<P,"[O;FO'3GS:A8!%X#]#AU,Z[*#WQ^
+M/,)=F1\LG1_*ZY?W<7R@F,\/?7X\JM1P51('0E2MX9HD#H6HK8;;)7%.B-IK
+M.*5R(UPN1!T5G$VHTN(*(<IJ.$CB2B$*-9Q+XBHA2O/.IKVKA2C-.YOVKA&B
+M-.]LVKNM$*5Y9]/>[80HS3N;]FXO1&G>@>*=";B#$*5Y!\R[1X1[''!'(4KS
+M#IAW3PCW=,!9*4KS#IAWSPCW/."$?@>:=\"\>T&XEP$G]#O0O`/FW2O"W0:<
+MT.]`\PZ8=Z\)]R;@A'X'FG?`O'L[\<X*_0XT[Y!Y]XY86<`)_0XU[Y!Y9PD'
+M`2?T.]2\0^8=$LX%G-#O4/,.F7<YX8J`$_H=:MXA\ZXD7!5P0K]#S3MDWM6$
+M>Q]P0K]#S3MDWGT@W,>`$_H=:MXA\^X3X=8!)_0[U+QSS+L-X3X'G-#OG.:=
+M8]Y](=Q=P`G]SFG>.>;=5\)]&W`@10W>99E\$.Y^4K.P[/6G"]?'5CCK`S/`
+MZA+@7(8>5R\ZX=Q/N-.@$<[ZP.EN-7X/P'.Q70"L:`7'.)IP[HO-KTZ3]Z5A
+MJ4!H>CL;RBR>\,:7QWH5X?8+K]^Y/BX`YKEIF@GP=Y\?S*9Q>7[E8>']K?SC
+MAK*KVKPP%3PTP[_W?Z9"M[C%*MCC],<---`G/+38"6X3X;HKEF/TR[A.1][%
+MGR/<>A5:?8N;?=S0W4,=I`%ULOFRLE1#LQILC?:YNW3O[K#Z?V]VZ3WLKPGY
+M"<T*1M.=R<],I]M=%0QW[VP_.APDIFO&N.W0680M3*S>>IK=;N'-L+PR'EBY
+M'61<N1X'RS:"^MQ96@/;7TW/^L#IYVK\]D!'P,56T!7=?]O-?U_U;%8C%0``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu
index 7daee29..b3375d7 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu
@@ -1,12 +1,12 @@
# $FreeBSD$
begin 644 img-63x255-4096-mbr.raw.gz
-M'XL("`/&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N<F%W+F]U=`"ME+V.PR`,
-MQ_<\A><."$AHZ))*E6Z_I>W,Y9*GR,/7Q*0Q)1^-!!B$9/CI;VR0DAI`I4&Z
-MA7G=,=Q$W(?B5(PT]7<,:"7T?0(4""1<BSC<@.9,6*"5/7CA.-!:!647UF0P
-MB+%=_=0(AOM_GTIMW1%P<YO#[8\!C0'G$N!]TJ<W91S75W>9\VO'@C$U5`;,
-M&:S^5N'SY_&AD'`J5\"$TWNX23!5T!+NRG`E5=],4>P4KSN^9KB&QH2KMM3A
-M3<ANR;$:K,E;+!9[?([G&50'J@1I@T_'P'=^8=9W267H*-P-?9"&ZSRNCO<K
-MAM,[X4*,\Q\5SV>4PIW;:U)U;>9DJ,^7\>7+]9#XY1).Y_T(+N//@A6(N])Y
-9W3'\BK@3L`K`;#?H?SXIBQ>7_'@>Y08`````
+M'XL("&+N+50``VEM9RTV,W@R-34M-#`Y-BUM8G(N<F%W+F]U=`"ME,V.A"`,
+MQ^\^1<][(`5E92Y.LLG>][(S9\;5I_#AMUAURN#'F$"18`J__$L+B-P`*@/H
+M5\9MQ_"E8AN*CV*DZ<<YH$-`G0`5`1G7$HX6D$QOPUCVX3>,P8&AM_3?37/N
+M,!!!7<FH-4K@_I9=:=]VC#C9GN'VYX#6@O<)\'?69W9EG-=7=YGSZ\:"L354
+M%NPG./.NPOOW[44AXW2N@!EGCG"S8*Z@-=Q5X$IR]F(E5^*T2]:=G`M<P]^,
+MJ_;4T4E@M^;8#-;F+19'%N^3>0;=@2X!W>0S,7#)+SSU75(9)@IW1Q^DX?J`
+MJ^/U6N#,0;@0XQ[+R[*2PH/3:U)U;>9DZ->;\>;-#9#XYC+.Y'T(+N/+0A5(
+<J])QVS'\J-@86$W`;"<87C[$XA^HPB9UY08`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
index 7b3c619..695a3e9 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-4096-mbr.vhd.gz
-M'XL("`3&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD+F]U=`"METUOXR`0
-MAN_Y%2/MK0<+CP'32RI5FSU7JMJ>L6M'/>RVVNPA!__X,@9L\%>:+;9C$<$\
-MO,,,8\&8O0!D`;(%V8`4U"XYR%LH%8#I=`_V[]S]A:Y^_]/4_][.F;NZG87E
-M++2*S<D>"^!FDA)0TR3RE=K0>4SVXW"\>?M]]#AT.#\QE\`1A('PV3R*#>J(
-M].O^\>=473%7-UK9>=H6BC88483JLNPNQ'%C9<;3(Z'EO4S_1'^BCA`7J1-L
-M8A7(7%K4P-DEG-RRN@9WLW.QL*EB$J,T;P8RAQ*I;=+&K\/L,:ER/GWHOZ=F
-MH@]74D4&P9CV\75WT:4*^L%.`2>!6^Y"3SE-<0NI\JW5D[$==PVS"$SX#NS=
-MCU=O1$&H3^9L8\W7@[&J3Y,^L[>87GBO=W3W67P/P*JZ#JB851CC!H>K>G!8
-MB]$CNU?=^M4Y%,UB0/IMNP_6KWI-'-^JO0XH!&@]`SYY??6FC.OU*94XOJI/
-M&%%2.1<2%'Y5X<OA>6'_*KU2#OZO^BF-EW!><%CM8]Q=@"ML]HV4H#A%>1>V
-M`]S>_CR.;ZFCFM`L=:PZ*Q(GBU83NS#.D#>0%\"4Z\,8.,071GVW<QD8N;NA
-M#^;N:L*5\?@\P.$%=R'&5>Z[ZT=&(;RP>ONYNCIQ,*KISOCBSB5(O',M#M,6
-M`MU7%I.!9M3\O=[1/63Q;8'H/D7)OFWHBFDRA=P!DRDTP":Q0IWV^R&=PD0'
-J!<(E/"@0+N%!@7`)#PJ$2WA0(%S"@P+ADAX4I#D",K;[!%1JM8A=#@``
+M'XL("&+N+50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD+F]U=`"METMOW"`0
+MQ^_[*4;J+0<+CP&3RZX4-3U7JMJ>L6-'.?2A;@\Y^,.7,>`%OS;;S)I%6,"/
+M/\S#0@C_`]`5Z!YT!UI1NY:@[Z$V`*XS%!SK,KS"T/[ZV;5_7UZ+\!L.'E:*
+M=%8^G>9C!=(M4@-:6D0_41N&B"D^/#[?O?QXCC@,N+BPU"`1E(/(Q3I&3.J(
+M].GAR\>YNFJI[C++K]/W4/7)B"I55Q2G%"?=+#>>BH9>CC)CR5ZRCA27J5-B
+M-BN1N7:HR6;7<'IOUBVXNT.PA7<5YQBUJP7H$FJDMG.;>`Z+XESE]?S;_CEW
+M,WVXX2HZ,<:\3VYO%X.K8!P<%$@2N+==&"GG.6[%5=YU>CJ?)T/#'8)0L0/'
+M[>>G=T%!JD^78N?,MXVQJ<^2/A=;PJ[4VQW#0Y$_$[!I;@,:X:,CQTT;;MH0
+M'0*LHIJBM`RQ&LZO=>_=BD%./FR/R?DU3\SV;?K;@$J!M0O@UZBOW95QNSYC
+MF.UK1H=1-:5SI<'@6Q5^?_RV$K_&;J2#_\M^QN(U7!2<9OL<=TIPE0^W"R5)
+M3IG?I>T$=_3_B)-[ZB@G=&L=FYM5S,YBS6Q>:F<H.R@K$";T80Z<[`L7??=+
+M&9AM=T<?++=K"5?GX\L$AU>V"SFNF3++B@FOG-YQJ:YE-D8SCXPW1BY!\LCU
+M..1-!';,+,X#W:AEO=TQ?"[RQP,Q?(K8OFT8DBF;0AF`;`H=L&-6:'F_'SHH
+L9+HH$([QHD`XQHL"X1@O"H1CO"@0CO&B0#C6BX)V5T`A#O\`HP_9YET.````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu
index 8cbe404..1e1f537 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu
@@ -1,15 +1,15 @@
# $FreeBSD$
begin 644 img-63x255-4096-mbr.vhdf.gz
-M'XL("`3&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD9BYO=70`K96[;L,@
-M%(;W/,61NF6PN)LLB10UG2M5;6?7P5&&MDN'#G[X@O&%8WQ)*NQC"POX_)\+
-M0(B_``0#4DR\YSOJ8X;O>K/=-#3Z<1]0$ZBJ")A9H,>5%F<'6"MDV[#&*W#"
-M[6.MI,!-V_8&==9<!_?:9P'NW,^*;;ZCQ0W7X&YU'U!**(H(^-KI8XLR[M>7
-MF\3YU4W!R!R$!*E`LUL5OI_>1@H]CJ9RV./8&JX3["MH"G<(<-Q7WT"AP:RP
-M[L)V@-O[I\.))74V$L1,=<PZ*],6B[8WGA?F&:@!RH'HMH]A8)]?&/3M8AD,
-MN;N@#V)W"X?+\7@:X-B*NX!Q;J,*\XE2N!*]?:RN3)P,.EX9-ZY<!\$KU^-8
-MVHU@U^PLM@+MJ/@]WU$_9_CV0-$"DT50MV>;XJ`J4`:4=.U<@-I!KD,@PY54
-ME]]?IORY_H89=CC:'T6QN?F,N]6B<F"%^XDZNW:@[^%TV5X_+QVNVZJZ'POE
-M@BXM1$3N:NSNT_'E<:R.QT'2*'IT.#A[QU'T#B%.],X:TVR!=##T@3HFMRJ'
-8DV0TZ[^Y]3B5N%3LN;OY`[XTL3D0"0``
+M'XL("&+N+50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD9BYO=70`K94];\,@
+M$(;W_(J3NF6P``,F2R)%3>=*5=O9<7"4(>W2H8-_?.^,[8"Q\U%A",(Z>/(>
+M=YP9<P^`%,#*B7'>T&RSL#6+Y:*E\?UC0,.`\0B8(=#A*L3A`I19*AKSFEYI
+M)`.C7N&[[>:N0X.$;(,-GW7FX0[#KKC/&UJ<_US<K1\#*@5E&0'?>WWBJHS'
+M]14V<7Q-FS"J`*E`:3#B7H6?NX^10H?CJ1QV.'$+UPMV&32%VWBX'(VUM])E
+M8K?+SSM_[N'6[M?CY#5U>!+,3AEFG55ID\5@"_?Y<09N@>?`3&<3(7"(+UST
+MK6(9(G#WBCZ(W2T)5X3KN8<3-]R%$+<?*LM$"&^<WCI65R4.!A_?C#MO+D'"
+MF^MP(FTA6+65!3,05\7CO*%YS<+F@+(#)CM!TWW;=`ZZ!FU!*YH7$O0*"N,#
+M19A)3?7]9:N?TZ\?8<)Q5PPF.^T7.=T678`HZ4_T@>:>OJ?=<7DZ'WM<7ZKZ
+M/Y::#ETA1$;NFM#=E^W;\UA='A^2"4Z/DTZ_[*'CP>EM?)P<G+6V+8'\TH.7
+=P#!9J@BGV&C7?V/K<#IQJN!W=_$'S:-I2Q`)````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu
index c26e913..5ebc9fc 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu
@@ -1,6 +1,6 @@
# $FreeBSD$
begin 644 img-63x255-4096-mbr.vmdk.gz
-M'XL("`3&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FUD:RYO=70`K5S1;N3&
+M'XL("&/N+50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FUD:RYO=70`K5S1;N3&
M$7SW5PSDMSPL6,LEN7PX.W'.`8(@@!$[]FO(Y3`68M\==$*0`_3QX9!3HR)%
M'FFK=:L#^]A=V]U#M735!679].'<I767B[MTKBA=!C?\T_1R6?YL#*]+NO'T
MM[=___'$CS^>3D]?3&`(41*"3.'$F+W/TVGQ0;CSYZ)F-X;7>1<N#U'MB\`(
@@ -74,11 +74,11 @@ MR"&1UN4F<DBD=;F)'!)<E]O((<%UN8T<$MY4#@EO*H>$-Y5#PIO*(>%-Y9#P
MIG)(>%,Y)+RI'!+>5`X);RJ'A#>50\*;RB'A3>60\*9R2/199BB'1&\JAT1O
M*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\J
MAT1O*H=$;RJ'/&=99BB'/&>F<LCSRU]-?`SN9;&3W/`RECO][M*7?V_?>/KF
-M-/^3`-'^-L#A0>C[%X`L^(+P*`\.PZLIXL7PRGLI^`:7^]6"OPY_?742N,ZX
-M?^A_&V!1N*9Y`?A/YG?^;!J_/;_*&Y_O=7Q@BBK\FMVB=-?ST0Q_^O;'1883
-MG)E^=H+;_?I(+&B_!?>UP.73T_>,HK\)7)\[O1:XKZ9/PET^EYTNJ(X5:_RK
-MNZ_9=1&GYQR^[P0ZD/_+.\\!T_FZY_SJEVF<9^5^)C_WLMSP/5=_>:V>QVQ,
-M;Y3KYG!A4.EYSHYPIWM?O<SN9GP86'YE'/S*#2#SK]P)[FP[".IQLDRJCY=_
->;]]X^NXT_S,!7B*@60<OX1>39%_\'RJ'TQAO8```
+M-/^3`-'^-L!)$+<$9,$7C(_RR'XUX_\)\SZ8>2\%WP;;KQ3\]?!G^/CJ)'"=
+M<?_0_S;`HG!-\P+PG\SO_-DT?GM^E3<^W^OXP!15^#6[1>FNYZ,9_O3MCXL,
+M)S@S_>P$M_OUD5C0?@ON:X$+/P_TXCG[3>#ZW.FUP'TU?1+N\KGL=$%UK%CC
+M7]U]S:Z+.#WG\'TGT('\7]YY#IC.USWG5[],XSPK]S/YN9?EAN^Y^LMK]3QF
+M8WJC7#>':]-D63G"G>Y]]3*[F_%A8/F5<?`K-X#,OW(GN+/M(*C'R3*I/E[^
+>O7WCZ;O3_,\$>(F`9AV\A%],DGWQ?Q6YC7-O8```
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu
index 0eada21..bfa03be 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu
@@ -1,126 +1,126 @@
# $FreeBSD$
begin 644 img-63x255-4096-pc98.qcow.gz
-M'XL(",HS(E0``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G%C;W<N;W5T`*V=RXX<
-M1Y)%]_J*Y/M-IIE%9$3PC0:F@=YQ%C.S[7RN]0'$?/M0I%=XE>6Y,FI$BA`H
-M9,=%IM>I(Z)UX-QN?_S8;$;;#+O-L&PNA\VW?VX_;7/K'^[^W'S]SW_^Z_7M
-M'U]_^S%FVS]Y*OWS=%[G[FS];Y_S/YXZ;K;+3\Q]^VDT=^O=Q5]X=[<^[/7<
-M\]]^?%A^SM5@W!G<M+EM>W\F3F_XN??W.7U<^W%ZO^[CNOBXHQK<W1G\TN;^
-MW=Z?_R58?NK]_<6O[X2#OZ_O;\"G9C6W_"E]OAWQJ;V:.Q1S.WSJJ.9.Q=R$
-M3YW5W*68F^$I4U\**[YS?;O@4^(;S8IO--_N\2GQC68WA*=OM"_KW`&?VJFY
-MN]S]^XJ[(SXEN+.2NQ,^);BSDKLS/B6XLY*["SXEN+.*.Z.G7''G%7=&BG+%
-MG5?<&1G9%7=><6?D.U?<><6=D>]<<><5=T:^<\6=5]P9^<X5=UYQ9^0[5]QY
-MR1WY+A1W47)'O@O%793<D>]"<1<E=^2[4-Q%R1WY+A1W47)'O@O%793<D>]"
-M<1<E=^2[4-Q%Q9W34X/B;JBX<_+=H+@;*NZ<?#<H[H:*.R??#8J[H>+.R7>#
-MXFZHN'/RW:"X&RKNG'PW*.Z&BCLGWPV*NZ'DCGPW*N[&DCORW:BX&TONR'>C
-MXFXLN2/?C8J[L>2.?#<J[L:2._+=J+@;2^[(=Z/B;BRY(]^-BKNQXB[HJ9WB
-M;E=Q%^2[G>)N5W$7Y+N=XFY7<1?DNYWB;E=Q%^2[G>)N5W$7Y+N=XFY7<1?D
-MNYWB;E=Q%^2[G>)N5W)'OIL4=U/)'?EN4MQ-)7?DNTEQ-Y7<D>\FQ=U4<D>^
-MFQ1W4\D=^6Y2W$TE=^2[27$WE=R1[R;%W51Q-]!3L^)NKK@;R'>SXFZNN!O(
-M=[/B;JZX&\AWL^)NKK@;R'>SXFZNN!O(=[/B;JZX&\AWL^)NKK@;R'>SXFXN
-MN2/?W?R_\/!"Q1WY;E'<+25WY+M%<;>4W)'O%L7=4G)'OEL4=TO)'?EN4=PM
-M)7?DNT5QMY3<D>\6Q=U2<3?24WO%W;[B;B3?[15W^XJ[D7RW5]SM*^Y&\MU>
-M<;>ON!O)=WO%W;[B;B3?[15W^XJ[D7RW5]SM*^Y&\MU><;<ON2/?W?S74'BA
-MXHY\=U#<'4KNR'<'Q=VAY(Y\=U#<'4KNR'<'Q=VAY(Y\=U#<'4KNR'<'Q=VA
-MY(Y\=U#<'2KN=O3447%WK+C;D>^.BKMCQ=V.?'=4W!TK[G;DNZ/B[EAQMR/?
-M'15WQXJ['?GNJ+@[5MSMR'='Q=VQXFY'OCLJ[HXE=^2[D^+N5')'OCLI[DXE
-M=^2[D^+N5')'OCLI[DXE=^2[D^+N5')'OCLI[DXE=^2[D^+N5')'OCLI[DX5
-M=Q,]M79`UR\4W$WDN[/B[EQQ-Y'OSHJ[<\7=1+X[*^[.%7<3^>ZLN#M7W$WD
-MN[/B[EQQ-Y'OSHJ[<\7=1+X[*^[.)7?DNXOB[E)R1[Z[*.XN)7?DNXOB[E)R
-M1[Z[*.XN)7?DNXOB[E)R1[Z[*.XN)7?DNXOB[E)R1[Z[*.XN%7<S/&4WOX`7
-M"NYF\)VIX-"JX-!G\)VIX-"V%7<S^,ZV@CO+_=T5=S/XSE1_9V5_-X/O3/5W
-M5O9W,_C.5']G97\W@^],]7=6]G<S^,Y4?V=E?S>#[TSU=U;V=S/XSE1_9V5_
-M-X/O3/5W5O9W,_C.5']G97\W@^],]7=6]G<S^,Y4?V=E?S>#[TSU=U;V=PL]
-MI?H[*_N[A7RG^CLK^[N%?*?Z.RO[NX5\I_H[*_N[A7RG^CLK^[N%?*?Z.RO[
-MNX5\I_H[*_N[A7RG^CLK^[N%?*?Z.RO[NX5\I_H[*_N[A7RG^CLK^[N%?*?Z
-M.RO[NX5\I_H[*_N[A7RG^CLK^[N%?*?Z.RO[NX5\I_H[*_N[/3VE^CLK^[L]
-M^4[U=U;V=WORG>KOK.SO]N0[U=]9V=_MR7>JO[.RO]N3[U1_9V5_MR??J?[.
-MROYN3[Y3_9V5_=V>?*?Z.RO[NSWY3O5W5O9W>_*=ZN^L[._VY#O5WUG9W^W)
-M=ZJ_L[*_VY/O5']G97^W)]^I_L[*_FY/OE/]G97]W8&>4OV=E?W=@7RG^CLK
-M^[L#^4[U=U;V=P?RG>KOK.SO#N0[U=]9V=\=R'>JO[.ROSN0[U1_9V5_=R#?
-MJ?[.RO[N0+Y3_9V5_=V!?*?Z.RO[NP/Y3O5W5O9W!_*=ZN^L[.\.Y#O5WUG9
-MWQW(=ZJ_L[*_.Y#O5']G97]W(-^I_L[*_NY(3ZG^SLK^[DB^4_V=E?W=D7RG
-M^CLK^[LC^4[U=U;V=T?RG>KOK.SOCN0[U=]9V=\=R7>JO[.ROSN2[U1_9V5_
-M=R3?J?[.RO[N2+Y3_9V5_=V1?*?Z.RO[NR/Y3O5W5O9W1_*=ZN^L[.^.Y#O5
-MWUG9WQW)=ZJ_L[*_.Y+O5']G97]WHJ=4?V=E?W<BWZG^SLK^[D2^4_V=E?W=
-MB7RG^CLK^[L3^4[U=U;V=R?RG>KOK.SO3N0[U=]9V=^=R'>JO[.ROSN1[U1_
-M9V5_=R+?J?[.RO[N1+Y3_9V5_=V)?*?Z.RO[NQ/Y3O5W5O9W)_*=ZN^L[.].
-MY#O5WUG9WYW(=ZJ_L[*_.]-3JK^SLK\[D^]4?V=E?W<FWZG^SLK^[DR^4_V=
-ME?W=F7RG^CLK^[LS^4[U=U;V=V?RG>KOK.SOSN0[U=]9V=^=R7>JO[.ROSN3
-M[U1_9V5_=R;?J?[.RO[N3+Y3_9V5_=V9?*?Z.RO[NS/Y3O5W5O9W9_*=ZN^L
-M[._.Y#O5WUG9WUWH*=7?6=G?7<AWJK^SLK^[D.]4?V=E?W<AWZG^SLK^[D*^
-M4_V=E?W=A7RG^CLK^[L+^4[U=U;V=Q?RG>KOK.SO+N0[U=]9V=]=R'>JO[.R
-MO[N0[U1_9V5_=R'?J?[.RO[N0KY3_9V5_=V%?*?Z.RO[NPOY3O5W5O9W%_*=
-MZN^LZN]B"T_YS2_@A3O<W7"RZ7/@.U?]G:?^;M/V-MMU#GSGJK_SU-]M&G>;
-M+^L<^,Y5?^>IO]LT[C:_KW/@.U?]G:?^#LX.?.>JO_/4W\$<^,Y5?^>IOX,Y
-M\)VK_LY3?P=SX#M7_9VG_NY>F[O7Y\!WKOH[3_W=O?;V[G7NP'>N^CM/_=V]
-MQMV]SAWXSE5_YZF_N]>XN]>Y`]^YZN\\]7=P=N`[5_V=I_X.YL!WKOH[3_T=
-MS('O7/5WGOJ[ZSFZ_\Y5?^>IO[O?YN[W.?*=ZN\\]7?W&W?W5^[H_CM7_9VG
-M_NY^X^[^RAW=?^>JO_/4W]UOW-U?N:/[[USU=Y[Z.S@[\IWJ[SSU=S!'OE/]
-MG:?^#N;(=ZJ_\]3?P1SY3O5WGOJ[!VWN09\CWZG^SE-_]Z!Q]Z!S1[Y3_9VG
-M_NY!X^Y!YXY\I_H[3_W=@\;=@\X=^4[U=Y[Z.S@[\IWJ[SSU=S!'OE/]G:?^
-M#N;(=ZJ_\]3?7<_1_7>N^CM/_=W#-O>PSY'O5'_GJ;][V+A[N')']]^YZN\\
-M]7</&W</5^[H_CM7_9VG_NYAX^[ARAW=?^>JO_/4W\'9D>]4?^>IOX,Y\IWJ
-M[SSU=S!'OE/]G:?^#N;(=ZJ_\]3?/6ISC_H<^4[U=Y[ZNT>-NT>=._*=ZN\\
-M]7>/&G>/.G?D.]7?>>KO'C7N'G7NR'>JO_/4W\'9D>]4?^>IOX,Y\IWJ[SSU
-M=S!'OE/]G:?^[GJ.[K]SU=]YZN\>M[G'?8Y\I_H[3_W=X\;=XY4[NO_.57_G
-MJ;][W+A[O')']]^YZN\\]7>/&W>/5^[H_CM7_9VG_@[.CGRG^CM/_1W,D>]4
-M?^>IOX,Y\IWJ[SSU=S!'OE/]G:?^[DF;>]+GR'>JO_/4WSUIW#WIW)'O5'_G
-MJ;][TKA[TKDCWZG^SE-_]Z1Q]Z1S1[Y3_9VG_@[.CGRG^CM/_1W,D>]4?^>I
-MOX,Y\IWJ[SSU=]=S=/^=J_[.4W_WM,T][7/D.]7?>>KOGC;NGJ[<T?UWKOH[
-M3_W=T\;=TY4[NO_.57_GJ;][VKA[NG)']]^YZN\\]7=P=N0[U=]YZN]@CGRG
-M^CM/_1W,D>]4?^>IOX,Y\IWJ[SSU=\_:W+,^1[Y3_9VG_NY9X^Y9YXY\I_H[
-M3_W=L\;=L\X=^4[U=Y[ZNV>-NV>=._*=ZN\\]7=P=N0[U=]YZN]@CGRG^CM/
-M_1W,D>]4?^>IO[N>H_OO7/5WGOJ[YVWN>9\CWZG^SE-_][QQ]WSECNZ_<]7?
-M>>KOGC?NGJ_<T?UWKOH[3_W=\\;=\Y4[NO_.57_GJ;^#LR/?J?[.4W\'<^0[
-MU=]YZN]@CGRG^CM/_1W,D>]4?^>IOWO1YE[T.?*=ZN\\]7<O&G<O.G?D.]7?
-M>>KO7C3N7G3NR'>JO_/4W[UHW+WHW)'O5'_GJ;^#LR/?J?[.4W\'<^0[U=]Y
-MZN]@CGRG^CM/_=WU'-U_YZJ_\]3?O6QS+_L<^4[U=Y[ZNY>-NY<K=W3_G:O^
-MSE-_][)Q]W+ECNZ_<]7?>>KO7C;N7J[<T?UWKOH[3_T=G!WY3O5WGOH[F"/?
-MJ?[.4W\'<^0[U=]YZN]@CGRG^CM/_=VK-O>JSY'O5'_GJ;][U;A[U;DCWZG^
-MSE-_]ZIQ]ZIS1[Y3_9VG_NY5X^Y5YXY\I_H[3_T=G!WY3O5WGOH[F"/?J?[.
-M4W\'<^0[U=]YZN^NY^C^.U?]G5?]7=#]=Z[Z.Z_ZNZ#[[USU=U[U=T'WW[GJ
-M[[SJ[X+NOW/5WWG5WP7=?^>JO_.JOPNZ_\Y5?^=5?Q=T_YVK_LZK_B[H_CM7
-M_9VG_NY-VWK3Y\AWJK_SU-^]:=R]Z=R1[U1_YZF_>].X>].Y(]^I_LY3?_>F
-M<?>F<T>^4_V=I_X.SHY\I_H[3_T=S)'O5'_GJ;^#.?*=ZN\\]7?7<W3_7=S\
-M`EZXP]VVS6W['/CNVU/,7:3^;MNXVZ[<T?UWH?J[2/W=MG&W7;FC^^]"]7>1
-M^KMMXVZ[<D?WWX7J[R+U=W!VX+M0_5VD_@[FP'>A^KM(_1W,@>]"]7>1^CN8
-M`]^%ZN\B]7?6YJS/@>]"]7>1^CMKW%GG#GP7JK^+U-]9X\XZ=^"[4/U=I/[.
-M&G?6N0/?A>KO(O5W<';@NU#]7:3^#N;`=Z'ZNTC]'<R![T+U=Y'ZN^LYNO\N
-M5'\7J;_S-N=]CGRG^KM(_9TW[GSECNZ_"]7?1>KOO''G*W=T_UVH_BY2?^>-
-M.U^YH_OO0O5WD?H[.#ORG>KO(O5W,$>^4_U=I/X.YLAWJK^+U-_!'/E.]7>1
-M^KMH<]'GR'>JOXO4WT7C+CIWY#O5WT7J[Z)Q%YT[\IWJ[R+U=]&XB\X=^4[U
-M=Y'Z.S@[\IWJ[R+U=S!'OE/]7:3^#N;(=ZJ_B]3?7<_1_7>A^KM(_=W0YH8^
-M1[Y3_5VD_FYHW`TK=W3_7:C^+E)_-S3NAI4[NO\N5'\7J;\;&G?#RAW=?Q>J
-MOXO4W\'9D>]4?Q>IOX,Y\IWJ[R+U=S!'OE/]7:3^#N;(=ZJ_B]3?C6UN['/D
-M.]7?1>KOQL;=V+DCWZG^+E)_-S;NQLX=^4[U=Y'ZN[%Q-W;NR'>JOXO4W\'9
-MD>]4?Q>IOX,Y\IWJ[R+U=S!'OE/]7:3^[GJ.[K\+U=]%ZN]V;6[7Y\AWJK^+
-MU-_M&G>[E3NZ_RY4?Q>IO]LU[G8K=W3_7:C^+E)_MVO<[5;NZ/Z[4/U=I/X.
-MSHY\I_J[2/T=S)'O5'\7J;^#.?*=ZN\B]7<P1[Y3_5VD_FYJ<U.?(]^I_BY2
-M?S<U[J;.'?E.]7>1^KNI<3=U[LAWJK^+U-]-C;NI<T>^4_U=I/X.SHY\I_J[
-M2/T=S)'O5'\7J;^#.?*=ZN\B]7?7<W3_7:C^+E)_-[>YN<^1[U1_%ZF_FQMW
-M\\H=W7\7JK^+U-_-C;MYY8[NOPO5WT7J[^;&W;QR1_??A>KO(O5W<';D.]7?
-M1>KO8(Y\I_J[2/T=S)'O5'\7J;^#.?*=ZN\B]7=+FUOZ'/E.]7>1^KNE<;=T
-M[LAWJK^+U-\MC;NE<T>^4_U=I/YN:=PMG3ORG>KO(O5W<';D.]7?1>KO8(Y\
-MI_J[2/T=S)'O5'\7J;^[GJ/[[T+U=Y'ZN[=M[FV?(]^I_BY2?_>V<?=VY8[N
-MOPO5WT7J[]XV[MZNW-']=Z'ZNTC]W=O&W=N5.[K_+E1_%ZF_@[,CWZG^+E)_
-M!W/D.]7?1>KO8(Y\I_J[2/T=S)'O5'\7J;][U^;>]3GRG>KO(O5W[QIW[SIW
-MY#O5WT7J[]XU[MYU[LAWJK^+U-^]:]R]Z]R1[U1_%ZF_@[,CWZG^+E)_!W/D
-M.]7?1>KO8(Y\I_J[2/W=]1S=?Q>JOXO4W[UO<^_['/E.]7>1^KOWC;OW*W=T
-M_UVH_BY2?_>^<?=^Y8[NOPO5WT7J[]XW[MZOW-']=Z'ZNTC]'9P=^4[U=Y'Z
-M.Y@CWZG^+E)_!W/D.]7?1>KO8(Y\I_J[2/W=AS;WH<^1[U1_%ZF_^]"X^]"Y
-M(]^I_BY2?_>A<?>A<T>^4_U=I/[N0^/N0^>.?*?ZNTC]'9P=^4[U=Y'Z.Y@C
-MWZG^+E)_!W/D.]7?1>KOKN?H_KM0_5VD_NYCF_O8Y\AWJK^+U-]];-Q]7+FC
-M^^]"]7>1^KN/C;N/*W=T_UVH_BY2?_>Q<?=QY8[NOPO5WT7J[^#LR'>JOXO4
-MW\$<^4[U=Y'Z.Y@CWZG^+E)_!W/D.]7?1>KO/K6Y3WV.?*?ZNTC]W:?&W:?.
-M'?E.]7>1^KM/C;M/G3ORG>KO(O5WGQIWGSIWY#O5WT7J[^#LR'>JOXO4W\$<
-M^4[U=Y'Z.Y@CWZG^+E)_=S4W;.&IX>87\,(=[FZ"WL]]#GPWJ/[NVPMWN/O<
-MN/N\7>?`=X/J[X;4WWUN;^_SEW4.?#>H_FY(_=WGQMWGW]<Y\-V@^KLA]7=P
-M=O3G;:LO17_AZ^OTX^MOS[\/CM^_MH-OMGOXNW[AZS]>W_UK'?Q^-\]?&!S'
-MS?YZ\+_:!QZ_W\VS#)OC0)_K<ND_JP_\8X[^K/>_<W[#+SZ_B;[9_LX[G,Z_
-M^!W.W]_A.&V&<3/N-K/_[#O\G__X;_B2S*2#_]\'_C$'.K@[=_.&XZ+F/MV:
-MBQ^8]16[]=31^F_\;O_ZUMS'U[?^%3Z3#OK<'^(\TPORP_YB'<Q75T[>_CI_
-MO\LY-MN;_W3C=P?7K^^FOS]*_.]\W#]Y?YOKC_O]MQC3W?^]W9KSXN-N[LY]
-M_RW&K:_GG2]A<7H?K]\=_1'W?^>+<75QXD]^Y_XQ<O<[]\><_UH1+-_-\L>_
-C3O?P=_W"UR^O[_[U8W!H@[_L!(=ON&RWO_T?@O'+%J.H````
+M'XL("&/N+50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G%C;W<N;W5T`*V=VXX4
+M67-&[^<IBC,TIXJ(S*I,#MW(DBWY#E_8OOWK>#T/@/SLAF9W[NZH]4TP&A@T
+M`A7Y*2MK]0+-+&W6ZY_?5JO15L-F-<RK\W[U_>?MNZWN_>3A]]6W__J/_WQW
+M_]NW/WZ.V?HOKDH_WYZ6N0=;_]?G_,=5A]5Z_H6Y[]^-YN[=7?R-N[OW9B_G
+MKO[X^6;Y.E>#\6!PU>;6[?Y,/+WAU^[O2WJ[]O/I_;ZWZ^+MCFIP\V#P:YO[
+M5[L__UNP_-+]_<W/=XN#?R[W-^!5DYJ;_Y(^7X]XU4[-[8NY#5YU4'/'8FZ+
+M5YW4W+F8F^`J4Q^%%5^YOI[Q*O&%9L47FJ]W>)7X0K,[PM,7VM=E;H]7;=3<
+M0^[^=<'=`:\2W%G)W1&O$MQ9R=T)KQ+<6<G=&:\2W%G%G=%5KKCSBCLC1;GB
+MSBONC(SLBCNON#/RG2ONO.+.R'>NN/.*.R/?N>+.*^Z,?.>*.Z^X,_*=*^Z\
+MY(Y\%XJ[*+DCWX7B+DKNR'>AN(N2._)=*.ZBY(Y\%XJ[*+DCWX7B+DKNR'>A
+MN(N2._)=*.ZBXL[IJD%Q-U3<.?EN4-P-%7=.OAL4=T/%G9/O!L7=4''GY+M!
+M<3=4W#GY;E#<#15W3KX;%'=#Q9V3[P;%W5!R1[X;%7=CR1WY;E3<C25WY+M1
+M<3>6W)'O1L7=6')'OAL5=V/)'?EN5-R-)7?DNU%Q-Y;<D>]&Q=U8<1=TU49Q
+MMZFX"_+=1G&WJ;@+\MU&<;>IN`ORW49QMZFX"_+=1G&WJ;@+\MU&<;>IN`OR
+MW49QMZFX"_+=1G&W*;DCWVT5=]N2._+=5G&W+;DCWVT5=]N2._+=5G&W+;DC
+MWVT5=]N2._+=5G&W+;DCWVT5=]N2._+=5G&WK;@;Z*I)<3=5W`WDNTEQ-U7<
+M#>2[27$W5=P-Y+M)<3=5W`WDNTEQ-U7<#>2[27$W5=P-Y+M)<3=5W`WDNTEQ
+M-Y7<D>_N_BL\O%!Q1[Z;%7=SR1WY;E;<S25WY+M9<3>7W)'O9L7=7')'OIL5
+M=W/)'?EN5MS-)7?DNUEQ-U?<C7353G&WJ[@;R7<[Q=VNXFXDW^T4=[N*NY%\
+MMU/<[2KN1O+=3G&WJ[@;R7<[Q=VNXFXDW^T4=[N*NY%\MU/<[4KNR'=W_S<4
+M7JBX(]_M%7?[DCORW5YQMR^Y(]_M%7?[DCORW5YQMR^Y(]_M%7?[DCORW5YQ
+MMR^Y(]_M%7?[BKL-7750W!TJ[C;DNX/B[E!QMR'?'11WAXJ[#?GNH+@[5-QM
+MR'<'Q=VAXFY#OCLH[@X5=QORW4%Q=ZBXVY#O#HJ[0\D=^>ZHN#N6W)'OCHJ[
+M8\D=^>ZHN#N6W)'OCHJ[8\D=^>ZHN#N6W)'OCHJ[8\D=^>ZHN#N6W)'OCHJ[
+M8\7=EJY:.J#+%PKNMN2[D^+N5'&W)=^=%'>GBKLM^>ZDN#M5W&W)=R?%W:GB
+M;DN^.RGN3A5W6_+=27%WJKC;DN].BKM3R1WY[JRX.Y?<D>_.BKMSR1WY[JRX
+M.Y?<D>_.BKMSR1WY[JRX.Y?<D>_.BKMSR1WY[JRX.Y?<D>_.BKMSQ=T$5]G=
+M#^"%@KL)?&<J.+0J./0)?&<J.+1UQ=T$OK.UX,YR?W?!W02^,]7?6=G?3>`[
+M4_V=E?W=!+XSU=]9V=]-X#M3_9V5_=T$OC/5WUG9WTW@.U/]G97]W02^,]7?
+M6=G?3>`[4_V=E?W=!+XSU=]9V=]-X#M3_9V5_=T$OC/5WUG9WTW@.U/]G97]
+MW4Q7J?[.ROYN)M^I_L[*_FXFWZG^SLK^;B;?J?[.ROYN)M^I_L[*_FXFWZG^
+MSLK^;B;?J?[.ROYN)M^I_L[*_FXFWZG^SLK^;B;?J?[.ROYN)M^I_L[*_FXF
+MWZG^SLK^;B;?J?[.ROYN)M^I_L[*_FXFWZG^SLK^;B;?J?[.ROYN1U>I_L[*
+M_FY'OE/]G97]W8Y\I_H[*_N['?E.]7=6]G<[\IWJ[ZSL[W;D.]7?6=G?[<AW
+MJK^SLK_;D>]4?V=E?[<CWZG^SLK^;D>^4_V=E?W=CGRG^CLK^[L=^4[U=U;V
+M=SORG>KOK.SO=N0[U=]9V=_MR'>JO[.RO]N1[U1_9V5_MZ>K5']G97^W)]^I
+M_L[*_FY/OE/]G97]W9Y\I_H[*_N[/?E.]7=6]G=[\IWJ[ZSL[_;D.]7?6=G?
+M[<EWJK^SLK_;D^]4?V=E?[<GWZG^SLK^;D^^4_V=E?W=GGRG^CLK^[L]^4[U
+M=U;V=WORG>KOK.SO]N0[U=]9V=_MR7>JO[.ROSO05:J_L[*_.Y#O5']G97]W
+M(-^I_L[*_NY`OE/]G97]W8%\I_H[*_N[`_E.]7=6]G<'\IWJ[ZSL[P[D.]7?
+M6=G?'<AWJK^SLK\[D.]4?V=E?W<@WZG^SLK^[D"^4_V=E?W=@7RG^CLK^[L#
+M^4[U=U;V=P?RG>KOK.SO#N0[U=]9V=\=Z2K5WUG9WQW)=ZJ_L[*_.Y+O5']G
+M97]W)-^I_L[*_NY(OE/]G97]W9%\I_H[*_N[(_E.]7=6]G='\IWJ[ZSL[X[D
+M.]7?6=G?'<EWJK^SLK\[DN]4?V=E?W<DWZG^SLK^[DB^4_V=E?W=D7RG^CLK
+M^[LC^4[U=U;V=T?RG>KOK.SO3G25ZN^L[.].Y#O5WUG9WYW(=ZJ_L[*_.Y'O
+M5']G97]W(M^I_L[*_NY$OE/]G97]W8E\I_H[*_N[$_E.]7=6]G<G\IWJ[ZSL
+M[T[D.]7?6=G?G<AWJK^SLK\[D>]4?V=E?W<BWZG^SLK^[D2^4_V=E?W=B7RG
+M^CLK^[L3^4[U=U;V=V>Z2O5W5O9W9_*=ZN^L[._.Y#O5WUG9WYW)=ZJ_L[*_
+M.Y/O5']G97]W)M^I_L[*_NY,OE/]G97]W9E\I_H[*_N[,_E.]7=6]G=G\IWJ
+M[ZSL[\[D.]7?6=G?G<EWJK^SLK\[D^]4?V=E?W<FWZG^SLK^[DR^4_V=E?W=
+MF7RG^CNK^KM8PU5^]P-XX0%W=YRL^ASXSE5_YZF_6[6]U7J9`]^YZN\\]7>K
+MQMWJZS('OG/5WWGJ[U:-N]6?RQSXSE5_YZF_@V<'OG/5WWGJ[V`.?.>JO_/4
+MW\$<^,Y5?^>IOX,Y\)VK_LY3?_>HS3WJ<^`[5_V=I_[N4;N]1YT[\)VK_LY3
+M?_>H<?>H<P>^<]7?>>KO'C7N'G7NP'>N^CM/_1T\._"=J_[.4W\'<^`[5_V=
+MI_X.YL!WKOH[3_W=Y1R=?^>JO_/4WSUN<X_['/E.]7>>^KO'C;O'"W=T_IVK
+M_LY3?_>X<?=XX8[.OW/5WWGJ[QXW[AXOW-'Y=Z[Z.T_]'3P[\IWJ[SSU=S!'
+MOE/]G:?^#N;(=ZJ_\]3?P1SY3O5WGOJ[)VWN29\CWZG^SE-_]Z1Q]Z1S1[Y3
+M_9VG_NY)X^Y)YXY\I_H[3_W=D\;=D\X=^4[U=Y[Z.WAVY#O5WWGJ[V".?*?Z
+M.T_]'<R1[U1_YZF_NYRC\^]<]7>>^KNG;>YIGR/?J?[.4W_WM''W=.&.SK]S
+MU=]YZN^>-NZ>+MS1^7>N^CM/_=W3QMW3A3LZ_\Y5?^>IOX-G1[Y3_9VG_@[F
+MR'>JO_/4W\$<^4[U=Y[Z.Y@CWZG^SE-_]ZS-/>MSY#O5WWGJ[YXU[IYU[LAW
+MJK_SU-\]:]P]Z]R1[U1_YZF_>]:X>]:Y(]^I_LY3?P?/CGRG^CM/_1W,D>]4
+M?^>IOX,Y\IWJ[SSU=Y=S=/Z=J_[.4W_WO,T][W/D.]7?>>KOGC?NGB_<T?EW
+MKOH[3_W=\\;=\X4[.O_.57_GJ;][WKA[OG!'Y]^YZN\\]7?P[,AWJK_SU-_!
+M'/E.]7>>^CN8(]^I_LY3?P=SY#O5WWGJ[UZTN1=]CGRG^CM/_=V+QMV+SAWY
+M3O5WGOJ[%XV[%YT[\IWJ[SSU=R\:=R\Z=^0[U=]YZN_@V9'O5'_GJ;^#.?*=
+MZN\\]7<P1[Y3_9VG_NYRCLZ_<]7?>>KO7K:YEWV.?*?Z.T_]W<O&W<N%.SK_
+MSE5_YZF_>]FX>[EP1^??N>KO//5W+QMW+Q?NZ/P[5_V=I_X.GAWY3O5WGOH[
+MF"/?J?[.4W\'<^0[U=]YZN]@CGRG^CM/_=VK-O>JSY'O5'_GJ;][U;A[U;DC
+MWZG^SE-_]ZIQ]ZIS1[Y3_9VG_NY5X^Y5YXY\I_H[3_T=/#ORG>KO//5W,$>^
+M4_V=I_X.YLAWJK_SU-]=SM'Y=Z[Z.T_]W56;N^ISY#O5WWGJ[ZX:=U<+=W3^
+MG:O^SE-_=]6XNUJXH_/O7/5WGOJ[J\;=U<(=G7_GJK_SU-_!LR/?J?[.4W\'
+M<^0[U=]YZN]@CGRG^CM/_1W,D>]4?^>IOWO=YE[W.?*=ZN\\]7>O&W>O.W?D
+M.]7?>>KO7C?N7G?NR'>JO_/4W[UNW+WNW)'O5'_GJ;^#9T>^4_V=I_X.YLAW
+MJK_SU-_!'/E.]7>>^KO+.3K_SE5_YZF_>]/FWO0Y\IWJ[SSU=V\:=V\6[NC\
+M.U?]G:?^[DWC[LW"'9U_YZJ_\]3?O6G<O5FXH_/O7/5WGOH[>';D.]7?>>KO
+M8(Y\I_H[3_T=S)'O5'_GJ;^#.?*=ZN\\]7=OV]S;/D>^4_V=I_[N;>/N;>>.
+M?*?Z.T_]W=O&W=O.'?E.]7>>^KNWC;NWG3ORG>KO//5W\.S(=ZJ_\]3?P1SY
+M3O5WGOH[F"/?J?[.4W]W.4?GW[GJ[[SJ[X+.OW/5WWG5WP6=?^>JO_.JOPLZ
+M_\Y5?^=5?Q=T_IVK_LZK_B[H_#M7_9U7_5W0^7>N^CNO^KN@\^]<]7=>]7=!
+MY]^YZN\\]7?OV];[/D>^4_V=I_[N?>/N?>>.?*?Z.T_]W?O&W?O.'?E.]7>>
+M^KOWC;OWG3ORG>KO//5W\.S(=ZJ_\]3?P1SY3O5WGOH[F"/?J?[.4W]W.4?G
+MW\7=#^"%!]RMV]RZSX'OOE_%W$7J[]:-N_7"'9U_%ZJ_B]3?K1MWZX4[.O\N
+M5'\7J;];-^[6"W=T_EVH_BY2?P?/#GP7JK^+U-_!'/@N5'\7J;^#.?!=J/XN
+M4G\'<^"[4/U=I/[.VISU.?!=J/XN4G]GC3OKW('O0O5WD?H[:]Q9YPY\%ZJ_
+MB]3?6>/..G?@NU#]7:3^#IX=^"Y4?Q>IOX,Y\%VH_BY2?P=SX+M0_5VD_NYR
+MCLZ_"]7?1>KOO,UYGR/?J?XN4G_GC3M?N*/S[T+U=Y'Z.V_<^<(=G7\7JK^+
+MU-]YX\X7[NC\NU#]7:3^#IX=^4[U=Y'Z.Y@CWZG^+E)_!W/D.]7?1>KO8(Y\
+MI_J[2/U=M+GH<^0[U=]%ZN^B<1>=._*=ZN\B]7?1N(O.'?E.]7>1^KMHW$7G
+MCGRG^KM(_1T\._*=ZN\B]7<P1[Y3_5VD_@[FR'>JOXO4WUW.T?EWH?J[2/W=
+MT.:&/D>^4_U=I/YN:-P-"W=T_EVH_BY2?S<T[H:%.SK_+E1_%ZF_&QIWP\(=
+MG7\7JK^+U-_!LR/?J?XN4G\'<^0[U=]%ZN]@CGRG^KM(_1W,D>]4?Q>IOQO;
+MW-CGR'>JOXO4WXV-N[%S1[Y3_5VD_FYLW(V=._*=ZN\B]7=CXV[LW)'O5'\7
+MJ;^#9T>^4_U=I/X.YLAWJK^+U-_!'/E.]7>1^KO+.3K_+E1_%ZF_V[2Y39\C
+MWZG^+E)_MVG<;1;NZ/R[4/U=I/YNT[C;+-S1^7>A^KM(_=VF<;=9N*/S[T+U
+M=Y'Z.WAVY#O5WT7J[V".?*?ZNTC]'<R1[U1_%ZF_@SGRG>KO(O5WVS:W[7/D
+M.]7?1>KOMHV[;>>.?*?ZNTC]W;9QM^W<D>]4?Q>IO]LV[K:=._*=ZN\B]7?P
+M[,AWJK^+U-_!'/E.]7>1^CN8(]^I_BY2?W<Y1^??A>KO(O5W4YN;^ASY3O5W
+MD?J[J7$W+=S1^7>A^KM(_=W4N)L6[NC\NU#]7:3^;FK<30MW=/Y=J/XN4G\'
+MSXY\I_J[2/T=S)'O5'\7J;^#.?*=ZN\B]7<P1[Y3_5VD_FYN<W.?(]^I_BY2
+M?S<W[N;.'?E.]7>1^KNY<3=W[LAWJK^+U-_-C;NY<T>^4_U=I/X.GAWY3O5W
+MD?H[F"/?J?XN4G\'<^0[U=]%ZN\NY^C\NU#]7:3^[D.;^]#GR'>JOXO4WWUH
+MW'U8N*/S[T+U=Y'ZNP^-NP\+=W3^7:C^+E)_]Z%Q]V'ACLZ_"]7?1>KOX-F1
+M[U1_%ZF_@SGRG>KO(O5W,$>^4_U=I/X.YLAWJK^+U-]];',?^QSY3O5WD?J[
+MCXV[CYT[\IWJ[R+U=Q\;=Q\[=^0[U=]%ZN\^-NX^=N[(=ZJ_B]3?P;,CWZG^
+M+E)_!W/D.]7?1>KO8(Y\I_J[2/W=Y1R=?Q>JOXO4WWUJ<Y_Z'/E.]7>1^KM/
+MC;M/"W=T_EVH_BY2?_>I<?=IX8[.OPO5WT7J[SXU[CXMW-'Y=Z'ZNTC]'3P[
+M\IWJ[R+U=S!'OE/]7:3^#N;(=ZJ_B]3?P1SY3O5WD?J[SVWN<Y\CWZG^+E)_
+M][EQ][ES1[Y3_5VD_NYSX^YSYXY\I_J[2/W=Y\;=Y\X=^4[U=Y'Z.WAVY#O5
+MWT7J[V".?*?ZNTC]'<R1[U1_%ZF_NYRC\^]"]7>1^KOK-G?=Y\AWJK^+U-]=
+M-^ZN%^[H_+M0_5VD_NZZ<7>]<$?GWX7J[R+U=]>-N^N%.SK_+E1_%ZF_@V='
+MOE/]7:3^#N;(=ZJ_B]3?P1SY3O5WD?H[F"/?J?XN4G]WT^9N^ASY3O5WD?J[
+MF\;=3>>.?*?ZNTC]W4WC[J9S1[Y3_5VD_NZF<7?3N2/?J?XN4G\'SXY\I_J[
+M2/T=S)'O5'\7J;^#.?*=ZN\B]7<7<\,:KAKN?@`O/.#N+NC]TN?`=X/J[[Z_
+M\("[+XV[+^ME#GPWJ/YN2/W=EW9[7[XN<^"[0?5W0^KOOC3NOORYS('O!M7?
+M#:F_@V='?]^V^BCZ"]_>I6_?_KBZ'1QO/]O!5^L=_%N_\.W?WCW\9QF\/9OG
+M;PR.XVIW.?C?[0V/MV?SS,/J,-#[:O8S_89OEC?\<X[^KO=_\OR&W_S\MO3%
+M]D_N<'OZS7<XW=[AN%T-XVK<K";_U3O\WW__GW2'/^=^VT?R<PYT\'#N[H:7
+MWSHOYF[NS?W0P?G>K[P/V^I@_0]^]W]\;^[ZW;W?PB?209_[(<X3O2#?[&_6
+MP71QY.3]S_GV+.=8K>_^UXT_'%P^WU6_/TK\'[S=O[B_U>7;O?TCQO;AK[=[
+M<UZ\W=7#N=L_8MS[/!]\A,73N[Z\._HK[O_)AW%Q<.(O?N7^&'GXE?MSSG^O
+J".9;L_SX[70'_]8O?/OZ[N$_/P>'-OC;GN#P'9?U^H__!PSBQAVCJ```
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu
index 4d325d8..be431e6 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu
@@ -1,22 +1,22 @@
# $FreeBSD$
begin 644 img-63x255-4096-pc98.qcow2.gz
-M'XL(",([(U0``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G%C;W<R+F]U=`"MF-N2
-MTS`,0-_[%>8."Y18LG/ATET6EAG>X`%X;KO-5W3X=NK:C1)%BKLE;2;3CD=G
-M9/M8L5,4\6.,M\:5QC6FW9C#_W2!Z?T97F;_\]OW9?^S7T28+90HH:':=;@!
-MZR_A0,,5=MQ@95PO.Q1P<(H:@W(XIV8WU2#@KA;'H3M.1LTB\!)@Q*F3<5%^
-M$//C$>["_&#N_%`>/W^*XPWE='X8\^-1E8:KLS@0HAH-M\[B4(C::+AM%N>$
-MJ'L-IZS<'LX+4:V"LQE5#KA2B+(:#K*X2HA"#>>RN%J(TKRS>>\:(4KSSN:]
-M6PM1FG<V[]U&B-*\LWGOMD*4YIW->W<O1&G>@>*=(=Q.B-*\`^;=HX1[3+A6
-MB-*\`^;=DX1[VN&L%*5Y!\R[9PGWG'!"O0/-.V#>O4BXEX03ZAUHW@'S[E7"
-M71%.J'>@>0?,N]<)]X9P0KT#S3M@WKT=>6>%>@>:=\B\>Y=8!>&$>H>:=\B\
-MLPD'A!/J'6K>(?,.$\X13JAWJ'F'S#N?<"7AA'J'FG?(O*L2KB:<4.]0\PZ9
-M=TW"O2><4.]0\PZ9=Q\2[B/AA'J'FG?(O/N4<"O""?4.->\<\^XZX6X()]0[
-MIWGGF'>?$^Z6<$*]<YIWCGGW)>&^=CB0HCKOBD*^$NYNM&9AWOVGH_VQ%>YZ
-MPP2P?@AP*L.(:V;ML(\=#AJLA;O>L+]=#K\=\"C,`X#>F_48^"MVV$=A&F>V
-M3NI7V])UQOCYN87Q84IF'3\03VC_D6&UFSG#.KYPJ,*Z]:6IX=P,_]S]%J:D
-MGN\,&7'Z"X?4<$H86PUWW<-AU(PHO95JMI8*?/]W#[=:4K$_X"9?.(13U$YJ
-M4#OKYY6E[LK5Z>K/<]B\AS/6Z?G--M_=_!K*3RA7,.CN1'YFW-VP+^C.[VP^
-M`@XRW35#7-@7].=S,(69T5N-L]O./!F6KXPS5VZ`#%=NQ,&\A:`Y5I:#@:&*
-=C^YZP_['<OB-0)>`LXV@*\/3;?$/F4FZ`B45````
+M'XL("&/N+50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G%C;W<R+F]U=`"MF-MR
+MTS`00-_S%>(.!8*U*_G")2F%,L,;/`#/B9M\189O)XH42U[O6FU0XO$TH^Z9
+ME?9H(Z>J_$LIJY6IE>G4?JN.G\,%*ODPOM3AY[?OR_1U6'B8KH0H9J#9#;@1
+MZV_$@82K]'1`\[@D.V1P<(Z:@G(X(V8W-\#@KA:GI3L5HR41>`G0X\1B7)0?
+M^/QHA+DP/RB='_+K9\]Q=*">SP]]?C2JD7!M%@=,5"?A-ED<,E%;"==G<8:)
+MNI-PPLY-<):)V@LXG5'EB*N9*"WA((MKF"B4<":+:YDHR3N=]ZYCHB3O=-Z[
+M#1,E>:?SWFV9*,D[G?>N9Z(D[W3>NSLF2O(.!.]4Q.V8*,D[(-X]"KC'$;=G
+MHB3O@'CW).">#CC-14G>`?'N6<`]CSBFWX'D'1#O7@3<RXAC^AU(W@'Q[E7`
+M744<T^]`\@Z(=Z\#[DW$,?T.).^`>/=VXIUF^AU(WB'Q[EU@51'']#N4O$/B
+MG0XXB#BFWZ'D'1+O,.!,Q#']#B7OD'AG`ZZ..*;?H>0=$N^:@&LCCNEW*'F'
+MQ+LNX-Y''-/O4/(.B7<?`NYCQ#']#B7OD'CW*>!6$<?T.Y2\,\2[=<!=1QS3
+M[XSDG2'>?0ZXFXAC^IV1O#/$NR\!]W7``1<U>%=5_!5PMY,]"V7/GR:>CS5S
+MEP=F@.U#@',9>EQ7=,+63]AIL&'N\L#A9CE^#\"3,`\`6JLV4^`O/V'KA>F,
+MZ@TWK[!/M#SA=;I^MK0PUI6DZ/H!^X3V'QDVN\(9MOX'A\;M6UNK%NZ;X9_;
+MWU.EC[AB)?$X^0>','!.>&BR$]PZP;DSRS[YSU0VU>O8X-._$]QJ&9O]$3?[
+M@X-[BMIQ`^)D;5E9VJ%=G:^TSN[P[IZQSM_?Y/`]U%?%_)AV!:/ISN2GIM-U
+MYX+A^9W4P^$@,UTUQKES05K/40DSJ[>:9M<7+H:F.^.>.]=!QCO7XZ!L(^A.
+CG>5HH.OBD[L\</BQ'+\]T`1@L14TM?MV6_P#%UJW"245````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu
index 7869940..3e69394 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu
@@ -1,12 +1,12 @@
# $FreeBSD$
begin 644 img-63x255-4096-pc98.raw.gz
-M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G)A=RYO=70`K93-CH0@
-M#,?O/D7/>S"EPHH7)YED[W.9W;-K]"E\^`7!E8KXD0!(,(5?_FVAB*X!2`+L
-M=N:T87J6O$_%1S'3Q'@/J!1T,?!M@#..K+Y&0B_!K#8#QG$=S#"5F[;@A#'&
-M('\J:=C!>7=EYO@1'@JYK[`>,BO4LT)5@U2@/D'3584_7]\[*=&8+24.1V>X
-M17`UIG"/`%>Y:[921'"J%U`-_B=<![C6?0M.'JDSD<!ASY!T5N6]+-IT?B[,
-M,X@!1`6HO8TX\#^_L.IK8AG$W#W0![&[G<75?+\(<'3B+G#<K\4%^60I/(E>
-M&ZOK,R=#;%_&Q9=K(?SE.ASE+03-7%G,#;15/)K3ANE5\NZ`T@.S1=!6/L3B
-)#]P1(I+G!@``
+M'XL("&3N+50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G)A=RYO=70`K91-CX,@
+M$(;O_HKWO`<#(U2]M$F3WO>RNV=K]%?XXY<O+2-^M`F@B!EX\@XSC!"^`8H@
+MNHUQWS#=2]ZGXJMP-#E^!M0:70K\,4"'(ZNO5>@5S&SUH!K=3":&J0SM%KXS
+M3AIC"@J[=@T+KEQPP5V5^?Q('`KY7&$]9%;8.(6ZAM+0%S3TKL*_Q^]*H<=E
+M"XG'T1EN%AR29P-WBW"5,8[1RCC9T$M40_B)YQ'NZM\9IX[4F9,0PY9AUUF=
+M-UD:T_F^.,Z0`V0%T00;<>`27[STM:D,8NX>Z$/J;F=Q-5\O(QR=N`N.>UI<
+M%$\6PI/3NZ;J^LS!D.N;\>;-M1!^<SV.\A:"UE46DX&VBB?COF'Z+GGW0!6`
+0V4[05CXABG]2`B^9YP8`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
index 8582877..056cb49 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-4096-pc98.vhd.gz
-M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9"YO=70`K9=-;^,@
-M$(;O^14C[:T'"X\!DTLK5=N>*U7MGHG7KGKH;M7LH0?_^#(&DL%?2;;$#L("
-M'M[Y`(00_@>@*]`=Z!:THGHM06^A-@"N,;PXE&7XA+[Y^Z=M_KU^%N'7;SRL
-M%'Q4.IS&8P7235(#6II$_Z8Z]!%3_+A[N7I]>XDX#+@XL=0@$92#R,D\1AS4
-M$>G^]O'G6%TU57<<Y>?I.J@ZUJ/BZHKBAN.D&^7ZTZNADX/,^"8?20/')>J4
-M&(UB,N><RHR=P^FU49?@KC8A%CY57&+4KA2@2ZB1ZBYMHA\FKTN5S_V[_=BW
-M(WVXD"J:!6/<)I?-Q9`J&#L'!9($KID+`V4_QLVDRK>\I]-Q,E2<$X2*#3B8
-MGWKOB`*N3Y=BQ>?+P5C49TF?6UO"SI3+#?UMD3X'X*Z[#*@4V"GP*1K<D+ZM
-MA$;.^9T;>=;J:!:R[[_CVV;V']I5(9<K-":S0C,H5#5MZ$J#P7,5_KI[G@F)
-ML=E"XG%X"A<%\_T^Q=TP7.73[$AAVQ,T)51M^.!UAKOV_XB3:^IH5VCG&A:-
-M59F3Q9K1.!YG*%LH*Q`FM&$*/,07COJV4QF8F+NB#Z;F6L+5:?^2X?"$N9#B
-M=N'DC3V3$)[PWO5479,Y&+OQRCASY1(D7;D>AWDW`COL+"X#:1>?E,L-_4.1
-M/AZ(X3#*=KIA.#VR*90!F$VA#.='1H6V64VV2[-0!X69K@J$RWA5(%S&JP+A
-?,EX5")?QJD"XC%<%PF6]*FAW"11B\P51KS:'7PX`````
+M'XL("&3N+50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9"YO=70`K9=-3^P@
+M%(;W\RM.XLY%0T^!,ALG,>K:Q.A=,[VM<7'5."Y<],?+*3"%TG8<+],.H0$>
+MWO,!!,;L#T!6(#N0+4A!]9J#W$*M`$RC>W$H2_<)??/VVC:?+U^%^_4;"RM9
+M."H>3N.Q`FXFJ0$U32+_4AUZCRDN;I\O7_X]>QPZG)^82^`(PD!X,H]B1W5$
+MNKM^N)FJJU)UXR@[3]=!U04]JE!=4>Q"'#>C3']Z)71\D.G?Z"-J"'&1.L$F
+MHP*9<TX-C)W#R;51Y^`N-RX6-E5,8M2F9"!+J)'J)FV\'Y+7I,K7X5U_'-J)
+M/EQ(%1D$8]K&E\U%ERKH.SL%G`2NF0L#Y3#%S:3*?WE/QN.XJQ@G,.$;<#`_
+M]MZ(@E"?+-F*SY>#L:A/DSZSMIB>*9<;^NLB?H[`?7<>4`C0*?#1&]R0OBV'
+MAL_YW2W9)&-&@W=Q?)N%[/MU?-O,_D.]*N1\A4IE5J@&A:*F#5U(4/A3A7]N
+MGV96L-+90F)Q>`KG!8?[?8S;!;C*+KB1$B0;-"54K?L(ZP'NROX]CJ^IHUVA
+MG6M8-%9D3A:M)N/".$/90ED!4ZX-8^`QOC#JVZ8R,#)W11^DYFK"U7'_,L#A
+M"7,AQNW=R>M[1B$\X;VK5%V3.1C[Z<KXX<HE2+QR+0[S;@1ZV%E,!M(NGI3+
+M#?U]$3\6B.XPRG:ZH3L]LBGD#IA-(7?G1T:%NEE-MG.S4#J%F:X*A,MX52!<
+CQJL"X3)>%0B7\:I`N(Q7!<)EO2I(<PED;/,-H6X,)U\.````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu
index bfbd1f1..8662222 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu
@@ -1,15 +1,15 @@
# $FreeBSD$
begin 644 img-63x255-4096-pc98.vhdf.gz
-M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9&8N;W5T`*V5/6^#
-M,!"&]_R*D[IEB/R-61(I:CI7JMK.E)HH0]NE0P=^?'T8@@]#DE;&!AD=?GCO
-MSCXS%BX`)8!5,\]E0[O?T-:NUJN.QIN_`;6&*@4^>V"'$ZBO5%`K\*-)AZ89
-M.S&TF\DUX+@WIJ!^UJ)A!M>[JS+'3["+0OZNL'"9%=I.H2Y`:=`&K+A5X>OA
-M928EEF5+2<"):[A!L&R6<+L()\,R&RD\FE5SD*Y_B<<1;AON`:<NJ?.18&[.
-ML.BLSKM8K&]T7IQGX`ZX!&9[FZ#`<WYAU%>F,@1Q]X(^2-VM$%?0[WF$$U?<
-M!8I[0UR43Y+"*]';INKJS,G@TYUQX\Y%"-VY`2?R%H*RJRQ^!6(53Y[+AO9Q
-M0UL`JAZ8+8*V/]V,!-.`<6`TC@L%IH3"QD!!5U);?WVZ^OOT$V<8<7QRYL0=
-MYPN)N\44("K\B7G'<:3O[G!<GSZ.`VXH5<./E<&@:P]1B;N6NONP?[J?JI-I
-MD"R)'D>=<=GSCI/H[6*<.COK7%<"^=C)"S',EBK$:3:9]=_<!IS)O%3\P;OZ
-)!3S1^)L2"0``
+M'XL("&3N+50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9&8N;W5T`*V5.V^#
+M,!#']WR*D[IE0'YCED2*FLZ5JK8SI2;*D';IT($/7QL;XL.01V5,B-'A'_][
+M^"#$'P""`:EGKLN&;E?@T:W6JYY&V_N`4D*=`E\ML,<QIZ\2T`BPL\D)O.UG
+M-#%T13BVX7_`46M,06'5HF'$%2,NN"LRQX^1BT+N5UB:S`IUKU"6("1(!9K=
+MJO!]_S91Z''94N)Q[!IN$!R*9P:WC7#<&MOHR;C8H*'`3;B)YQ%NXW\#3EQ2
+M9R-!S)QAT5F9MUBT'7A=G&>@!B@'HH.-8>"87SCKJU(9#+E[01^D[M8.5^+G
+M:81C5]P%C/MPN"B?*(57HK=)U369DT&G.^/&G>L@>.=Z',O;"*J^L]@*=%T\
+MN2X;NN<"#P\4`9@M@CI\W10'U8(RH*2;EP)4!:6.@0Q74M=\?YGFY_@;9]CA
+MJ&\&LZ=;S[C;+:H$5KN7J$\WC_0][`_KX^DPX(96-;Q8*!=T:2$B<5=C=Y]V
+M+X]3=3P-DD;1HTYGW/:LXRAZVQ@G1F>-Z5L@/9_H!AEF6Y7#23)9]=_<>IS*
+/7"KVP[OZ`WO*69D2"0``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu
index 9036f37..c3521af 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu
@@ -1,84 +1,84 @@
# $FreeBSD$
begin 644 img-63x255-4096-pc98.vmdk.gz
-M'XL("`;&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9M9&LN;W5T`*U<78_<
-MQA%\]Z\8G-_RL&`MOY8/<A)'#A`$`0S;L5]#+LGX$%L23H<@`O;'AT-.S16Y
+M'XL("&7N+50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9M9&LN;W5T`*U<78_<
+MQA%\]Z\8G-_RL&`MOY8/LA-'#A`$`8S8L5]#+LGX$%L23H<@`O;'AT-.S16Y
MI$C[^K0GL,7NVNZ>W;Y3=6&39/IR+FM<EKFL=7GA$KCAGZ:'2](78WAD\<;M
-M[V__\>.)7W\ZG6Y?3&#P41*"1.'$F#W/[;3X(MSY<U&S&\/CO`N7^JCF+C#`
+M;V___N.)7W\\G6Y?3&#P41*"1.'$F#W/[;3X(MSY<U&S&\/CO`N7^JCF+C#`
MG3=N;,(-_7#GM1!F5X^W6W\A<"X"N1E<OE+39K&?R^X/7X3F^?Q2G\-PO$7E
MRM0533!=D8]VZLKS>"]QY>#4#X!?NK>/'__CWG8?KT^/'Y[?A_S._FP'YZSP
-M_L75(PR%E86_\#<\7.4ABLZEK4OA;[O;TU\??^E._^V>/CZ^?_<&+/?LSS9+
-M75;Y=+Q_\O*8&?Y)$E?`/X>[_>5O;]^$5VYR^E`_$<Y'#8D,SSW4H;A%X?SW
+M_L75(PR%E86_\#<\7.4ABLZEK4OA;[O;TU\>?^E._^V>/CZ^?_<&+/?LSS9+
+M75;Y=+Q_\O*8&?Y)$E?`/X>[_?FO;]^$5VYR^E`_$<Y'#8D,SSW4H;A%X?SW
M_6/,KGOW[!'[\!6S\V<;FI./SYWYBSQS9>7&='*/?1YNMZ'DL7?7IZY^[G[X
M]*%[\_#K^W>Q=_YL?<NJ$>@R-BIU>>JA0FF^?;E']"^;\=3<[9?'YY\?K]\/
-M97[L'DY?.L(5OG?#`5Y"7E/50TBQ>;)#VK=O_O<\U.O:<+*/A!N3&(L8GCL_
-MN[ST6,,!ID/OTM2E%Y>.\$/"0R49O).[O7]W^NXGAR*]9.[[;__\'>$N`]S@
-M.20XA`P%S6K*I_KSY<O2W;[_QCWX(G_XN1M?@82KIK>9=Y[.`:-Y]A>A:Q.\
-M'V*9OS&>K'M;/]?NZ_IC=_KR[=NOX\G6OMAL?`RI=1ZEF*#]ZWMLY]"XZ:2G
-M@QZ/HFV;4]W6'YZ[)W^\\2@:_VIM0Z7^6+.78YP_3SF>5.]?,>[VQCT\ML.9
-M>MA_=^]_)=QU>AD/>?B71#4&IOYB>/6,\%UXAND5XX_)PW7/3Y].UT^_/+YK
-MAS>:>T.X=NK=D,YPFE-2,:=E4O%IA]X]X"6U`9MPG6_1E-0EO#$&K"F/ERZD
-MPR/WC]"%VZ?3SUW=#FFYAW.>/\2CZ)='H2U:=&$ZZ*$7TU&$Q#Z=/G;7`)<F
-MX0#[67.FG/Q+>7@E3QG-!^CS^Z<QM2)]T'F<+G^6O78>9W<_4LO?"3C!6>=7
-M)'L_S_A(9X!.P)*7_`J?7R:>N4858I0SN.&WB=.WP_>_AN\/`N=?8A?QK#2J
-M%J,YTKW"_[RXBF>K49T8_2&X++2(OZ!`KL>FTDCU1H1SB][EH7?TS#6J$*.<
-MP6WUK@B]HV>E4;48S6IVRV++T#MZMAK5B=$?@KN$WO$7,,CUV#L::;+V6]ZR
-M=U7H'3USC2K$*&=P6[VK0^_H66E4+4:SFMVRV";TCIZM1G5B](?@KJ%W'"N0
-MZ[%W-%*]L=F[-O2.GKE&%6*4,[BMWG6A=_2L-*H6HUG-;EEL'WI'SU:C.C'Z
-M(W!E$GJ72>]X/?:.1JHWMGI7<M[1,]>H0HQR!K?1NY+SCIZ51M5B-*O9+8OE
-MO*-GJU&=&/TA.,Z[7'K'Z[%W-%*]L=D[SCMZYAI5B%'.X+9ZQWE'STJC:C&:
-MU>R6Q7+>T;/5J$Z,_A`<YUTAO>/UV#L:J=[8[!WG'3USC2K$*&=P6[WCO*-G
-MI5&U&,UJ=LMB.>_HV6I4)T9_"([SCK\Z0:['WM%(]<9F[SCOZ)EK5"%&.8/;
-MZAWG'3TKC:K%:%:S6Q;+>4?/5J,Z,?HC<)<D].XBO>/UV#L:J=[8ZMV%\XZ>
-MN4858I0SN(W>73COZ%EI5"U&LYK=LEC..WJV&M6)T1^"X[RKI'>\'GM'(]4;
-MF[WCO*-GKE&%&.4,;JMWG'?TK#2J%J-9S6Y9+.<=/5N-ZL3H#\%QWO$_7I#K
-ML7<T4KVQV3O..WKF&E6(4<[@MGK'>4?/2J-J,9K5[);%<M[1L]6H3HS^$!SG
-M'5E+R/78.QJIWMCL'><=/7.-*L0H9W!;O>.\HV>E4;48S6IVRV(Y[^C9:E0G
-M1G\$KDI"[Z[2.UZ/O:.1ZHVMWE6<=_3,-:H0HYS!;?2NXKRC9Z51M1C-:G;+
-M8CGOZ-EJ5"=&?PB.\ZZ5WO&:K';L77L'M^P=YQT]<XTJQ"AG<%N]X[RC9Z51
-MM1C-:G;+8CGOZ-EJ5"=&?PB.\ZZ3WO%Z[!V-5&]L]H[SCIZY1A5BE#.XK=YQ
-MWM&STJA:C&8UNV6QG'?T;#6J$Z,_!,=YUTOO>#WVCD:J-S9[QWE'SURC"C'*
-M&=Q6[SCOZ%EI5"U&LYK=LEC..WJV&M6)T1^!JY.I=W'G!KGVO8M&JC>V>E>'
-M>1<]<XTJQ"AG<!N]J\.\BYZ51M5B-*O9+8L-\RYZMAK5B=$?@@OS#L+?0?D[
-M"'^'7?ZN#O,.PM]!^3L(?X==_JX.\P["WT'Y.PA_MY+=LM@P[R#\'92_@_!W
-M!^#"O(/P=U#^#L+?89>_J\.\@_!W4/X.PM]AE[^KP[R#\'=0_@["WZUDMRPV
-MS#L(?P?E[R#\W0&X,.\@_!V4OX/P=]CE[^HP[R#\'92_@_!WV.7OZC#O(/P=
-ME+^#\'<KV2V+#?,.PM]!^3L(?[</UR2A=\+?0?D["'^'7?ZNX;P3_@[*WT'X
-M.^SR=PWGG?!W4/X.PM^M9+<LEO-.^#LH?P?A[P[`<=X)?P?E[R#\'7;YNX;S
-M3O@[*'\'X>^PR]\UG'?"WT'Y.PA_MY+=LEC..^'OH/P=A+\[`,=Y)_P=E+^#
-M\'?8Y>\:SCOA[Z#\'82_PRY_UW#>"7\'Y>\@_-U*=LMB.>^$OX/R=Q#^[@`<
-MYYWP=U#^#L+?89>_:SCOA+^#\G<0_@Z[_%W#>2?\'92_@_!W*]DMB^6\$_X.
-MRM]!^+M]N&L2>B?\'92_@_!WV.7OKIQWPM]!^3L(?X==_N[*>2?\'92_@_!W
-M*]DMB^6\$_X.RM]!^+L#<)QWPM]!^3L(?X==_N[*>2?\'92_@_!WV.7OKIQW
-MPM]!^3L(?[>2W;)8SCOA[Z#\'82_.P#'>2?\'92_@_!WV.7OKIQWPM]!^3L(
-M?X==_N[*>2?\'92_@_!W*]DMB^6\$_X.RM]!^+L#<)QWPM]!^3L(?X==_N[*
-M>2?\'92_@_!WV.7OKIQWPM]!^3L(?[>2W;)8SCOA[Z#\'82_VX=KD]`[X>^@
-M_!V$O\,N?]=RW@E_!^7O(/P==OF[EO-.^#LH?P?A[U:R6Q;+>2?\'92_@_!W
-M!^`X[X2_@_)W$/X.N_Q=RWDG_!V4OX/P=]CE[UK..^'OH/P=A+];R6Y9+.>=
-M\'=0_@["WQV`X[P3_@[*WT'X.^SR=RWGG?!W4/X.PM]AE[]K.>^$OX/R=Q#^
-M;B6[9;&<=\+?0?D["']W`([S3O@[*'\'X>^PR]^UG'?"WT'Y.PA_AUW^KN6\
-M$_X.RM]!^+N5[);%<MX)?P?E[R#\W3Y<ETR]BQ(\R/4H8Z21ZHW;V+3AVPW?
-MB7N!"_-N5=&W\D^Q=VX]NSLM_C&X^V(GN2%&N6'<1$SE_C[`"<Y8#HE+Z/H^
-MX!$Y).*ZG(]7R2$1U^5\O$H.B;@NY^-5<DC$=;F)'!)Q76XBAT1<EYO((1'7
-MY29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1
-MU^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A
-M$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO(
-M(1'7Y29R2'!=;B.'!-?E-G)(<%UN(X<$U^4V<DAP76XCAP37Y39R2'!=;B.'
-M!-?E-G)(<%UN(X<$U^4V<DAP76XCAP37Y39R2'!=;B.'!-?E-G)(<%UN(X<$
-MU^4V<DAP76XCAP37Y39R2'!=;B.'!-?E-G)(<%UN(X<$U^4V<DAP76XCAP37
-MY39R2'!=;B.'!-?E-G)(<%UN(X<$U^4V<DAP76XCAP37Y39R2'!=;B.'!-?E
-M-G)(Q'5Y\M*[WR^'1%R7T_-5<DC$=3D]7R6'1%R7T_-5<DC$=;F)'!)Q76XB
-MAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN
-M(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=
-M;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q
-M76XBAT1<EYO((1'7Y29R2'!=;B.'!-?E-G)(=*9R2'2F<DATIG)(=*9R2'2F
-M<DATIG)(=*9R2'2F<DATIG)(=*9R2'2F<DATIG)(=*9R2'2F<DCT26(HAT1O
-M*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\J
-MAT1O*H=$;RJ'1&\JASPG26(HASPGIG+(\_U'$Q^#NR]VDAMF8[G39Y?>_[U]
-MX_;U:?XG`J+_;8!Y[NI[P'^&@K/QTX2KS%VSM;KZ_N6Q5_`$9RS7S#+C_A7)
-M9Q/Y[1F6G7&&ES'#O/0?M)L7[G(^FN%/W_RXR'"",SN2"6[W'1)YT'X+[H\"
-METXOLQ<4_2SP*US*::S7`O?5]$VX['/9Z8KJ6+'&']Y]22Z+.#UG_Y/'$X+\
-M?]YY#AC/U[WD5]VG<9Z5^YG\W'VY_J>N?GRMGL=L4&^4Z^9P_J>NGN?L"'>Z
-M]]5]=E?CP\#RG7'PG>M!YN_<">YL.PBJ<;),NH_[O[=OW+X]S?],@%D`-.M@
-/YC^:)/GB_P?]NZ=Q8```
+M97[L'DY?.L(5OG?#`5Y"7E/50TBQ>;)#VK=O__<\U.O:<+*/A!N3&(L8GCL_
+MN[ST6,,!ID/OTM2E%Y>.\$/"0R49O).[O7]W^L=/#D5ZR=SWW_WI'X2[#'"#
+MYY#@$#(4-*LIG^K/ER]+=_O^6_?@B_SAYVY\!1*NFMYFWGDZ!XSFV5^$KDWP
+M?HAE_L9XLNYM_5R[;^J/W>G+MV^_B2=;^V*S\3&DUGF48H+VK^^QG4/CII.>
+M#GH\BK9M3G5;?WCNGOSQQJ-H_*NU#97Z8\U>CG'^/.5X4KU_Q;C;&_?PV`YG
+MZF'_W;W_E7#7Z64\Y.%?$M48F/J+X=4SPG?A&:97C#\F#]<]/WTZ73_]\OBN
+M'=YH[@WAVJEW0SK#:4Y)Q9R62<6G'7KW@)?4!FS"=;Y%4U*7\,88L*8\7KJ0
+M#H_</T(7;I]./W=U.Z3E'LYY_A"/HE\>A;9HT87IH(=>3$<1$OMT^MA=`UR:
+MA`/L9\V9<O(OY>&5/&4T'Z#/[Y_&U(KT0>=QNOQ9]MIYG-W]2"U_)^`$9YU?
+MD>S]/.,CG0$Z`4M>\BM\?IEXYAI5B%'.X(;?)D[?#=__&KX_")Q_B5W$L]*H
+M6HSF2/<*__/B*IZM1G5B](?@LM`B_H("N1Z;2B/5&Q'.+7J7A][1,]>H0HQR
+M!K?5NR+TCIZ51M5B-*O9+8LM0^_HV6I4)T9_".X2>L=?P"#78^]HI,G:;WG+
+MWE6A=_3,-:H0HYS!;?6N#KVC9Z51M1C-:G;+8IO0.WJV&M6)T1^"NX;><:Q`
+MKL?>T4CUQF;OVM`[>N8:58A1SN"V>M>%WM&STJA:C&8UNV6Q?>@=/5N-ZL3H
+MC\"52>A=)KWC]=@[&JG>V.I=R7E'SURC"C'*&=Q&[TK..WI6&E6+T:QFMRR6
+M\XZ>K49U8O2'X#CO<ND=K\?>T4CUQF;O.._HF6M4(48Y@]OJ'><=/2N-JL5H
+M5K-;%LMY1\]6HSHQ^D-PG'>%]([78^]HI'ICLW><=_3,-:H0HYS!;?6.\XZ>
+ME4;58C2KV2V+Y;RC9ZM1G1C](3C.._[J!+D>>T<CU1N;O>.\HV>N4848Y0QN
+MJW><=_2L-*H6HUG-;EDLYQT]6XWJQ.B/P%V2T+N+]([78^]HI'ICJW<7SCMZ
+MYAI5B%'.X#9Z=^&\HV>E4;48S6IVRV(Y[^C9:E0G1G\(CO.NDM[Q>NP=C51O
+M;/:.\XZ>N4858I0SN*W><=[1L]*H6HQF-;MEL9QW]&PUJA.C/P3'><?_>$&N
+MQ][12/7&9N\X[^B9:U0A1CF#V^H=YQT]*XVJQ6A6LUL6RWE'SU:C.C'Z0W"<
+M=V0M(==C[VBD>F.S=YQW],PUJA"CG,%M]8[SCIZ51M5B-*O9+8OEO*-GJU&=
+M&/T1N"H)O;M*[W@]]HY&JC>V>E=QWM$SUZA"C'(&M]&[BO..GI5&U6(TJ]DM
+MB^6\HV>K49T8_2$XSKM6>L=KLMJQ=^T=W+)WG'?TS#6J$*.<P6WUCO..GI5&
+MU6(TJ]DMB^6\HV>K49T8_2$XSKM.>L?KL7<T4KVQV3O..WKF&E6(4<[@MGK'
+M>4?/2J-J,9K5[);%<M[1L]6H3HS^$!SG72^]X_78.QJIWMCL'><=/7.-*L0H
+M9W!;O>.\HV>E4;48S6IVRV(Y[^C9:E0G1G\$KDZFWL6=&^3:]RX:J=[8ZET=
+MYEWTS#6J$*.<P6WTK@[S+GI6&E6+T:QFMRPVS+OHV6I4)T9_""[,.PA_!^7O
+M(/P==OF[.LP["'\'Y>\@_!UV^;LZS#L(?P?E[R#\W4IVRV+#O(/P=U#^#L+?
+M'8`+\P["WT'Y.PA_AUW^K@[S#L+?0?D["'^'7?ZN#O,.PM]!^3L(?[>2W;+8
+M,.\@_!V4OX/P=P?@PKR#\'=0_@["WV&7OZO#O(/P=U#^#L+?89>_J\.\@_!W
+M4/X.PM^M9+<L-LP["'\'Y>\@_-T^7).$W@E_!^7O(/P==OF[AO-.^#LH?P?A
+M[[#+WS6<=\+?0?D["'^WDMVR6,X[X>^@_!V$OSL`QWDG_!V4OX/P=]CE[QK.
+M.^'OH/P=A+_#+G_7<-X)?P?E[R#\W4IVRV(Y[X2_@_)W$/[N`!SGG?!W4/X.
+MPM]AE[]K..^$OX/R=Q#^#KO\7<-Y)_P=E+^#\'<KV2V+Y;P3_@[*WT'XNP-P
+MG'?"WT'Y.PA_AUW^KN&\$_X.RM]!^#OL\G<-YYWP=U#^#L+?K62W+);S3O@[
+M*'\'X>_VX:Y)Z)WP=U#^#L+?89>_NW+>"7\'Y>\@_!UV^;LKYYWP=U#^#L+?
+MK62W+);S3O@[*'\'X>\.P''>"7\'Y>\@_!UV^;LKYYWP=U#^#L+?89>_NW+>
+M"7\'Y>\@_-U*=LMB.>^$OX/R=Q#^[@`<YYWP=U#^#L+?89>_NW+>"7\'Y>\@
+M_!UV^;LKYYWP=U#^#L+?K62W+);S3O@[*'\'X>\.P''>"7\'Y>\@_!UV^;LK
+MYYWP=U#^#L+?89>_NW+>"7\'Y>\@_-U*=LMB.>^$OX/R=Q#^;A^N34+OA+^#
+M\G<0_@Z[_%W+>2?\'92_@_!WV.7O6LX[X>^@_!V$OUO);EDLYYWP=U#^#L+?
+M'8#CO!/^#LK?0?@[[/)W+>>=\'=0_@["WV&7OVLY[X2_@_)W$/YN);MEL9QW
+MPM]!^3L(?W<`CO-.^#LH?P?A[[#+W[6<=\+?0?D["'^'7?ZNY;P3_@[*WT'X
+MNY7LEL5RW@E_!^7O(/S=`3C..^'OH/P=A+_#+G_7<MX)?P?E[R#\'7;YNY;S
+M3O@[*'\'X>]6LEL6RWDG_!V4OX/P=_MP73+U+DKP(->CC)%&JC=N8].&;S=\
+M)^X%+LR[547?RC_%WKGU[.ZT^,?@[HN=Y(88Y89Q$S&5^_L`)SAC.20NH>O[
+M@$?DD(CK<CY>)8=$7)?S\2HY).*ZG(]7R2$1U^4F<DC$=;F)'!)Q76XBAT1<
+MEYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$
+M7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'
+M1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XB
+MAT1<EYO((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<
+M$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P2
+M7)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<
+ME]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7
+MV\@A$=?ER4OO?K\<$G%=3L]7R2$1U^7T?)4<$G%=3L]7R2$1U^4F<DC$=;F)
+M'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6Y
+MB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1U
+MN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$
+M=;F)'!)Q76XBAT1<EYO((<%UN8T<$ER7V\@AT9G*(=&9RB'1F<HAT9G*(=&9
+MRB'1F<HAT9G*(=&9RB'1F<HAT9G*(=&9RB'1F<HAT9G*(=&9RB'1)XFA'!*]
+MJ1P2O:D<$KVI'!*]J1P2O:D<$KVI'!*]J1P2O:D<$KVI'!*]J1P2O:D<$KVI
+M'!*]J1P2O:D<$KVI'/*<)(FA'/*<F,HAS_<?37P,[K[826Z8C>5.GUUZ__?V
+MC=LWI_F?"(C^MP'FN:OO`?\9"L[&3Q.N,G?-UNI*I^/$=L%?S_J7G8WEFEEF
+MW+\B^6PBOSW#LC/.\#)FF)?^@W;SPEW.1S/\Z=L?%QE.<&9',L'MOD,B#]IO
+MP7TM</XW@EX\9Y\%?H5+.8WU6N"^FKX)EWTN.UU1'2O6^,.[+\EE$:?G['_R
+M>$*0_\\[SP'C^;J7_*K[-,ZS<C^3G[LOU__4U8^OU?.8#>J-<MT<SO_4U?.<
+M'>%.][ZZS^YJ?!A8OC,.OG,]R/R=.\&=;0=!-4Z62?=Q__?VC=MWI_F?"3`+
+3@&8=S/Q'DR1?_!^)[K:L<6``````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu
index 490438a..39509f6 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu
@@ -1,128 +1,128 @@
# $FreeBSD$
begin 644 img-63x255-512-ebr.qcow.gz
-M'XL("+@S(E0``VEM9RTV,W@R-34M-3$R+65B<BYQ8V]W+F]U=`"MG<EN'-D1
-M1??ZBM(L45-%1(X:*,*`#7AG+VQO.\=U?8#@;S<EOH&,O%>A=K>::%!0YT75
-MX^%1VWWP=#[?_3B=6CDUW:D93_M\NOUY^I#3O9\\_#A]^^??_O[^_H]OC^[&
-MY/R3I]S/^ZW,/=CZ;YW3[T\MI_/X"W.W'X+F[KTZ^QVO[MZ;/<Y=/;I[L_@Y
-M98/V8/"4YL[I]0DYO>;77M^->[MR=WI_WMM5\G;;7QO\AWM]^KM@^:77]SN_
-MOAT<_*V\O@8^U;.YX<'<Y?!V6_C4R.:FG\*LYPX^-;.Y)9CKX5,KF]N"N0$^
-MM>,Y^<G7]FYNA$\)FU,X=RIS$WS*V%SS8.Z<YF[*W`R?(M\7XKC+WQ>5NP4^
-M1;B3D+L5/D6XDY"[#3Y%N).0NQT^1;B3B#O!3Q'N-.).D**4<:<1=X*,K(P[
-MC;@3Y#MEW&G$G2#?*>-.(^X$^4X9=QIQ)\AWRKC3B#M!OE/&G8;<(=\IX\Y"
-M[I#OC'%G(7?(=\:XLY`[Y#MCW%G('?*=,>XLY`[YSAAW%G*'?&>,.PNY0[XS
-MQIU%W"E^BG#71-PI\EW#N&LB[A3YKF'<-1%WBGS7,.Z:B#M%OFL8=TW$G2+?
-M-8R[)N).D>\:QET3<:?(=PWCK@FY0[YK&'=MR!WR7<NX:T/ND.]:QET;<H=\
-MUS+NVI`[Y+N6<=>&W"'?M8R[-N0.^:YEW+4A=\AW+>.NC;@S_!3AKHNX,^2[
-MCG'71=P9\EW'N.LB[@SYKF/<=1%WAGS7,>ZZB#M#ONL8=UW$G2'?=8R[+N+.
-MD.\ZQET7<H=\US'N^I`[Y+N><=>'W"'?]8R[/N0.^:YGW/4A=\AW/>.N#[E#
-MONL9=WW('?)=S[CK0^Z0[WK&71]QU^"G"'=#Q%V#?#<P[H:(NP;Y;F#<#1%W
-M#?+=P+@;(NX:Y+N!<3=$W#7(=P/C;HBX:Y#O!L;=$''7(-\-C+LAY`[Y;F#<
-MY?][GL\AWXV,NS'D#OEN9-R-(7?(=R/C;@RY0[X;&7=CR!WRW<BX&T/ND.]&
-MQMT8<H=\-S+NQHB[%C]%N)LB[EKDNXEQ-T7<M<AW$^-NBKAKD>\FQMT4<=<B
-MWTV,NRGBKD6^FQAW4\1=BWPW,>ZFB+L6^6YBW$TA=\AW$^,N_V=2/H=\-S/N
-MYI`[Y+N9<3>'W"'?S8R[.>0.^6YFW,TA=\AW,^-N#KE#OIL9=W/('?+=S+B;
-M(^XZ_!3A;HFXZY#O%L;=$G'7(=\MC+LEXJY#OEL8=TO$78=\MS#NEHB[#OEN
-M8=PM$7<=\MW"N%LB[CKDNX5QMX3<(=\MC+LUY`[Y;F7<K2%WR'<KXVX-N4.^
-M6QEW:\@=\MW*N%M#[I#O5L;=&G*'?+<R[M:0.^2[E7&W1MSU^"G"'0F$[LTA
-MWVV,NRWBKD>^VQAW6\1=CWRW,>ZVB+L>^6YCW&T1=SWRW<:XVR+N>N2[C7&W
-M1=SUR'<;XVX+N4.^VQAW>\@=\MW.N-M#[I#O=L;='G*'?+<S[O:0.^2[G7&W
-MA]PAW^V,NSWD#OEN9]SM(7?(=SOC;H^X&_!3F#O)G_`YX#LY$^[D''$W`-_)
-MF7`GYXB[`?A.6!\HOK\[<#<`WPGK[R3L[P;@.V']G83]W0!\)ZR_D["_&X#O
-MA/5W$O9W`_"=L/Y.POYN`+X3UM])V-\-P'?"^CL)^[L!^$Y8?R=A?S<`WPGK
-M[R3L[P;@.V']G83]W0!\)ZR_D["_&X#OA/5W$O9W(WZ*<!?V=R/R'>OO).SO
-M1N0[UM])V-^-R'>LOY.POQN1[UA_)V%_-R+?L?Y.POYN1+YC_9V$_=V(?,?Z
-M.PG[NQ'YCO5W$O9W(_(=Z^\D[.]&Y#O6WTG8WXW(=ZR_D["_&Y'O6'\G87\W
-M(M^Q_D["_FY$OF/]G83]W8A\Q_H["?N["3]%N`O[NPGYCO5W$O9W$_(=Z^\D
-M[.\FY#O6WTG8WTW(=ZR_D["_FY#O6'\G87\W(=^Q_D["_FY"OF/]G83]W81\
-MQ_H["?N["?F.]7<2]G<3\AWK[R3L[R;D.];?2=C?3<AWK+^3L+^;D.]8?R=A
-M?S<AW['^3L+^;D*^8_V=A/W=C)\BW(7]W8Q\Q_H["?N[&?F.]7<2]G<S\AWK
-M[R3L[V;D.];?2=C?S<AWK+^3L+^;D>]8?R=A?S<CW['^3L+^;D:^8_V=A/W=
-MC'S'^CL)^[L9^8[U=Q+V=S/R'>OO).SO9N0[UM])V-_-R'>LOY.POYN1[UA_
-M)V%_-R/?L?Y.POYNP4\1[L+^;D&^8_V=A/W=@GS'^CL)^[L%^8[U=Q+V=POR
-M'>OO).SO%N0[UM])V-\MR'>LOY.POUN0[UA_)V%_MR#?L?Y.POYN0;YC_9V$
-M_=V"?,?Z.PG[NP7YCO5W$O9W"_(=Z^\D[.\6Y#O6WTG8WRW(=ZR_D["_6Y#O
-M6'\G87^WXJ<(=V%_MR+?L?Y.POYN1;YC_9V$_=V*?,?Z.PG[NQ7YCO5W$O9W
-M*_(=Z^\D[.]6Y#O6WTG8WZW(=ZR_D["_6Y'O6'\G87^W(M^Q_D["_FY%OF/]
-MG83]W8I\Q_H["?N[%?F.]7<2]G<K\AWK[R3L[U;D.];?2=C?K<AWK+^3L+_;
-M\%.$N["_VY#O6'\G87^W(=^Q_D["_FY#OF/]G83]W89\Q_H["?N[#?F.]7<2
-M]G<;\AWK[R3L[S;D.];?2=C?;<AWK+^3L+_;D.]8?R=A?[<AW['^3L+^;D.^
-M8_V=A/W=AGS'^CL)^[L-^8[U=Q+V=QOR'>OO).SO-N0[UM])V-_M^"G"7=C?
-M[<AWK+^3L+_;D>]8?R=A?[<CW['^3L+^;D>^8_V=A/W=CGS'^CL)^[L=^8[U
-M=Q+V=SOR'>OO).SO=N0[UM])V-_MR'>LOY.PO]N1[UA_)V%_MR/?L?Y.POYN
-M1[YC_9V$_=V.?,?Z.PG[NQWYCO5W$O9W._(=Z^\DZN_LC)_"W&G^Q,V=ZASP
-MW>U3F#MU_5V^[^]T*G/`=\KZ.W7]W2EQ=[HI<\!WROH[=?W=*7%W^JW,`=\I
-MZ^_4]7>GR^'L@.^4]7?J^KMR=G4.^$Y9?Z>NOP-SP'?*^CMU_1V8`[Y3UM^I
-MZ^_RW.,Z!WRGK+]3U]\]SG.5.^`[9?V=NO[N<>+N<>4.^$Y9?Z>NOWN<N'M<
-MN0.^4];?J>OO'E\.9P=\IZR_4]??E;.K<\!WROH[=?T=F`.^4];?J>OOCG/H
-M_CME_9VZ_B[//:ESR'>LOU/7WSW)<X4[=/^=LOY.77_W)''WI'"'[K]3UM^I
-MZ^^>).Z>%.[0_7?*^CMU_=V3R^'LD.]8?Z>NORMG5^>0[UA_IZZ_`W/(=ZR_
-M4]??@3GD.];?J>OO\MS3.H=\Q_H[=?W=TSQ7N4.^8_V=NO[N:>+N:>4.^8[U
-M=^KZNZ>)NZ>5.^0[UM^IZ^^>7@YGAWS'^CMU_5TYNSJ'?,?Z.W7]'9A#OF/]
-MG;K^[CB'[K]3UM^IZ^_RW+,ZAWS'^CMU_=VS/%>X0_??*>OOU/5WSQ)WSPIW
-MZ/X[9?V=NO[N6>+N6>$.W7^GK+]3U]\]NQS.#OF.]7?J^KMR=G4.^8[U=^KZ
-M.S"'?,?Z.W7]'9A#OF/]G;K^+L\]KW/(=ZR_4]??/<]SE3OD.];?J>OOGB?N
-MGE?ND.]8?Z>NOWN>N'M>N4.^8_V=NO[N^>5P=LAWK+]3U]^5LZMSR'>LOU/7
-MWX$YY#O6WZGK[XYSZ/X[9?V=NOXNS[VH<\AWK+]3U]^]R'.%.W3_G;+^3EU_
-M]R)Q]Z)PA^Z_4];?J>OO7B3N7A3NT/UWROH[=?W=B\OA[)#O6'^GKK\K9U?G
-MD.]8?Z>NOP-SR'>LOU/7WX$YY#O6WZGK[_+<RSJ'?,?Z.W7]W<L\5[E#OF/]
-MG;K^[F7B[F7E#OF.]7?J^KN7B;N7E3OD.];?J>OO7EX.9X=\Q_H[=?U=.;LZ
-MAWS'^CMU_1V80[YC_9VZ_NXXA^Z_4];?J>OO\MRK.H=\Q_H[=?W=JSQ7N$/W
-MWRGK[]3U=Z\2=Z\*=^C^.V7]G;K^[E7B[E7A#MU_IZR_4]??O;H<S@[YCO5W
-MZOJ[<G9U#OF.]7?J^CLPAWS'^CMU_1V80[YC_9VZ_B[/O:YSR'>LOU/7W[W.
-M<Y4[Y#O6WZGK[UXG[EY7[I#O6'^GKK][G;A[7;E#OF/]G;K^[O7E<';(=ZR_
-M4]??E;.K<\AWK+]3U]^!.>0[UM^IZ^^.<^C^.V7]G;K^+L]=U3GD.];?J>OO
-MKO)<X0[=?Z>LOU/7WUTE[JX*=^C^.V7]G;K^[BIQ=U6X0_??*>OOU/5W5Y?#
-MV2'?L?Y.77]7SJ[.(=^Q_DY=?P?FD.]8?Z>NOP-SR'>LOU/7W^6Y-W4.^8[U
-M=^KZNS=YKG*'?,?Z.W7]W9O$W9O*'?(=Z^_4]7=O$G=O*G?(=ZR_4]??O;D<
-MS@[YCO5WZOJ[<G9U#OF.]7?J^CLPAWS'^CMU_=UQ#MU_IZR_4]??Y;FW=0[Y
-MCO5WZOJ[MWFN<(?NOU/6WZGK[]XF[MX6[M#]=\KZ.W7]W=O$W=O"';K_3EE_
-MIZZ_>WLYG!WR'>OOU/5WY>SJ'/(=Z^_4]7=@#OF.]7?J^CLPAWS'^CMU_5V>
-M>U?GD.]8?Z>NOWN7YRIWR'>LOU/7W[U+W+VKW"'?L?Y.77_W+G'WKG*'?,?Z
-M.W7]W;O+X>R0[UA_IZZ_*V=7YY#O6'^GKK\#<\AWK+]3U]\=Y]#]=\KZ.W7]
-M79Y[7^>0[UA_IU%_9^C^.V7]G4;]G:'[[Y3U=QKU=X;NOU/6WVG4WQFZ_TY9
-M?Z=1?V?H_CME_9U&_9VA^^^4]7<:]7>&[K]3UM\IZ>\^U#GD.];?J>OO/N2Y
-MRAWR'>OOU/5W'Q)W'RIWR'>LOU/7WWU(W'VHW"'?L?Y.77_WX7(X.^0[UM^I
-MZ^_*V=4YY#O6WZGK[\`<\AWK[]3U=\<Y=/^=LO[.\B=N[ESG@.^,]7>WO_"`
-MN^RG<^$.W7]GK+\SU]^=T]ZY<(?NOS/6WYGK[\Z)NW/A#MU_9ZR_,]??G2^'
-MLP.^,];?F>OORMG5.>`[8_V=N?X.S`'?&>OOS/5W8`[XSEA_9ZZ_RW-2YX#O
-MC/5WYOH[R7.5.^`[8_V=N?Y.TLN3RAWPG;'^SEQ_)XD[J=P!WQGK[\SU=W(Y
-MG!WPG;'^SEQ_5\ZNS@'?&>OOS/5W8`[XSEA_9ZZ_.\ZA^^^,]7?F^KL\IW4.
-M^8[U=^;Z.\USA3MT_YVQ_LY<?Z>).RW<H?OOC/5WYOH[3=QIX0[=?V>LOS/7
-MW^GE<';(=ZR_,]??E;.K<\AWK+\SU]^!.>0[UM^9Z^_`'/(=Z^_,]7=YSNH<
-M\AWK[\SU=Y;G*G?(=ZR_,]??6>+.*G?(=ZR_,]??6>+.*G?(=ZR_,]??V>5P
-M=LAWK+\SU]^5LZMSR'>LOS/7WX$YY#O6WYGK[XYSZ/X[8_V=N?XNSS5U#OF.
-M]7?F^KLFSQ7NT/UWQOH[<_U=D[AK"G?H_CMC_9VY_JY)W#6%.W3_G;'^SEQ_
-MUUP.9X=\Q_H[<_U=.;LZAWS'^CMS_1V80[YC_9VY_@[,(=^Q_LY<?Y?GVCJ'
-M?,?Z.W/]79OG*G?(=ZR_,]??M8F[MG*'?,?Z.W/]79NX:RMWR'>LOS/7W[67
-MP]DAW['^SEQ_5\ZNSB'?L?[.7'\'YI#O6']GKK\[SJ'[[XSU=^;ZNSS7U3GD
-M.];?F>OONCQ7N$/WWQGK[\SU=UWBKBO<H?OOC/5WYOJ[+G'7%>[0_7?&^CMS
-M_5UW.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOH[,(=\Q_H[<_U=GNOK
-M'/(=Z^_,]7=]GJO<(=^Q_LY<?]<G[OK*'?(=Z^_,]7=]XJZOW"'?L?[.7'_7
-M7PYGAWS'^CMS_5TYNSJ'?,?Z.W/]'9A#OF/]G;G^[CB'[K\SUM^9Z^_RW%#G
-MD.]8?V>NOQOR7.$.W7]GK+\SU]\-B;NA<(?NOS/6WYGK[X;$W5"X0_??&>OO
-MS/5WP^5P=LAWK+\SU]^5LZMSR'>LOS/7WX$YY#O6WYGK[\`<\AWK[\SU=WEN
-MK'/(=ZR_,]??C7FN<H=\Q_H[<_W=F+@;*W?(=ZR_,]??C8F[L7*'?,?Z.W/]
-MW7@YG!WR'>OOS/5WY>SJ'/(=Z^_,]7=@#OF.]7?F^KOC'+K_SEA_9ZZ_RW,?
-MZQSR'>OOS/5W'_-<X0[=?V>LOS/7WWU,W'TLW*'[[XSU=^;ZNX^)NX^%.W3_
-MG;'^SEQ_]_%R.#OD.];?F>OORMG5.>0[UM^9Z^_`'/(=Z^_,]7=@#OF.]7?F
-M^KL\]ZG.(=^Q_LY<?_<ISU7ND.]8?V>NO_N4N/M4N4.^8_V=N?[N4^+N4^4.
-M^8[U=^;ZNT^7P]DAW['^SEQ_5\ZNSB'?L?[.7'\'YI#O6']GKK\[SJ'[[XSU
-M=^;ZNSSWN<XAW['^SEQ_]SG/%>[0_7?&^CMS_=WGQ-WGPAVZ_\Y8?V>NO_N<
-MN/M<N$/WWQGK[\SU=Y\OA[-#OF/]G;G^KIQ=G4.^8_V=N?X.S"'?L?[.7'\'
-MYI#O6']GKK_+<U_J'/(=Z^_,]7=?\ESE#OF.]7?F^KLOB;LOE3OD.];?F>OO
-MOB3NOE3ND.]8?V>NO_MR.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOJ[
-MXQRZ_\Y8?V>NO\MSUW4.^8[U=^;ZN^L\5[A#]]\9Z^_,]7?7B;OKPAVZ_\Y8
-M?V>NO[M.W%T7[M#]=\;Z.W/]W?7E<';(=ZR_,]??E;.K<\AWK+\SU]^!.>0[
-MUM^9Z^_`'/(=Z^_,]7=Y[FN=0[YC_9VY_NYKGJO<(=^Q_LY<?_<U<?>U<H=\
-MQ_H[<_W=U\3=U\H=\AWK[\SU=U\OA[-#OF/]G;G^KIQ=G4.^8_V=N?X.S"'?
-ML?[.7']WF&O.^"G,79,_<7,W=0[XKF']7>/ZNYL\=RISP'>W3V'N&M??W23N
-M;F[*'/!=P_J[QO5W-XF[F]_*'/!=P_J[QO5W-Y?#V:$_;[N<./V%;^_=CV^/
-MKGX,MN@:HF!PW^'@W=SW;[/;?^#V8VK3)[<?=S)*SR]2?U-\^/I^L')]?P[]
-M,<]_Z.VB/YGY)X-M>YJFP^"_\NM#-P?]D=?7_?B?4HV>SA/X._^%;W]Y__"O
-M/-C_^-YM^U/3GMKN-.BOOL+__/7?X.O;H^_=_^\-W\V![]V'<_D%E]_.#G-?
-M[\W9'7UU1>X]=9^[^Y_?F[M^?^_WVQY][]:Y[[[:T"_0-_LG?^_VA_LA[W^=
-M?URA;*=S_L\I[E[2\O4]U=>'>OP';_<GK^]T?+L__GV@?_C/R[TY#=[NZ>'<
-M#U'=^WH^^!(&IW=]?'7HSZ/_(U^,PRV'O_B=^WWDX7?NW9S^N2(8?ICE^^]B
-B$_@[_X5O_WC_\*^[P28-_FDGV-S2=SX_^A\T>1%04*@`````
+M'XL("%+N+50``VEM9RTV,W@R-34M-3$R+65B<BYQ8V]W+F]U=`"MG=F.5-D1
+M1=_YBF2&8LJ(N"-#5<F2+?G-?K#]VG=\S@]`_G8#=8:JN'L3M+MIU`+1=ROS
+MU,I%V[UT.)_OOIU.K9R:[M2,IWT^??MY^BZG>S]Y^/WT]9]_^_O[^]^^/KH;
+MD_-/GG(_[[<R]V#KOW5.OS^UG,[C+\Q]^RYH[MZKL]_QZNZ]V>/<U:.[-XN?
+M4S9H#P9/:>Z<7I^0TVM^[?7=NK<K=Z?WY[U=)6^W_;7!?[C7I[\+EE]Z?;_S
+MZ]O!P=_*ZVO@4SV;&Q[,70YOMX5/C6QN^BG,>N[@4S.;6X*Y'CZULKDMF!O@
+M4SN>DY]\;>_F1OB4L#F%<Z<R-\&GC,TU#^;.:>ZVS,WP*?*Y$,==_EQ4[A;X
+M%.%.0NY6^!3A3D+N-O@4X4Y"[G;X%.%.(NX$/T6XTX@[08I2QIU&W`DRLC+N
+M-.).D.^4<:<1=X)\IXP[C;@3Y#MEW&G$G2#?*>-.(^X$^4X9=QIRAWRGC#L+
+MN4.^,\:=A=PAWQGCSD+ND.^,<6<A=\AWQKBSD#OD.V/<6<@=\ITQ[BSD#OG.
+M&'<6<:?X*<)=$W&GR'<-XZZ)N%/DNX9QUT3<*?)=P[AK(NX4^:YAW#41=XI\
+MUS#NFH@[1;YK&'=-Q)TBWS6,NR;D#OFN8=RU(7?(=RWCK@VY0[YK&7=MR!WR
+M7<NX:T/ND.]:QET;<H=\US+NVI`[Y+N6<=>&W"'?M8R[-N+.\%.$NR[BSI#O
+M.L9=%W%GR'<=XZZ+N#/DNXYQUT7<&?)=Q[CK(NX,^:YCW'41=X9\US'NNH@[
+M0[[K&'==R!WR7<>XZT/ND.]ZQET?<H=\US/N^I`[Y+N><=>'W"'?]8R[/N0.
+M^:YGW/4A=\AW/>.N#[E#ONL9=WW$78.?(MP-$7<-\MW`N!LB[AKDNX%Q-T3<
+M-<AW`^-NB+AKD.\&QMT0<=<@WPV,NR'BKD&^&QAW0\1=@WPW,.Z&D#ODNX%Q
+ME__O>3Z'?#<R[L:0.^2[D7$WAMPAWXV,NS'D#OEN9-R-(7?(=R/C;@RY0[X;
+M&7=CR!WRW<BX&R/N6OP4X6Z*N&N1[R;&W11QUR+?38R[*>*N1;Z;&'=3Q%V+
+M?#<Q[J:(NQ;Y;F+<31%W+?+=Q+B;(NY:Y+N)<3>%W"'?38R[_)])^1SRW<RX
+MFT/ND.]FQMT<<H=\-S/NYI`[Y+N9<3>'W"'?S8R[.>0.^6YFW,TA=\AW,^-N
+MCKCK\%.$NR7BKD.^6QAW2\1=AWRW,.Z6B+L.^6YAW"T1=QWRW<*X6R+N.N2[
+MA7&W1-QUR'<+XVZ)N.N0[Q;&W1)RAWRW,.[6D#ODNY5QMX;<(=^MC+LUY`[Y
+M;F7<K2%WR'<KXVX-N4.^6QEW:\@=\MW*N%M#[I#O5L;=&G'7XZ<(=R00NC>'
+M?+<Q[K:(NQ[Y;F/<;1%W/?+=QKC;(NYZY+N-<;=%W/7(=QOC;HNXZY'O-L;=
+M%G'7(]]MC+LMY`[Y;F/<[2%WR'<[XVX/N4.^VQEW>\@=\MW.N-M#[I#O=L;=
+M'G*'?+<S[O:0.^2[G7&WA]PAW^V,NSWB;L!/8>XD_X#/`=_)F7`GYXB[`?A.
+MSH0[.4?<#<!WPOI`\?W=@;L!^$Y8?R=A?S<`WPGK[R3L[P;@.V']G83]W0!\
+M)ZR_D["_&X#OA/5W$O9W`_"=L/Y.POYN`+X3UM])V-\-P'?"^CL)^[L!^$Y8
+M?R=A?S<`WPGK[R3L[P;@.V']G83]W0!\)ZR_D["_&_%3A+NPOQN1[UA_)V%_
+M-R+?L?Y.POYN1+YC_9V$_=V(?,?Z.PG[NQ'YCO5W$O9W(_(=Z^\D[.]&Y#O6
+MWTG8WXW(=ZR_D["_&Y'O6'\G87\W(M^Q_D["_FY$OF/]G83]W8A\Q_H["?N[
+M$?F.]7<2]G<C\AWK[R3L[T;D.];?2=C?3?@IPEW8WTW(=ZR_D["_FY#O6'\G
+M87\W(=^Q_D["_FY"OF/]G83]W81\Q_H["?N["?F.]7<2]G<3\AWK[R3L[R;D
+M.];?2=C?3<AWK+^3L+^;D.]8?R=A?S<AW['^3L+^;D*^8_V=A/W=A'S'^CL)
+M^[L)^8[U=Q+V=Q/R'>OO).SO9OP4X2[L[V;D.];?2=C?S<AWK+^3L+^;D>]8
+M?R=A?S<CW['^3L+^;D:^8_V=A/W=C'S'^CL)^[L9^8[U=Q+V=S/R'>OO).SO
+M9N0[UM])V-_-R'>LOY.POYN1[UA_)V%_-R/?L?Y.POYN1KYC_9V$_=V,?,?Z
+M.PG[NQGYCO5W$O9W"WZ*<!?V=POR'>OO).SO%N0[UM])V-\MR'>LOY.POUN0
+M[UA_)V%_MR#?L?Y.POYN0;YC_9V$_=V"?,?Z.PG[NP7YCO5W$O9W"_(=Z^\D
+M[.\6Y#O6WTG8WRW(=ZR_D["_6Y#O6'\G87^W(-^Q_D["_FY!OF/]G83]W8)\
+MQ_H["?N[%3]%N`O[NQ7YCO5W$O9W*_(=Z^\D[.]6Y#O6WTG8WZW(=ZR_D["_
+M6Y'O6'\G87^W(M^Q_D["_FY%OF/]G83]W8I\Q_H["?N[%?F.]7<2]G<K\AWK
+M[R3L[U;D.];?2=C?K<AWK+^3L+];D>]8?R=A?[<BW['^3L+^;D6^8_V=A/W=
+MAI\BW(7]W89\Q_H["?N[#?F.]7<2]G<;\AWK[R3L[S;D.];?2=C?;<AWK+^3
+ML+_;D.]8?R=A?[<AW['^3L+^;D.^8_V=A/W=AGS'^CL)^[L-^8[U=Q+V=QOR
+M'>OO).SO-N0[UM])V-]MR'>LOY.PO]N0[UA_)V%_MR'?L?Y.POYNQT\1[L+^
+M;D>^8_V=A/W=CGS'^CL)^[L=^8[U=Q+V=SOR'>OO).SO=N0[UM])V-_MR'>L
+MOY.PO]N1[UA_)V%_MR/?L?Y.POYN1[YC_9V$_=V.?,?Z.PG[NQWYCO5W$O9W
+M._(=Z^\D[.]VY#O6WTG8W^W(=ZR_D["_VY'O6'\G47]G9_P4YD[S#]S<J<X!
+MWWU["G.GKK_+]_V=3F4.^$Y9?Z>NOSLE[DZW90[X3EE_IZZ_.R7N3K^5.>`[
+M9?V=NO[N=#F<'?"=LOY.77]7SJ[.`=\IZ^_4]7=@#OA.67^GKK\#<\!WROH[
+M=?U=GGM<YX#OE/5WZOJ[QWFN<@=\IZR_4]??/4[</:[<`=\IZ^_4]7>/$W>/
+M*W?`=\KZ.W7]W>/+X>R`[Y3U=^KZNW)V=0[X3EE_IZZ_`W/`=\KZ.W7]W7$.
+MW7^GK+]3U]_EN2=U#OF.]7?J^KLG>:YPA^Z_4];?J>OOGB3NGA3NT/UWROH[
+M=?W=D\3=D\(=NO].67^GKK][<CF<'?(=Z^_4]7?E[.H<\AWK[]3U=V`.^8[U
+M=^KZ.S"'?,?Z.W7]79Y[6N>0[UA_IZZ_>YKG*G?(=ZR_4]??/4W</:W<(=^Q
+M_DY=?_<T<?>T<H=\Q_H[=?W=T\OA[)#O6'^GKK\K9U?GD.]8?Z>NOP-SR'>L
+MOU/7WQWGT/UWROH[=?U=GGM6YY#O6'^GKK][EN<*=^C^.V7]G;K^[EGB[EGA
+M#MU_IZR_4]??/4O</2O<H?OOE/5WZOJ[9Y?#V2'?L?Y.77]7SJ[.(=^Q_DY=
+M?P?FD.]8?Z>NOP-SR'>LOU/7W^6YYW4.^8[U=^KZN^=YKG*'?,?Z.W7]W?/$
+MW?/*'?(=Z^_4]7?/$W?/*W?(=ZR_4]??/;\<S@[YCO5WZOJ[<G9U#OF.]7?J
+M^CLPAWS'^CMU_=UQ#MU_IZR_4]??Y;D7=0[YCO5WZOJ[%WFN<(?NOU/6WZGK
+M[UXD[EX4[M#]=\KZ.W7]W8O$W8O"';K_3EE_IZZ_>W$YG!WR'>OOU/5WY>SJ
+M'/(=Z^_4]7=@#OF.]7?J^CLPAWS'^CMU_5V>>UGGD.]8?Z>NOWN9YRIWR'>L
+MOU/7W[U,W+VLW"'?L?Y.77_W,G'WLG*'?,?Z.W7]W<O+X>R0[UA_IZZ_*V=7
+MYY#O6'^GKK\#<\AWK+]3U]\=Y]#]=\KZ.W7]79Y[5>>0[UA_IZZ_>Y7G"G?H
+M_CME_9VZ_NY5XNY5X0[=?Z>LOU/7W[U*W+TJW*'[[Y3U=^KZNU>7P]DAW['^
+M3EU_5\ZNSB'?L?Y.77\'YI#O6'^GKK\#<\AWK+]3U]_EN==U#OF.]7?J^KO7
+M>:YRAWS'^CMU_=WKQ-WKRAWR'>OOU/5WKQ-WKRMWR'>LOU/7W[V^',X.^8[U
+M=^KZNW)V=0[YCO5WZOH[,(=\Q_H[=?W=<0[=?Z>LOU/7W^6YJSJ'?,?Z.W7]
+MW56>*]RA^^^4]7?J^KNKQ-U5X0[=?Z>LOU/7WUTE[JX*=^C^.V7]G;K^[NIR
+M.#OD.];?J>OORMG5.>0[UM^IZ^_`'/(=Z^_4]7=@#OF.]7?J^KL\]Z;.(=^Q
+M_DY=?_<FSU7ND.]8?Z>NOWN3N'M3N4.^8_V=NO[N3>+N3>4.^8[U=^KZNS>7
+MP]DAW['^3EU_5\ZNSB'?L?Y.77\'YI#O6'^GKK\[SJ'[[Y3U=^KZNSSWMLXA
+MW['^3EU_]S;/%>[0_7?*^CMU_=W;Q-W;PAVZ_TY9?Z>NOWN;N'M;N$/WWRGK
+M[]3U=V\OA[-#OF/]G;K^KIQ=G4.^8_V=NOX.S"'?L?Y.77\'YI#O6'^GKK_+
+M<^_J'/(=Z^_4]7?O\ESE#OF.]7?J^KMWB;MWE3OD.];?J>OOWB7NWE7ND.]8
+M?Z>NOWMW.9P=\AWK[]3U=^7LZASR'>OOU/5W8`[YCO5WZOJ[XQRZ_TY9?Z>N
+MO\MS[^L<\AWK[S3J[PS=?Z>LO].HOS-T_YVR_DZC_L[0_7?*^CN-^CM#]]\I
+MZ^\TZN\,W7^GK+_3J+\S=/^=LOY.H_[.T/UWROH[)?W=ASJ'?,?Z.W7]W8<\
+M5[E#OF/]G;K^[D/B[D/E#OF.]7?J^KL/B;L/E3OD.];?J>OO/EP.9X=\Q_H[
+M=?U=.;LZAWS'^CMU_1V80[YC_9VZ_NXXA^Z_4];?6?Z!FSO7.>`[8_W=MU]X
+MP%WVT[EPA^Z_,];?F>OOSFGO7+A#]]\9Z^_,]7?GQ-VY<(?NOS/6WYGK[\Z7
+MP]D!WQGK[\SU=^7LZASPG;'^SEQ_!^:`[XSU=^;Z.S`'?&>LOS/7W^4YJ7/`
+M=\;Z.W/]G>2YRAWPG;'^SEQ_)^GE2>4.^,Y8?V>NOY/$G53N@.^,]7?F^CNY
+M',X.^,Y8?V>NORMG5^>`[XSU=^;Z.S`'?&>LOS/7WQWGT/UWQOH[<_U=GM,Z
+MAWS'^CMS_9WFN<(=NO_.6']GKK_3Q)T6[M#]=\;Z.W/]G2;NM'"'[K\SUM^9
+MZ^_T<C@[Y#O6WYGK[\K9U3GD.];?F>OOP!SR'>OOS/5W8`[YCO5WYOJ[/&=U
+M#OF.]7?F^CO+<Y4[Y#O6WYGK[RQQ9Y4[Y#O6WYGK[RQQ9Y4[Y#O6WYGK[^QR
+M.#OD.];?F>OORMG5.>0[UM^9Z^_`'/(=Z^_,]7?'.73_G;'^SEQ_E^>:.H=\
+MQ_H[<_U=D^<*=^C^.V/]G;G^KDG<-84[=/^=L?[.7'_7).Z:PAVZ_\Y8?V>N
+MOVLNA[-#OF/]G;G^KIQ=G4.^8_V=N?X.S"'?L?[.7'\'YI#O6']GKK_+<VV=
+M0[YC_9VY_J[-<Y4[Y#O6WYGK[]K$75NY0[YC_9VY_JY-W+65.^0[UM^9Z^_:
+MR^'LD.]8?V>NORMG5^>0[UA_9ZZ_`W/(=ZR_,]??'>?0_7?&^CMS_5V>Z^H<
+M\AWK[\SU=UV>*]RA^^^,]7?F^KLN<=<5[M#]=\;Z.W/]79>XZPIWZ/X[8_V=
+MN?ZNNQS.#OF.]7?F^KMR=G4.^8[U=^;Z.S"'?,?Z.W/]'9A#OF/]G;G^+L_U
+M=0[YCO5WYOJ[/L]5[I#O6']GKK_K$W=]Y0[YCO5WYOJ[/G'75^Z0[UA_9ZZ_
+MZR^'LT.^8_V=N?ZNG%V=0[YC_9VY_@[,(=^Q_LY<?W><0_??&>OOS/5W>6ZH
+M<\AWK+\SU]\->:YPA^Z_,];?F>OOAL3=4+A#]]\9Z^_,]7=#XFXHW*'[[XSU
+M=^;ZN^%R.#OD.];?F>OORMG5.>0[UM^9Z^_`'/(=Z^_,]7=@#OF.]7?F^KL\
+M-]8YY#O6WYGK[\8\5[E#OF/]G;G^;DS<C94[Y#O6WYGK[\;$W5BY0[YC_9VY
+M_FZ\',X.^8[U=^;ZNW)V=0[YCO5WYOH[,(=\Q_H[<_W=<0[=?V>LOS/7W^6Y
+MCW4.^8[U=^;ZNX]YKG"'[K\SUM^9Z^\^)NX^%N[0_7?&^CMS_=W'Q-W'PAVZ
+M_\Y8?V>NO_MX.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOH[,(=\Q_H[
+M<_U=GOM4YY#O6']GKK_[E.<J=\AWK+\SU]]]2MQ]JMPAW['^SEQ_]REQ]ZER
+MAWS'^CMS_=VGR^'LD.]8?V>NORMG5^>0[UA_9ZZ_`W/(=ZR_,]??'>?0_7?&
+M^CMS_5V>^USGD.]8?V>NO_N<YPIWZ/X[8_V=N?[N<^+N<^$.W7]GK+\SU]]]
+M3MQ]+MRA^^^,]7?F^KO/E\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0[UA_9ZZ_
+M`W/(=ZR_,]??Y;DO=0[YCO5WYOJ[+WFN<H=\Q_H[<_W=E\3=E\H=\AWK[\SU
+M=U\2=U\J=\AWK+\SU]]]N1S.#OF.]7?F^KMR=G4.^8[U=^;Z.S"'?,?Z.W/]
+MW7$.W7]GK+\SU]_EN>LZAWS'^CMS_=UUGBO<H?OOC/5WYOJ[Z\3==>$.W7]G
+MK+\SU]]=)^ZN"W?H_CMC_9VY_N[Z<C@[Y#O6WYGK[\K9U3GD.];?F>OOP!SR
+M'>OOS/5W8`[YCO5WYOJ[/'=3YY#O6']GKK^[R7.5.^0[UM^9Z^]N$G<WE3OD
+M.];?F>OO;A)W-Y4[Y#O6WYGK[VXNA[-#OF/]G;G^KIQ=G4.^8_V=N?X.S"'?
+ML?[.7']WF&O.^"G,79-_X.9NZQSP7</ZN\;U=[=Y[E3F@.^^/86Y:UQ_=YNX
+MN[TM<\!W#>OO&M??W2;N;G\K<\!W#>OO&M??W5X.9X?^O.URXO07OKYWW[X^
+MNOHQV*)KB*)!@8-W<S\^9C]2N*E-G'S[Z9V,TO.+U-\4[[^^FSM6KN_/H3_F
+M^0^]7?0G,_]DL&U/TW08_%=^?>CFH#_R^KH?_U.JT=-Y`G_GO_#U+^\?_I4'
+M^Q^?W;8_->VI[4Z#_NHK_,]?_PV^OCWZ[/Y_;_AN#GQV'\[E%UQ^.SO,W=R;
+M^_[9W>_]DV>Y]]1][N[_^-[<]?M[O]_VZ+-;Y[[[:D._0-_LG_S9[0_W0][_
+M.O^X0ME.Y_R?4]R]I.7K>ZJO#_7X#][N3U[?Z?AV?_S[0/_PGY=[<QJ\W=/#
+MN;F8!7P)@].[/KXZ].?1_Y$OQN&6PU_\Y'X?>?C)O9O3/U<$PP^S?/]=;`)_
+@Y[_P]1_O'_YU-]BDP3_M!)MO])W/C_X'"T=/.U"H````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu
index dfe95ff..71e3879 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu
@@ -1,22 +1,22 @@
# $FreeBSD$
begin 644 img-63x255-512-ebr.qcow2.gz
-M'XL("*X[(U0``VEM9RTV,W@R-34M-3$R+65B<BYQ8V]W,BYO=70`K9C)DM-`
-M#$#O^8IF6`8&"&ZIO;$D,#!4<8,#<'86?T6*;\=.RVY;EMR3E!.7*ZFV7JG=
-M3_*2)/YC3&J-RXPK3;TSS7_:P`S^C#=S^O7]QWKX.:T\S"9*E#"0'WO<B/4O
-MX$##)78Z8&7<(#L4<-!%34$QG%.SFQL0<'>K\ZD[+T;!(O`:H,>IBW%5?N#S
-MXQ'NROQ@Z?Q0/G]I%\<'LOG\T.?'HW(-5T1Q($25&JZ*XE"(VFFX?13GA*B#
-MAE,J=X!+A:A:P=F(*@TN$Z*LAH,H+A>B4,.Y**X0HC3O;-R[4HC2O+-Q[RHA
-M2O/.QKW;"5&:=S;NW5Z(TKRS<>\.0I3F'2C>F8`["E&:=\"\>T*XFX"KA2C-
-M.V#>/27<LQYGI2C-.V#>/2?<BX`3^AUHW@'S[I9P+P-.Z'>@>0?,NU>$NPLX
-MH=^!YATP[UX3[DW`"?T.-.^`>?=VXIT5^AUHWB'S[AVQDH`3^AUJWB'SSA(.
-M`D[H=ZAYA\P[))P+.*'?H>8=,N]2PF4!)_0[U+Q#YEU.N"+@A'Z'FG?(O"L)
-M]S[@A'Z'FG?(O/M`N(\!)_0[U+Q#YMTGPFT"3NAWJ'GGF'=;PGT..*'?.<T[
-MQ[S[0KC[@!/ZG=.\<\R[KX3[UN-`BNJ]2Q)Y(]S#I&9AV?M/%^Z/K;#7!V:`
-MQ27`N0P]KEQTPJFOC<N`=:WEE_K::`YHMBJE'\WF?:;XO0U5,<YO2Y41<(>E
-MIUM?!DQ34U43X.\N/YA-X_+\\F,[W%9E)>SU@=/]>OSM@(5_.Y"W199FIH#'
-M9OCWX8^POL5R#WP>I[\=H($NX;XC3G#;`0Z]?8$R**N1=\/?`]QF'3IS@YM]
-M.]`^\ARE`76RZ;*R%'UOZ6T=K'-[I]T^$'476W:GW*^O"?D)O05&TYW)STRG
-MVU[$^X=MMAXM#B+3-6/<N5$-UG.TA)&SMYEFMU]X,2ROC$=6;@L95Z['P;*-
-EH#QWEL;`YJCI7A\X_5R/OQ[H"+C8&719>^U=_0=D5Z&8TA0`````
+M'XL("%+N+50``VEM9RTV,W@R-34M-3$R+65B<BYQ8V]W,BYO=70`K9C;DM,P
+M#(;O]RG,&18HL>2D"8<6%I89[N`"N$Y/3]'AV:EK)784*=YVTG8R[;C_-W+\
+M64U:%.%A3&F-JXQKS&%C3I_I!2;Y,'R9XZ_O/Q;IXW@38+904L+`<M_C!JQ_
+M$0<:KK#C`2OCDNI0P$&7&H-R.*=6-S4@X&YOSJ?NO!@U2^`UP(!3%^.J^B#4
+MQQ/NROI@[OI0/G]EE^,#U71]&.KCJ:6&J[,X$%*-AFNS.!12&PVWS>*<D-II
+M.&7G)KA22!T4G,VH<L)50LIJ.,CBED(*-9S+XFHAI7EG\]XU0DKSSN:]:X64
+MYIW->[<14IIW-N_=5DAIWMF\=SLAI7D'BG<FXO9"2O,.F'>/"/<XX@Y"2O,.
+MF'=/"/>TQUDII7D'S+MGA'L><4*_`\T[8-Z](-S+B!/Z'6C>`?/N%>%N(T[H
+M=Z!Y!\R[UX1[$W%"OP/-.V#>O1UY9X5^!YIWR+Q[1ZPBXH1^AYIWR+RSA(.(
+M$_H=:MXA\PX)YR).Z'>H>8?,NY)P5<0)_0XU[Y!YMR1<'7%"OT/-.V3>-81[
+M'W%"OT/-.V3>?2#<QX@3^AUJWB'S[A/A5A$G]#O4O'/,NS7A/D><T.^<YIUC
+MWGTAW%W$"?W.:=XYYMU7PGWK<2"E>N^*0GX1[GZT9V'>ZT\7KX^M<-0')H#U
+M)<"I"@.NF77"9=@;%P+E"0><WQMA,FW9F6S)9\IO;=P5:7WK8/,JQ>WFGN[A
+M,F!9FK8=`7]W]<%D&9?7M]S[8;\K6^&H#QSO%L-G!ZS#OP-+O\G*RM3PT`K_
+MWO\1UK>>[X8OX/1_!VB@*[COB"/<.L'Y"XQ#\LUT6PV\2]\GN-4B=N83;O+?
+M`7_+LY<&U,F6\\I2][VEMS599W^E[6^(NA];=J7<KZ^)]0F]!0;3G:C/C*?K
+M?\3[FVVV'AX'F>F:(6[3=Q9A"3-G;S6N;COS8EB^,QZX<SUDN',##N9M!,VY
+CLYP,/'UK?-0'CC\7PV<`.@+.=@9=Y7][;_X#6VG_\](4````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu
index ba30800..019b487 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu
@@ -1,12 +1,12 @@
# $FreeBSD$
begin 644 img-63x255-512-ebr.raw.gz
-M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65B<BYR87<N;W5T`*V4S0["(`S'
-M[WN*GCTLP(;#RY:8>/>BGG%N3[&'MXQ-6V$?)O`5DL(O_])2(7P#P!D=RX8A
-M_VE#=LA&FGS^#>S[*-#C6KR%!W!8/6UP%#W!M1**+JJO<4M-<:_4[O;_`;4&
-M:P/@;=:G$H>CZIRY5"!L9%TV#.><]QEHQH31%90:]!&,VJOP<;E'XFN$3.6P
-MQZDMW"S89U`,UQ!<X;/O2Y'D%LT[NB>XVL\95ZZIPY<07<RPZ*Q.FRP&.[]'
-MXPRR`UF`,)--<>`GOO#5=PIE*.;NBCX(W;4.5_'SDN#4AKO`<6.A(O%D(=QX
-MO3I4UR8.AOS]&3M_KH/PG^MQ*FTA.(V5!3,03X7KLF&XYKQ[8#D!D[V@JWQ"
-*9&_T+/:\Y08`````
+M'XL("%+N+50``VEM9RTV,W@R-34M-3$R+65B<BYR87<N;W5T`*V4S0Z#(`S'
+M[SY%SSL80)GLHLF2W7?9=D:G3^'#KQ5U(/B50(5("K_\2PN,F0:`/?BM._IT
+MT?KDD@PT7I\'\B#0X!K:Q6F9EC1F'4UIG'$-SMN`O@H-6VGCOK'#[<X!I02M
+M/>!KTB<BIZ-HR9T+8#HPKCOZ>^K:!%1#P<@"<@GR"DH<5?AYO`/Y58S'"MC@
+MQ!YN$FPJ*(2K+%R&SLY::2IQW&77G?UOX4K3)UR^I0Y/@K4AQVJP,FZQ*#1W
+MGYUGX"WP#)@:?<(%SOF%O[Z;+T,XX6[H`S]<3;C"7<\MG-@)%UQ</;\L@13N
+MG%[IJVLB)X,O;\;!FTL0]^8:G(C[$-R&EP4K$%?YX[JC?Z:N&6`^`J.=(+U\
++C"4_RQ*HU^4&````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
index b0e08ed..eae437d 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-512-ebr.vhd.gz
-M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65B<BYV:&0N;W5T`*V7P6Z<,!"&
-M[_L4(_66`S*#;<AE(T5-SY&BM&<O@2B'-E&WAQQX^'BPO=B`V6PSP"*OQO/Y
-M'\_8R$*X"T!7H'O0'6A%[5J"OH:Z`;!&_^#X+OU?&-K7/UW[[^6]\->P<[!2
-MQ%ZI._EC!=(.4@,:&D0_41N&@"F^W3U?O?Q^#CCTN#"PU"`1E(7(Q3B-.*DC
-MTH_;A^]S==52W>3EQNE[J/JH1Q6K*XJ;&">ME^U/CX9>CC+#D_Q)##$N4:?$
-MS"N2N3:I4;!K.+WE=0GN:N=SX4K%%D9MWP)T"352VY9-F(?%8TOE_?AF_AZ[
-MF3[,E(J.DC&WR7RXZ$L%0V>O0)+`K7!AI!SGN)52^=+LZ=1/^H:=!*&"`<?P
-MT]F;4!#KTZ78F/-\,K+ZS&9<_Q'PX7`Q,*/0X=I3P$9-$;FUZOW;$JIN5=^X
-M;/<Q[HD[W/XRH%)@S`+X&/2US.EH&C+;O5.8E7?>,-P6Z7T"C@6C:MK.E88&
-M/ZOPU]W/E?PV)K,=7!ZPP^$Y7!`<[_8I[B;"5:[Z)DJT.25U%[<CW-[]`DYN
-MJ:,]H5LS9(-5S,5BFIE?G&<H.R@K$(VW80H\Y1<F?==+&9B$NZ$/EN$:PM5I
-M_S+"X9EP(<4=_'<W]$Q2>&;V]DMU+7,R#O.5\<F52Y!TY3H<\FX$9MQ9;`7:
-M7LMWWC#<%^GM@.@_16S?-O2;*9M"Z8%L"BVP8U9H>+\?VBMD.B@0CO&@0#C&
-A@P+A&`\*A&,\*!".\:!`.-:#@K9'0"%V'P.\AOE=#@``
+M'XL("%/N+50``VEM9RTV,W@R-34M-3$R+65B<BYV:&0N;W5T`*V736_C(!"&
+M[_D5(_76@X7'@-U+(E7-GE>JVIZQ:U<][(>:/>3@'[^,@63P5YJ6F""L81[>
+M@0$+(=P/0!>@.]`M:$7M4H*^@[("L$9?<*AS_PI]\^=WV_Q[/V;^UV\<+!?<
+M*W8G?RQ`VD%*0$.#Z%=J0Q\PV<W^[?;]UUO`H<>%@:4&B:`L1$[&J<1)'9%^
+MW#\^C-454W5G+S=.UT'1L1X%5Y=E.XZ3ULOVIZ*ADX/,4**7R,!QD3HE1EY,
+MYMRDLF#G<'K-ZQK<[<:OA4L5FQBEK07H'$JDMDV;,`^38E/E>/AK/@[M2!\N
+MI(IFBS&VR>5PT:<*ALY>@22!:^'"0#F,<3.I\JW9T[&?]`T["4(%`P[AQ[-W
+M1@'7IW.Q,N?+B[&HSZS&]86`Z_IZX,KNJ!N_.P08137MTMSO5>_?V/=V1M_.
+M;=LMQ[VF#K>[#J@4&#,!/@5]3>+EJ"HRV[-3F)EZV=#?9_%S`@X)HTHZSI6&
+M"C^K\&7_/+.^E5DX#JX/V.'P$BX(YJ=]C-LQ7.&V&T_5LQ?/.]YFN*W[!YQ<
+M4T=G0CMG6`Q6)4X64XW\^#I#WD)>@*B\#6/@:7WAK.]N*@.C<%?TP31<0[@R
+M[I\S'%X(%V)<?3I99I;PPNQMI^J:Q(M1CW?&)W<N0>*=ZW"8]B`PP\EB,]#V
+MFM;+AOYG%C\.B/Y3E.S;AOXP3:90>F`RA1;8)E9HTGX_M%>8Z*)`N(07!<(E
+CO"@0+N%%@7`)+PJ$2WA1(%S2BX*V5T`A-O\!]-GJEUT.````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu
index b865e86..edf4354 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu
@@ -1,15 +1,15 @@
# $FreeBSD$
begin 644 img-63x255-512-ebr.vhdf.gz
-M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65B<BYV:&1F+F]U=`"ME3MOPR`0
-M@/?\BI.Z98@``R:+(T5-YTI5V]EU<)2A[=*A@W]\P1B;,SB/"H,1UL'G>W$0
-MXAX`\R;[LJ#;S)YNM5[U-/IQ-[!MDT"':\PNL\#T6@P3TXLVP#44"IW4;V>'
-M*L0=<YO;W@<4`NHZ`KYZ_5CF<)3:BCD#4B?&94&WW^#F@:I/&%$"%R`D*':K
-MAN^'MT1\%:&Y#'8X=@WG%789E,+M`ESALF^BT&!7F'?A/,!5[O4X?DD[XPFB
-M4X)%8T7>9%&FX7UAG(%JH`40-<@8!H[QA4F_;:P&0^9>T`]B<VN+*_%Z&N#8
-M%7,!X_I"%<03A?"*]ZI8NR9S,.C\9-QX<BT$GUR'8WD+P;:O+"8#S:IX7!9T
-MSQO<')`/P&P>5,/=)@N0+4@-4MAYR4%NH50AD.%,ZIKO+]W\G'_#"%L<':^B
-MN-O]K+"G19;`:OL3>;3S0+^'PVE]_CQYG"]5_L=<6J<+`^&1N0J;^[1_>9QK
-M5\1.4LA[=+HX1\.1]W8ACH_&:MV70#IU]($$R5)E<8+,=OTWM@XG,Z>*N7=7
-)?T_5:9P0"0``
+M'XL("%/N+50``VEM9RTV,W@R-34M-3$R+65B<BYV:&1F+F]U=`"ME3MOPR`0
+M@/?\BI.Z98@``R9+(D5-YTI5V]EQ<92A[=*A@W]\.6,<SL9Y5!B,0`>?[\69
+M,?\`N#?9YP7M:O2TB^6BH_'#_4">!'I<C:<X;JL4CD6#2QP'7.W6-J'?UC7W
+M;&+<1VYSF_N`2D%538"O03^1.1RE1;$4P*K$."]H=RO:`M!T":-*D`J4!B-N
+MU?!]_Y:(KV$\E\$>)Z[A@L(^@U*X;80KG+")=OI,[$_%>1?/(]S&OP$G+VGG
+M/,%L2C!KK,J;+,8U>BZ.,W`+O`!F>IF@P"&^<-9O/55#$',OZ`=3<RO$E70_
+MCW#BBKE`<8>ALB1">,5[FZEV=>9@\/'-N/'F(H3>7(\3>0O!NJLL+@/=KNDX
+M+VB?5[1YH.R!V3QH^G^;+D`WH"UHA?-2@EY#:6*@H)G4UM]?MOXY_<811ASW
+MQ2#9\;PH\+;H$D2%']$?.(_T>]@?EZ?/8\"%4A4^+#4Z73F(G)AKJ+E/NY?'
+ML7;%U$F&>(^CGG'9<X83[VUCG!R,M;8K@?S<R8((DJ4*<8J-3OTWMAZG,Z>*
+-^^\N_@`\0K'N$`D`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu
index 869f19c..ada1aea 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu
@@ -1,6 +1,6 @@
# $FreeBSD$
begin 644 img-63x255-512-ebr.vmdk.gz
-M'XL("/G%'50``VEM9RTV,W@R-34M-3$R+65B<BYV;61K+F]U=`"M7-%NY,81
+M'XL("%/N+50``VEM9RTV,W@R-34M-3$R+65B<BYV;61K+F]U=`"M7-%NY,81
M?/=7#.2W/"Q8RR6Y?#@[<<X!@B"`$3OV:\CE,!9BWQUT0I`#]/'AD%.C(D4>
M::MUJP/[V%W;W4.U=-4%9=GTX=RE=9>+NW2N*%T&-_S3]')9_FP,KTNZ\?2W
MMW__\<2//YY.3U],8`A1$H),X<28O<_3:?%!N//GHF8WAM=Y%RX/4>V+P`AW
@@ -73,12 +73,12 @@ MD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1UN4F<DBD=;F)'!)I76XBAT1:EYO(
M(9'6Y29R2*1UN8D<$ER7V\@AP76YC1P2WE0."6\JAX0WE4/"F\HAX4WED/"F
M<DAX4SDDO*D<$MY4#@EO*H>$-Y5#PIO*(>%-Y9#PIG)(]%EF*(=$;RJ'1&\J
MAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'
-M1&\JAT1O*H<\9UEF*(<\9Z9RR//+7TU\#.YEL9/<\(+V-P/V_6;W+@A/WN`P
-MO)HB7@ROO!>X&USN5_/[.OSUE<)UUN7VOPVP*%S3O`#\)_,[?S:-WYY?-?[O
-M8OI5LB__WK[Q],UI_H>`U_%Q+JKP6W&+TEW/1S/\Z=L?%QE.<&9RUPEN]W%.
-MI&6_!?>UP.73T_>,HK^X6Y\[O1:XKZ9/PET^EYWNDXX5:_R;MJ_9=1&GYQR^
-M303VCO\I.\\!T_FZY_SJEVF<9^5^)C_WLMSP+5)_UZR>QVRJ;I3KYG#CH)+S
-MG!WA3O>^>IG=S?@PL/S*./B5&T#F7[D3W-EV$-3C9)E$&B__WK[Q]-UI_F<"
-5O$1`LPY>PN\1R;[X/U4+_GL>8```
+M1&\JAT1O*H<\9UEF*(<\9Z9RR//+7TU\#.YEL9/<\(+VMP-BLWL7C$_>2%8U
+MXW_A\CZ8>2]PM\'V*_E]/?P9/KY2N,ZZW/ZW`1:%:YH7@/]D?N?/IO';\ZO&
+M_UU,OTKVY=_;-YZ^.<W_$/`Z/LY%%7XK;E&ZZ_EHAC]]^^,BPPG.3.XZP>T^
+MSHFT[+?@OA:X\.V[%\_9+^[6YTZO!>ZKZ9-PE\]EI_ND8\4:_Z;M:W9=Q.DY
+MAV\3@;WC?\K.<\!TONXYO_IE&N=9N9_)S[TL-WR+U-\UJ^<QFZH;Y;HY7)LF
+MR\H1[G3OJY?9W8P/`\NOC(-?N0%D_I4[P9UM!T$]3I9)I/'R[^T;3]^=YG\F
+6P$L$-.O@)?P>D>R+_P-J-:`0'F``````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu
index 2abc3ee..e99d8f8 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu
@@ -1,128 +1,128 @@
# $FreeBSD$
begin 644 img-63x255-512-mbr.qcow.gz
-M'XL("+PS(E0``VEM9RTV,W@R-34M-3$R+6UB<BYQ8V]W+F]U=`"MG<EN7%>R
-M1>?^BE0O45U&Q&W5D$0!KX":U1N\JJEO.\X/$.K;BQ9/0\;=6R$_2R8,"O3=
-MR#Q<6C+LA:/S^?['Z=3*J>E.S7C:Y]/=S].'G![\Y/''Z=O__OT?'Q[^^/;;
-M_9B<?_"4^WF_E;E'6_^I<_K'4\OI//[$W-V'H+D'K\[^Q*M[\&:/<U>_W;]9
-M_)RR07LT>$ISY_3ZA)Q>\W.O[]:]7;D_O5_W=I6\W?;G!O_I7I_^*5A^ZO7]
-MR>]O!P=_+Z^O@4_U;&YX-'<YO-T6/C6RN>F',.NY@T_-;&X)YGKXU,KFMF!N
-M@$_M>$Y^\+V]GQOA4\+F%,Z=RMP$GS(VUSR:.Z>YVS(WPZ?(KPMQW.5?%Y6[
-M!3Y%N).0NQ4^1;B3D+L-/D6XDY"['3Y%N).(.\%/$>XTXDZ0HI1QIQ%W@HRL
-MC#N-N!/D.V7<:<2=(-\IXTXC[@3Y3AEW&G$GR'?*N-.(.T&^4\:=AMPAWRGC
-MSD+ND.^,<6<A=\AWQKBSD#OD.V/<6<@=\ITQ[BSD#OG.&'<6<H=\9XP["[E#
-MOC/&G47<*7Z*<-=$W"GR7<.X:R+N%/FN8=PU$7>*?-<P[IJ(.T6^:QAW3<2=
-M(M\UC+LFXDZ1[QK&71-QI\AW#>.N";E#OFL8=VW('?)=R[AK0^Z0[UK&71MR
-MAWS7,N[:D#ODNY9QUX;<(=^UC+LVY`[YKF7<M2%WR'<MXZZ-N#/\%.&NB[@S
-MY+N.<==%W!GR7<>XZR+N#/FN8]QU$7>&?-<Q[KJ(.T.^ZQAW7<2=(=]UC+LN
-MXLZ0[SK&71=RAWS7,>[ZD#ODNYYQUX?<(=_UC+L^Y`[YKF?<]2%WR'<]XZX/
-MN4.^ZQEW?<@=\EW/N.M#[I#O>L9='W'7X*<(=T/$78-\-S#NAHB[!OEN8-P-
-M$7<-\MW`N!LB[AKDNX%Q-T3<-<AW`^-NB+AKD.\&QMT0<=<@WPV,NR'D#OEN
-M8-SE_SS/YY#O1L;=&'*'?#<R[L:0.^2[D7$WAMPAWXV,NS'D#OEN9-R-(7?(
-M=R/C;@RY0[X;&7=CQ%V+GR+<31%W+?+=Q+B;(NY:Y+N)<3=%W+7(=Q/C;HJX
-M:Y'O)L;=%''7(M]-C+LIXJY%OIL8=U/$78M\-S'NII`[Y+N)<9?_-RF?0[Z;
-M&7=SR!WRW<RXFT/ND.]FQMT<<H=\-S/NYI`[Y+N9<3>'W"'?S8R[.>0.^6YF
-MW,T1=QU^BG"W1-QUR'<+XVZ)N.N0[Q;&W1)QUR'?+8R[)>*N0[Y;&'=+Q%V'
-M?+<P[I:(NP[Y;F'<+1%W'?+=PKA;0NZ0[Q;&W1IRAWRW,N[6D#ODNY5QMX;<
-M(=^MC+LUY`[Y;F7<K2%WR'<KXVX-N4.^6QEW:\@=\MW*N%LC[GK\%.&.!$(/
-MYI#O-L;=%G'7(]]MC+LMXJY'OML8=UO$78]\MS'NMHB['OEN8]QM$7<]\MW&
-MN-LB[GKDNXUQMX7<(=]MC+L]Y`[Y;F?<[2%WR'<[XVX/N4.^VQEW>\@=\MW.
-MN-M#[I#O=L;='G*'?+<S[O:0.^2[G7&W1]P-^"G,G>1/^!SPG9P)=W*.N!N`
-M[^1,N)-SQ-T`?">L#Q3?WQVX&X#OA/5W$O9W`_"=L/Y.POYN`+X3UM])V-\-
-MP'?"^CL)^[L!^$Y8?R=A?S<`WPGK[R3L[P;@.V']G83]W0!\)ZR_D["_&X#O
-MA/5W$O9W`_"=L/Y.POYN`+X3UM])V-\-P'?"^CL)^[L1/T6X"_N[$?F.]7<2
-M]G<C\AWK[R3L[T;D.];?2=C?C<AWK+^3L+\;D>]8?R=A?S<BW['^3L+^;D2^
-M8_V=A/W=B'S'^CL)^[L1^8[U=Q+V=R/R'>OO).SO1N0[UM])V-^-R'>LOY.P
-MOQN1[UA_)V%_-R+?L?Y.POYN1+YC_9V$_=V$GR+<A?W=A'S'^CL)^[L)^8[U
-M=Q+V=Q/R'>OO).SO)N0[UM])V-]-R'>LOY.POYN0[UA_)V%_-R'?L?Y.POYN
-M0KYC_9V$_=V$?,?Z.PG[NPGYCO5W$O9W$_(=Z^\D[.\FY#O6WTG8WTW(=ZR_
-MD["_FY#O6'\G87\W(=^Q_D["_F[&3Q'NPOYN1KYC_9V$_=V,?,?Z.PG[NQGY
-MCO5W$O9W,_(=Z^\D[.]FY#O6WTG8W\W(=ZR_D["_FY'O6'\G87\W(]^Q_D["
-M_FY&OF/]G83]W8Q\Q_H["?N[&?F.]7<2]G<S\AWK[R3L[V;D.];?2=C?S<AW
-MK+^3L+^;D>]8?R=A?[?@IPAW87^W(-^Q_D["_FY!OF/]G83]W8)\Q_H["?N[
-M!?F.]7<2]G<+\AWK[R3L[Q;D.];?2=C?+<AWK+^3L+];D.]8?R=A?[<@W['^
-M3L+^;D&^8_V=A/W=@GS'^CL)^[L%^8[U=Q+V=POR'>OO).SO%N0[UM])V-\M
-MR'>LOY.POUOQ4X2[L+];D>]8?R=A?[<BW['^3L+^;D6^8_V=A/W=BGS'^CL)
-M^[L5^8[U=Q+V=ROR'>OO).SO5N0[UM])V-^MR'>LOY.POUN1[UA_)V%_MR+?
-ML?Y.POYN1;YC_9V$_=V*?,?Z.PG[NQ7YCO5W$O9W*_(=Z^\D[.]6Y#O6WTG8
-MWVWX*<)=V-]MR'>LOY.PO]N0[UA_)V%_MR'?L?Y.POYN0[YC_9V$_=V&?,?Z
-M.PG[NPWYCO5W$O9W&_(=Z^\D[.\VY#O6WTG8WVW(=ZR_D["_VY#O6'\G87^W
-M(=^Q_D["_FY#OF/]G83]W89\Q_H["?N[#?F.]7<2]G<;\AWK[R3L[W;\%.$N
-M[.]VY#O6WTG8W^W(=ZR_D["_VY'O6'\G87^W(]^Q_D["_FY'OF/]G83]W8Y\
-MQ_H["?N['?F.]7<2]G<[\AWK[R3L[W;D.];?2=C?[<AWK+^3L+_;D>]8?R=A
-M?[<CW['^3L+^;D>^8_V=A/W=CGS'^CL)^[L=^8[U=Q+U=W;&3V'N-'_BYDYU
-M#OCN[BG,G;K^+M_W=SJ5.>`[9?V=NO[NE+@[W98YX#ME_9VZ_NZ4N#O]7N:`
-M[Y3U=^KZN]/E<';`=\KZ.W7]73F[.@=\IZR_4]??@3G@.V7]G;K^#LP!WRGK
-M[]3U=WGN29T#OE/6WZGK[Y[DN<H=\)VR_DY=?_<D<?>D<@=\IZR_4]??/4G<
-M/:G<`=\IZ^_4]7=/+H>S`[Y3UM^IZ^_*V=4YX#ME_9VZ_@[,`=\IZ^_4]7?'
-M.73_G;+^3EU_E^>>UCGD.];?J>OOGN:YPAVZ_TY9?Z>NOWN:N'M:N$/WWRGK
-M[]3U=T\3=T\+=^C^.V7]G;K^[NGE<';(=ZR_4]??E;.K<\AWK+]3U]^!.>0[
-MUM^IZ^_`'/(=Z^_4]7=Y[EF=0[YC_9VZ_NY9GJO<(=^Q_DY=?_<L<?>L<H=\
-MQ_H[=?W=L\3=L\H=\AWK[]3U=\\NA[-#OF/]G;K^KIQ=G4.^8_V=NOX.S"'?
-ML?Y.77]WG$/WWRGK[]3U=WGN>9U#OF/]G;K^[GF>*]RA^^^4]7?J^KOGB;OG
-MA3MT_YVR_DY=?_<\<?>\<(?NOU/6WZGK[YY?#F>'?,?Z.W7]73F[.H=\Q_H[
-M=?T=F$.^8_V=NOX.S"'?L?Y.77^7YU[4.>0[UM^IZ^]>Y+G*'?(=Z^_4]7<O
-M$G<O*G?(=ZR_4]??O4C<O:C<(=^Q_DY=?_?B<C@[Y#O6WZGK[\K9U3GD.];?
-MJ>OOP!SR'>OOU/5WQSET_YVR_DY=?Y?G7M8YY#O6WZGK[U[FN<(=NO].67^G
-MKK][F;A[6;A#]]\IZ^_4]7<O$W<O"W?H_CME_9VZ_N[EY7!VR'>LOU/7WY6S
-MJW/(=ZR_4]??@3GD.];?J>OOP!SR'>OOU/5W>>Y5G4.^8_V=NO[N59ZKW"'?
-ML?Y.77_W*G'WJG*'?,?Z.W7]W:O$W:O*'?(=Z^_4]7>O+H>S0[YC_9VZ_JZ<
-M79U#OF/]G;K^#LPAW['^3EU_=YQ#]]\IZ^_4]7=Y[G6=0[YC_9VZ_NYUGBO<
-MH?OOE/5WZOJ[UXF[UX4[=/^=LOY.77_W.G'WNG"'[K]3UM^IZ^]>7PYGAWS'
-M^CMU_5TYNSJ'?,?Z.W7]'9A#OF/]G;K^#LPAW['^3EU_E^?>U#GD.];?J>OO
-MWN2YRAWR'>OOU/5W;Q)W;RIWR'>LOU/7W[U)W+VIW"'?L?Y.77_WYG(X.^0[
-MUM^IZ^_*V=4YY#O6WZGK[\`<\AWK[]3U=\<Y=/^=LOY.77^7YZ[J'/(=Z^_4
-M]7=7>:YPA^Z_4];?J>OOKA)W5X4[=/^=LOY.77]WE;B[*MRA^^^4]7?J^KNK
-MR^'LD.]8?Z>NORMG5^>0[UA_IZZ_`W/(=ZR_4]??@3GD.];?J>OO\MS;.H=\
-MQ_H[=?W=VSQ7N4.^8_V=NO[N;>+N;>4.^8[U=^KZN[>)N[>5.^0[UM^IZ^_>
-M7@YGAWS'^CMU_5TYNSJ'?,?Z.W7]'9A#OF/]G;K^[CB'[K]3UM^IZ^_RW+LZ
-MAWS'^CMU_=V[/%>X0_??*>OOU/5W[Q)W[PIWZ/X[9?V=NO[N7>+N7>$.W7^G
-MK+]3U]^]NQS.#OF.]7?J^KMR=G4.^8[U=^KZ.S"'?,?Z.W7]'9A#OF/]G;K^
-M+L^]KW/(=ZR_4]??O<]SE3OD.];?J>OOWB?NWE?ND.]8?Z>NOWN?N'M?N4.^
-M8_V=NO[N_>5P=LAWK+]3U]^5LZMSR'>LOU/7WX$YY#O6WZGK[XYSZ/X[9?V=
-MNOXNSWVH<\AWK+_3J+\S=/^=LOY.H_[.T/UWROH[C?H[0_??*>OO-.KO#-U_
-MIZR_TZB_,W3_G;+^3J/^SM#]=\KZ.XWZ.T/WWRGK[Y3T=Q_K'/(=Z^_4]7<?
-M\USE#OF.]7?J^KN/B;N/E3OD.];?J>OO/B;N/E;ND.]8?Z>NO_MX.9P=\AWK
-M[]3U=^7LZASR'>OOU/5W8`[YCO5WZOJ[XQRZ_TY9?V?Y$S=WKG/`=\;ZN[LO
-M/.(N^^E<N$/WWQGK[\SU=^>T=R[<H?OOC/5WYOJ[<^+N7+A#]]\9Z^_,]7?G
-MR^'L@.^,]7?F^KMR=G4.^,Y8?V>NOP-SP'?&^CMS_1V8`[XSUM^9Z^_RG-0Y
-MX#MC_9VY_D[R7.4.^,Y8?V>NOY/T\J1R!WQGK+\SU]])XDXJ=\!WQOH[<_V=
-M7`YG!WQGK+\SU]^5LZMSP'?&^CMS_1V8`[XSUM^9Z^^.<^C^.V/]G;G^+L]I
-MG4.^8_V=N?Y.\USA#MU_9ZR_,]??:>)."W?H_CMC_9VY_DX3=UJX0_??&>OO
-MS/5W>CF<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.^8[U=^;Z.S"'?,?Z.W/]79ZS
-M.H=\Q_H[<_V=Y;G*'?(=Z^_,]7>6N+/*'?(=Z^_,]7>6N+/*'?(=Z^_,]7=V
-M.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOJ[XQRZ_\Y8?V>NO\MS39U#
-MOF/]G;G^KLESA3MT_YVQ_LY<?]<D[IK"';K_SEA_9ZZ_:Q)W3>$.W7]GK+\S
-MU]\UE\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0[UA_9ZZ_`W/(=ZR_,]??Y;FV
-MSB'?L?[.7'_7YKG*'?(=Z^_,]7=MXJZMW"'?L?[.7'_7)N[:RAWR'>OOS/5W
-M[>5P=LAWK+\SU]^5LZMSR'>LOS/7WX$YY#O6WYGK[XYSZ/X[8_V=N?XNSW5U
-M#OF.]7?F^KLNSQ7NT/UWQOH[<_U=E[CK"G?H_CMC_9VY_JY+W'6%.W3_G;'^
-MSEQ_UUT.9X=\Q_H[<_U=.;LZAWS'^CMS_1V80[YC_9VY_@[,(=^Q_LY<?Y?G
-M^CJ'?,?Z.W/]79_G*G?(=ZR_,]??]8F[OG*'?,?Z.W/]79^XZRMWR'>LOS/7
-MW_67P]DAW['^SEQ_5\ZNSB'?L?[.7'\'YI#O6']GKK\[SJ'[[XSU=^;ZNSPW
-MU#GD.];?F>OOACQ7N$/WWQGK[\SU=T/B;BC<H?OOC/5WYOJ[(7$W%.[0_7?&
-M^CMS_=UP.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOH[,(=\Q_H[<_U=
-MGAOK'/(=Z^_,]7=CGJO<(=^Q_LY<?S<F[L;*'?(=Z^_,]7=CXFZLW"'?L?[.
-M7'\W7@YGAWS'^CMS_5TYNSJ'?,?Z.W/]'9A#OF/]G;G^[CB'[K\SUM^9Z^_R
-MW*<ZAWS'^CMS_=VG/%>X0_??&>OOS/5WGQ)WGPIWZ/X[8_V=N?[N4^+N4^$.
-MW7]GK+\SU]]]NAS.#OF.]7?F^KMR=G4.^8[U=^;Z.S"'?,?Z.W/]'9A#OF/]
-MG;G^+L]]KG/(=ZR_,]???<YSE3OD.];?F>OO/B?N/E?ND.]8?V>NO_N<N/M<
-MN4.^8_V=N?[N\^5P=LAWK+\SU]^5LZMSR'>LOS/7WX$YY#O6WYGK[XYSZ/X[
-M8_V=N?XNSWVI<\AWK+\SU]]]R7.%.W3_G;'^SEQ_]R5Q]Z5PA^Z_,];?F>OO
-MOB3NOA3NT/UWQOH[<_W=E\OA[)#O6']GKK\K9U?GD.]8?V>NOP-SR'>LOS/7
-MWX$YY#O6WYGK[_+<USJ'?,?Z.W/]W=<\5[E#OF/]G;G^[FOB[FOE#OF.]7?F
-M^KNOB;NOE3OD.];?F>OOOEX.9X=\Q_H[<_U=.;LZAWS'^CMS_1V80[YC_9VY
-M_NXXA^Z_,];?F>OO\MQUG4.^8_V=N?[N.L\5[M#]=\;Z.W/]W77B[KIPA^Z_
-M,];?F>OOKA-WUX4[=/^=L?[.7']W?3F<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.
-M^8[U=^;Z.S"'?,?Z.W/]79Z[J7/(=ZR_,]??W>2YRAWR'>OOS/5W-XF[F\H=
-M\AWK[\SU=S>)NYO*'?(=Z^_,]7<WE\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0
-M[UA_9ZZ_.\PU9_P4YJ[)G[BYVSH'?->P_JYQ_=UMGCN5.>"[NZ<P=XWK[VX3
-M=[>W90[XKF']7>/ZN]O$W>WO90[XKF']7>/ZN]O+X>S0G[==3IQ^X=L']^/;
-M;U??!]OOW]M&3^<)_)U_X=O?/CS^JPQ^O]?H3PS>O>%]/PSF-]Q^O]?H[A^X
-M^YC:],G=Q[W=TMM;I/XN^_@-WQ3SY3GTYT;_E?-#5Q']:+!M3]-T&/R__/K0
-M541_Y?5UVR_^_O;?@6G[4].>VNXTZ,^^PG__S[_<*[R?`S+X_[WA^SD@@\=S
-M^067WQ\/<S</YNR>OKHB#YYZR-W#SQ_,77]X\!MXCV10Y_X0X(:^0-_L+Y9!
-M?[AP\N'W^?N=S'8ZY_\_XRXZ+=_?4WU]*/!_]'9_\/I.Q[?[_5\P^L?_O#R8
-MT^#MGA[/??\7C`??ST??PN#TKH^O#OT!]W_EFW&X-O$G?^7^,?+X5^[]G/Y:
-J$0S?S?+';XL3^#O_PK=_?GC\U_U@DP9_V0DV=_2=S[_]%X1YCWBAJ```
+M'XL("%7N+50``VEM9RTV,W@R-34M-3$R+6UB<BYQ8V]W+F]U=`"MG<F.5=D1
+M1>?U%8\>DNY%Q&UI,E.6;,DS>V![6K<=OP]`_G8#>9K,N'L3E`M`I419=^N]
+MDXM%J5@ZG,]WWTZG5DY-=VK&TSZ?OOX\_9#3O9\\_''Z\L^__?W=_6]??KL;
+MD_,/GG(_[[<R]V#KOW5.OSVUG,[C3\Q]_2%H[MZKLS_PZNZ]V>/<U6]W;Q8_
+MIVS0'@R>TMPYO3XAI]?\W.N[=6]7[D[OU[U=)6^W_;G!?[C7IW\(EI]Z?7_P
+MZ]O!P=_+ZVO@4SV;&Q[,70YOMX5/C6QN^B',>N[@4S.;6X*Y'CZULKDMF!O@
+M4SN>DQ]\;>_F1OB4L#F%<Z<R-\&GC,TU#^;.:>ZVS,WP*?+K0AQW^==%Y6Z!
+M3Q'N).1NA4\1[B3D;H-/$>XDY&Z'3Q'N).).\%.$.XVX$Z0H9=QIQ)T@(ROC
+M3B/N!/E.&7<:<2?(=\JXTX@[0;Y3QIU&W`GRG3+N-.).D.^4<:<A=\AWRKBS
+MD#OD.V/<6<@=\ITQ[BSD#OG.&'<6<H=\9XP["[E#OC/&G87<(=\9X\Y"[I#O
+MC'%G$7>*GR+<-1%WBGS7,.Z:B#M%OFL8=TW$G2+?-8R[)N).D>\:QET3<:?(
+M=PWCKHFX4^2[AG'71-PI\EW#N&M"[I#O&L9=&W*'?-<R[MJ0.^2[EG'7AMPA
+MW[6,NS;D#OFN9=RU(7?(=RWCK@VY0[YK&7=MR!WR7<NX:R/N##]%N.LB[@SY
+MKF/<=1%WAGS7,>ZZB#M#ONL8=UW$G2'?=8R[+N+.D.\ZQET7<6?(=QWCKHNX
+M,^2[CG'7A=PAWW6,NS[D#OFN9]SU(7?(=SWCK@^Y0[[K&7=]R!WR7<^XZT/N
+MD.]ZQET?<H=\US/N^I`[Y+N><=='W#7X*<+=$''7(-\-C+LAXJY!OAL8=T/$
+M78-\-S#NAHB[!OEN8-P-$7<-\MW`N!LB[AKDNX%Q-T3<-<AW`^-N"+E#OAL8
+M=_E_S_,YY+N1<3>&W"'?C8R[,>0.^6YDW(TA=\AW(^-N#+E#OAL9=V/('?+=
+MR+@;0^Z0[T;&W1AQU^*G"'=3Q%V+?#<Q[J:(NQ;Y;F+<31%W+?+=Q+B;(NY:
+MY+N)<3=%W+7(=Q/C;HJX:Y'O)L;=%''7(M]-C+LIY`[Y;F+<Y3\FY7/(=S/C
+M;@ZY0[Z;&7=SR!WRW<RXFT/ND.]FQMT<<H=\-S/NYI`[Y+N9<3>'W"'?S8R[
+M.>*NPT\1[I:(NP[Y;F'<+1%W'?+=PKA;(NXZY+N%<;=$W'7(=POC;HFXZY#O
+M%L;=$G'7(=\MC+LEXJY#OEL8=TO('?+=PKA;0^Z0[U;&W1IRAWRW,N[6D#OD
+MNY5QMX;<(=^MC+LUY`[Y;F7<K2%WR'<KXVX-N4.^6QEW:\1=CY\BW)%`Z-X<
+M\MW&N-LB[GKDNXUQMT7<]<AW&^-NB[CKD>\VQMT6<=<CWVV,NRWBKD>^VQAW
+M6\1=CWRW,>ZVD#ODNXUQMX?<(=_MC+L]Y`[Y;F?<[2%WR'<[XVX/N4.^VQEW
+M>\@=\MW.N-M#[I#O=L;='G*'?+<S[O:(NP$_A;F3_`&?`[Z3,^%.SA%W`_"=
+MG`EW<HZX&X#OA/6!XON[`W<#\)VP_D["_FX`OA/6WTG8WPW`=\+Z.PG[NP'X
+M3EA_)V%_-P#?">OO).SO!N`[8?V=A/W=`'PGK+^3L+\;@.^$]7<2]G<#\)VP
+M_D["_FX`OA/6WTG8WPW`=\+Z.PG[NP'X3EA_)V%_-^*G"'=A?S<BW['^3L+^
+M;D2^8_V=A/W=B'S'^CL)^[L1^8[U=Q+V=R/R'>OO).SO1N0[UM])V-^-R'>L
+MOY.POQN1[UA_)V%_-R+?L?Y.POYN1+YC_9V$_=V(?,?Z.PG[NQ'YCO5W$O9W
+M(_(=Z^\D[.]&Y#O6WTG8WXW(=ZR_D["_F_!3A+NPOYN0[UA_)V%_-R'?L?Y.
+MPOYN0KYC_9V$_=V$?,?Z.PG[NPGYCO5W$O9W$_(=Z^\D[.\FY#O6WTG8WTW(
+M=ZR_D["_FY#O6'\G87\W(=^Q_D["_FY"OF/]G83]W81\Q_H["?N["?F.]7<2
+M]G<3\AWK[R3L[R;D.];?2=C?S?@IPEW8W\W(=ZR_D["_FY'O6'\G87\W(]^Q
+M_D["_FY&OF/]G83]W8Q\Q_H["?N[&?F.]7<2]G<S\AWK[R3L[V;D.];?2=C?
+MS<AWK+^3L+^;D>]8?R=A?S<CW['^3L+^;D:^8_V=A/W=C'S'^CL)^[L9^8[U
+M=Q+V=S/R'>OO).SO%OP4X2[L[Q;D.];?2=C?+<AWK+^3L+];D.]8?R=A?[<@
+MW['^3L+^;D&^8_V=A/W=@GS'^CL)^[L%^8[U=Q+V=POR'>OO).SO%N0[UM])
+MV-\MR'>LOY.POUN0[UA_)V%_MR#?L?Y.POYN0;YC_9V$_=V"?,?Z.PG[NP7Y
+MCO5W$O9W*WZ*<!?V=ROR'>OO).SO5N0[UM])V-^MR'>LOY.POUN1[UA_)V%_
+MMR+?L?Y.POYN1;YC_9V$_=V*?,?Z.PG[NQ7YCO5W$O9W*_(=Z^\D[.]6Y#O6
+MWTG8WZW(=ZR_D["_6Y'O6'\G87^W(M^Q_D["_FY%OF/]G83]W8I\Q_H["?N[
+M#3]%N`O[NPWYCO5W$O9W&_(=Z^\D[.\VY#O6WTG8WVW(=ZR_D["_VY#O6'\G
+M87^W(=^Q_D["_FY#OF/]G83]W89\Q_H["?N[#?F.]7<2]G<;\AWK[R3L[S;D
+M.];?2=C?;<AWK+^3L+_;D.]8?R=A?[<AW['^3L+^;D.^8_V=A/W=CI\BW(7]
+MW8Y\Q_H["?N['?F.]7<2]G<[\AWK[R3L[W;D.];?2=C?[<AWK+^3L+_;D>]8
+M?R=A?[<CW['^3L+^;D>^8_V=A/W=CGS'^CL)^[L=^8[U=Q+V=SOR'>OO).SO
+M=N0[UM])V-_MR'>LOY.PO]N1[UA_)V%_MR/?L?Y.HO[.SO@IS)WF#]S<J<X!
+MWWU]"G.GKK_+]_V=3F4.^$Y9?Z>NOSLE[DZW90[X3EE_IZZ_.R7N3K^7.>`[
+M9?V=NO[N=#F<'?"=LOY.77]7SJ[.`=\IZ^_4]7=@#OA.67^GKK\#<\!WROH[
+M=?U=GGM4YX#OE/5WZOJ[1WFN<@=\IZR_4]??/4K</:K<`=\IZ^_4]7>/$G>/
+M*G?`=\KZ.W7]W:/+X>R`[Y3U=^KZNW)V=0[X3EE_IZZ_`W/`=\KZ.W7]W7$.
+MW7^GK+]3U]_EN<=U#OF.]7?J^KO'>:YPA^Z_4];?J>OO'B?N'A?NT/UWROH[
+M=?W=X\3=X\(=NO].67^GKK][?#F<'?(=Z^_4]7?E[.H<\AWK[]3U=V`.^8[U
+M=^KZ.S"'?,?Z.W7]79Y[4N>0[UA_IZZ_>Y+G*G?(=ZR_4]??/4G</:G<(=^Q
+M_DY=?_<D<?>D<H=\Q_H[=?W=D\OA[)#O6'^GKK\K9U?GD.]8?Z>NOP-SR'>L
+MOU/7WQWGT/UWROH[=?U=GGM:YY#O6'^GKK][FN<*=^C^.V7]G;K^[FGB[FGA
+M#MU_IZR_4]??/4W</2W<H?OOE/5WZOJ[IY?#V2'?L?Y.77]7SJ[.(=^Q_DY=
+M?P?FD.]8?Z>NOP-SR'>LOU/7W^6Y9W4.^8[U=^KZNV=YKG*'?,?Z.W7]W;/$
+MW;/*'?(=Z^_4]7?/$G?/*G?(=ZR_4]??/;L<S@[YCO5WZOJ[<G9U#OF.]7?J
+M^CLPAWS'^CMU_=UQ#MU_IZR_4]??Y;GG=0[YCO5WZOJ[YWFN<(?NOU/6WZGK
+M[YXG[IX7[M#]=\KZ.W7]W?/$W?/"';K_3EE_IZZ_>WXYG!WR'>OOU/5WY>SJ
+M'/(=Z^_4]7=@#OF.]7?J^CLPAWS'^CMU_5V>>U'GD.]8?Z>NOWN1YRIWR'>L
+MOU/7W[U(W+VHW"'?L?Y.77_W(G'WHG*'?,?Z.W7]W8O+X>R0[UA_IZZ_*V=7
+MYY#O6'^GKK\#<\AWK+]3U]\=Y]#]=\KZ.W7]79Y[6>>0[UA_IZZ_>YGG"G?H
+M_CME_9VZ_NYEXNYEX0[=?Z>LOU/7W[U,W+TLW*'[[Y3U=^KZNY>7P]DAW['^
+M3EU_5\ZNSB'?L?Y.77\'YI#O6'^GKK\#<\AWK+]3U]_EN5=U#OF.]7?J^KM7
+M>:YRAWS'^CMU_=VKQ-VKRAWR'>OOU/5WKQ)WKRIWR'>LOU/7W[VZ',X.^8[U
+M=^KZNW)V=0[YCO5WZOH[,(=\Q_H[=?W=<0[=?Z>LOU/7W^6YJSJ'?,?Z.W7]
+MW56>*]RA^^^4]7?J^KNKQ-U5X0[=?Z>LOU/7WUTE[JX*=^C^.V7]G;K^[NIR
+M.#OD.];?J>OORMG5.>0[UM^IZ^_`'/(=Z^_4]7=@#OF.]7?J^KL\][K.(=^Q
+M_DY=?_<ZSU7ND.]8?Z>NOWN=N'M=N4.^8_V=NO[N=>+N=>4.^8[U=^KZN]>7
+MP]DAW['^3EU_5\ZNSB'?L?Y.77\'YI#O6'^GKK\[SJ'[[Y3U=^KZNSSWILXA
+MW['^3EU_]R;/%>[0_7?*^CMU_=V;Q-V;PAVZ_TY9?Z>NOWN3N'M3N$/WWRGK
+M[]3U=V\NA[-#OF/]G;K^KIQ=G4.^8_V=NOX.S"'?L?Y.77\'YI#O6'^GKK_+
+M<V_K'/(=Z^_4]7=O\USE#OF.]7?J^KNWB;NWE3OD.];?J>OOWB;NWE;ND.]8
+M?Z>NOWM[.9P=\AWK[]3U=^7LZASR'>OOU/5W8`[YCO5WZOJ[XQRZ_TY9?Z>N
+MO\MS[^H<\AWK[S3J[PS=?Z>LO].HOS-T_YVR_DZC_L[0_7?*^CN-^CM#]]\I
+MZ^\TZN\,W7^GK+_3J+\S=/^=LOY.H_[.T/UWROH[)?W=^SJ'?,?Z.W7]W?L\
+M5[E#OF/]G;K^[GWB[GWE#OF.]7?J^KOWB;OWE3OD.];?J>OOWE\.9X=\Q_H[
+M=?U=.;LZAWS'^CMU_1V80[YC_9VZ_NXXA^Z_4];?6?[`S9WK'/"=L?[NZR<>
+M<)?]="[<H?OOC/5WYOJ[<]H[%^[0_7?&^CMS_=TY<7<NW*'[[XSU=^;ZN_/E
+M<';`=\;Z.W/]73F[.@=\9ZR_,]??@3G@.V/]G;G^#LP!WQGK[\SU=WE.ZASP
+MG;'^SEQ_)WFN<@=\9ZR_,]??27IY4KD#OC/6WYGK[R1Q)Y4[X#MC_9VY_DXN
+MA[,#OC/6WYGK[\K9U3G@.V/]G;G^#LP!WQGK[\SU=\<Y=/^=L?[.7'^7Y[3.
+M(=^Q_LY<?Z=YKG"'[K\SUM^9Z^\T<:>%.W3_G;'^SEQ_IXD[+=RA^^^,]7?F
+M^CN]',X.^8[U=^;ZNW)V=0[YCO5WYOH[,(=\Q_H[<_T=F$.^8_V=N?XNSUF=
+M0[YC_9VY_L[R7.4.^8[U=^;Z.TO<6>4.^8[U=^;Z.TO<6>4.^8[U=^;Z.[L<
+MS@[YCO5WYOJ[<G9U#OF.]7?F^CLPAWS'^CMS_=UQ#MU_9ZR_,]??Y;FFSB'?
+ML?[.7'_7Y+G"';K_SEA_9ZZ_:Q)W3>$.W7]GK+\SU]\UB;NF<(?NOS/6WYGK
+M[YK+X>R0[UA_9ZZ_*V=7YY#O6']GKK\#<\AWK+\SU]^!.>0[UM^9Z^_R7%OG
+MD.]8?V>NOVOS7.4.^8[U=^;ZNS9QUU;ND.]8?V>NOVL3=VWE#OF.]7?F^KOV
+M<C@[Y#O6WYGK[\K9U3GD.];?F>OOP!SR'>OOS/5WQSET_YVQ_LY<?Y?GNCJ'
+M?,?Z.W/]79?G"G?H_CMC_9VY_JY+W'6%.W3_G;'^SEQ_UR7NNL(=NO_.6']G
+MKK_K+H>S0[YC_9VY_JZ<79U#OF/]G;G^#LPAW['^SEQ_!^:0[UA_9ZZ_RW-]
+MG4.^8_V=N?ZNSW.5.^0[UM^9Z^_ZQ%U?N4.^8_V=N?ZN3]SUE3OD.];?F>OO
+M^LOA[)#O6']GKK\K9U?GD.]8?V>NOP-SR'>LOS/7WQWGT/UWQOH[<_U=GAOJ
+M'/(=Z^_,]7=#GBO<H?OOC/5WYOJ[(7$W%.[0_7?&^CMS_=V0N!L*=^C^.V/]
+MG;G^;K@<S@[YCO5WYOJ[<G9U#OF.]7?F^CLPAWS'^CMS_1V80[YC_9VY_B[/
+MC74.^8[U=^;ZNS'/5>Z0[UA_9ZZ_&Q-W8^4.^8[U=^;ZNS%Q-U;ND.]8?V>N
+MOQLOA[-#OF/]G;G^KIQ=G4.^8_V=N?X.S"'?L?[.7']WG$/WWQGK[\SU=WGN
+M0YU#OF/]G;G^[D.>*]RA^^^,]7?F^KL/B;L/A3MT_YVQ_LY<?_<A<?>A<(?N
+MOS/6WYGK[SY<#F>'?,?Z.W/]73F[.H=\Q_H[<_T=F$.^8_V=N?X.S"'?L?[.
+M7'^7YS[6.>0[UM^9Z^\^YKG*'?(=Z^_,]7<?$W<?*W?(=ZR_,]???4S<?:S<
+M(=^Q_LY<?_?Q<C@[Y#O6WYGK[\K9U3GD.];?F>OOP!SR'>OOS/5WQSET_YVQ
+M_LY<?Y?G/M4YY#O6WYGK[S[EN<(=NO_.6']GKK_[E+C[5+A#]]\9Z^_,]7>?
+M$G>?"G?H_CMC_9VY_N[3Y7!VR'>LOS/7WY6SJW/(=ZR_,]??@3GD.];?F>OO
+MP!SR'>OOS/5W>>YSG4.^8_V=N?[N<YZKW"'?L?[.7'_W.7'WN7*'?,?Z.W/]
+MW>?$W>?*'?(=Z^_,]7>?+X>S0[YC_9VY_JZ<79U#OF/]G;G^#LPAW['^SEQ_
+M=YQ#]]\9Z^_,]7=Y[KK.(=^Q_LY<?W>=YPIWZ/X[8_V=N?[N.G%W7;A#]]\9
+MZ^_,]7?7B;OKPAVZ_\Y8?V>NO[N^',X.^8[U=^;ZNW)V=0[YCO5WYOH[,(=\
+MQ_H[<_T=F$.^8_V=N?XNS]W4.>0[UM^9Z^]N\ESE#OF.]7?F^KN;Q-U-Y0[Y
+MCO5WYOJ[F\3=3>4.^8[U=^;ZNYO+X>R0[UA_9ZZ_*V=7YY#O6']GKK\#<\AW
+MK+\SU]\=YIHS?@ISU^0/W-QMG0.^:UA_U[C^[C;/G<H<\-W7IS!WC>OO;A-W
+MM[=E#OBN8?U=X_J[V\3=[>]E#OBN8?U=X_J[V\OA[-#?MUU.G'[BRSOW[<MO
+M5]\'V^]?VT9/YPG\DW_BRU_>/?Q>!K_?:_0'!K^]83D,YC?<WMUK]+VMF]H$
+MWM>?WMDMO;U%ZN^R]]_PS1U\U^_NS:&_-_K/G!^ZBNA'@VU[FJ;#X+_RZT-7
+M$?V9U]=MO_CKVW\'INU/37MJN].@/_L*__/7?[M7>#<'9/#_O>&[.2"#AW/Y
+M!9??'P]S-_?FOLE@O_=OGN7>4_>YN__QO;GK=_=^`^^1#.K<-P%NZ!/TS?YB
+M&?2'"R?O?YV_W\ELIW/^\QEWT6GY^I[JZT.!_X.W^X/7=SJ^W>__@=$__/?E
+MWIP&;_?T<&XN9@%?PN#TKH^O#OT%]W_FBW&X-O$G?^5^&WGX*_=N3G^M"(;O
+G9OGVV^($_LD_\>4?[QY^OQMLTN`O.\'F*WWG\V__`[M'T1.AJ```
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu
index bb82f75..bea1353 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu
@@ -1,23 +1,22 @@
# $FreeBSD$
begin 644 img-63x255-512-mbr.qcow2.gz
-M'XL("+([(U0``VEM9RTV,W@R-34M-3$R+6UB<BYQ8V]W,BYO=70`K9C;DM,P
-M#$#?]RO,'18HL>2D"9<6%I89WN`!>$YO7]'AVTEJ-4H4*=YVTF8R[;@Z(]M'
-M:I(LBR_G<N]"X4+E#AO7?*<#7._+\'#'7]]_+/JOXTV$^<R(4@:6^PXW8/UC
-M'%BXS(\'O([K98<*#LY18U`*%\SLI@84W.W-:>E.FU&*"+P&&''F9ER5'\3\
-M9$2X,C^8.S_4UR\_Q\F!8CH_C/G)J*6%*Y,X4*(J"U<G<:A$;2S<-HD+2M3.
-MPAF5V\/E2M3!P/F$*@VN4**\A8,D;JE$H84+25RI1%G>^;1WE1)E>>?3WM5*
-ME.6=3WNW4:(L[WS:NZT297GGT][ME"C+.S"\<XS;*U&6=R"\>T2XQXP[*%&6
-M=R"\>T*XIQW.:U&6=R"\>T:XYXQ3^AU8WH'P[@7A7C).Z7=@>0?"NU>$NV6<
-MTN_`\@Z$=Z\)]X9Q2K\#RSL0WKT=>>>5?@>6=RB\>T>LC'%*OT/+.Q3>><(!
-MXY1^AY9W*+Q#P@7&*?T.+>]0>)<3KF"<TN_0\@Z%=TO"E8Q3^AU:WJ'PKB+<
-M>\8I_0XM[U!X]X%P'QFG]#NTO$/AW2?"K1BG]#NTO`O"NS7A/C-.Z7?!\BX(
-M[[X0[HYQ2K\+EG=!>/>5<-\Z'&A1G7=9IA^$NQ_5+,Q[_1GX^M@K9WM@`EA>
-M`IS*,.*J62><QPFW&M3*V1XXWBV&[PYX*K8+@,WZ'`XC($TXC\76_*`YZIP^
-M-$<L$)K>UG.9#2>\IE)CW&[F]3O5QP7`/'=U/0+^/N<'DVE<GM]R/_/^EO%Q
-MP[*MVKQP)3PTP[_W?\9"-[C9*CCB[,<--'!.N&NQ(]RZA\-H'U-Z=3KPKO^Y
-MAULMN-4WN,G'#>T]U%X;,">;SRM+V36KSM;>/K>7[NT=UOG?6UQZ=_OK.#^E
-M6<%@NA/YN?%TVZN"[NY=[$>+@\1TW1#7-JK^?@ZV,+%ZJW%VVYDWP\O*>&#E
-MMI!AY48<S-L(JE-G:0QL?C4^VP/'GXOA.P(#`6=;P5"T_VTW_P%@RS(](Q4`
-!````
+M'XL("%7N+50``VEM9RTV,W@R-34M-3$R+6UB<BYQ8V]W,BYO=70`K9C;DM,P
+M#$#?]RO,'18HL>3<N+2PL,SP!@_`<WK[B@[?3E(KL:-(\;:3-I-IQ]49V3Y2
+MDV29?QF36^,*XVISW)KV.QU@HB_CPYQ^??^QBE^G&P^SF1(E#)2'`3=B_0LX
+MT'"9G0Y8&1=EAP(.^J@I*(5S:G9S`P+N]N:\=.?-J%@$7@/T.'4SKLH/?'X\
+MPEV9'RR='\KKE_=Q?*"8SP]]?CRJU'!5$@="5*WAFB0.A:BMAMLE<4Z(VFLX
+MI7(C7"Y$'16<3:C2X@HARFHX2.)*(0HUG$OB*B%*\\ZFO:N%*,T[F_:N$:(T
+M[VS:NZT0I7EGT][MA"C-.YOV;B]$:=Z!XIT)N(,0I7D'S+M'A'L<<$<A2O,.
+MF'=/"/=TP%DI2O,.F'?/"/<\X(1^!YIWP+Q[0;B7`2?T.]"\`^;=*\+=!IS0
+M[T#S#IAWKPGW)N"$?@>:=\"\>SOQS@K]#C3OD'GWCEA9P`G]#C7OD'EG"0<!
+M)_0[U+Q#YAT2S@6<T.]0\PZ9=SGABH`3^AUJWB'SKB1<%7!"OT/-.V3>U81[
+M'W!"OT/-.V3>?2#<QX`3^AUJWB'S[A/AU@$G]#O4O'/,NPWA/@><T.^<YIUC
+MWGTAW%W`"?W.:=XYYMU7PGT;<"!%#=YEF7P0[GY2L[#L]:<+U\=6..L#,\#J
+M$N!<AAY7+SKAW$^XTZ`1SOK`Z6XU?@_`<[%=`*QH!<<XFG#NB\VO3I/WI6&I
+M0&AZ.QO*+)[PQI?'>A7A]@NOW[D^+@#FN6F:"?!WGQ_,IG%Y?N5AX?VM_..&
+MLJO:O#`5/#3#O_=_ID*WN,4JV./TQPTTT"<\M-@);A/ANBN68_3+N$Y'WL6?
+M(]QZ%5I]BYM]W-#=0QVD`76R^;*R5$.S&FR-]KF[=._NL/I_;W;I/>RO"?D)
+MS0I&TYW)STRGVUT5#'?O;#\Z'"2F:\:X[=!9A"U,K-YZFMUNX<VPO#(>6+D=
+L9%RY'@?+-H+ZW%E:`]M?3<_ZP.GG:OSV0$?`Q5;0%=U_V\U_7_5L5B,5````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu
index 894b95d..dc6c0cb 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu
@@ -1,12 +1,12 @@
# $FreeBSD$
begin 644 img-63x255-512-mbr.raw.gz
-M'XL("/K%'50``VEM9RTV,W@R-34M-3$R+6UB<BYR87<N;W5T`*V4O8[#(`S'
-M]SR%YPX(2&CHDDJ5;K^E[<SEDJ?(P]?$I#$E'XT$&(1D^.EO;)"2&D"E0;J%
-M>=TQW$3<A^)4C#3U=PQH)?1]`A0()%R+.-R`YDQ8H)4]>.$XT%H%91?69#"(
-ML5W]U`B&^W^?2FW=$7!SF\/MCP&-`><2X'W2IS=E'-=7=YGS:\>",354!LP9
-MK/Y6X?/G\:&0<"I7P(33>[A),%70$N[*<"55WTQ1[!2O.[YFN(;&A*NVU.%-
-MR&[)L1JLR5LL%GM\CN<95`>J!&F#3\?`=WYAUG=)9>@HW`U]D(;K/*Z.]RN&
-MTSOA0HSS'Q7/9Y3"G=MK4G5MYF2HSY?QY<OUD/CE$D[G_0@NX\^"%8B[TGG=
-8,?R*N!.P"L!L-^A_/BF+%Y?\>![E!@``
+M'XL("%;N+50``VEM9RTV,W@R-34M-3$R+6UB<BYR87<N;W5T`*V4S8Z$(`S'
+M[SY%SWL@!65E+DZRR=[WLC-GQM6G\.&W6'7*X,>80)%@"K_\2PN(W``J`^A7
+MQFW'\*5B&XJ/8J3IQSF@0T"=`!4!&=<2CA:03&_#6/;A-XS!@:&W]-]-<^XP
+M$$%=R:@U2N#^EEUIWW:,.-F>X?;G@-:"]PGP=]9G=F6<UU=WF?/KQH*Q-506
+M["<X\Z["^_?M12'C=*Z`&6>.<+-@KJ`UW%7@2G+V8B57XK1+UIV<"US#WXRK
+M]M3126"WYM@,UN8M%D<6[Y-Y!MV!+@'=Y#,Q<,DO//5=4ADF"G=''Z3A^H"K
+MX_5:X,Q!N!#C'LO+LI+"@]-K4G5MYF3HUYOQYLT-D/CF,L[D?0@NX\M"%4BK
+;TG';,?RHV!A83<!L)QA>/L3B'ZC")G7E!@``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
index 53ce054..251e27e 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-512-mbr.vhd.gz
-M'XL("/K%'50``VEM9RTV,W@R-34M-3$R+6UB<BYV:&0N;W5T`*V736_C(!"&
-M[_D5(^VM!PN/`=-+*E6;/5>JVIZQ:T<][+;:["$'__@R!FSP5YHMMF,1P3R\
-MPPQCP9B]`&0!L@79@!34+CG(6R@5@.ET#_;OW/V%KG[_T]3_WLZ9N[J=A>4L
-MM(K-R1X+X&:2$E#3)/*5VM!Y3/;C<+QY^WWT.'0X/S&7P!&$@?#9/(H-ZHCT
-MZ_[QYU1=,5<W6MEYVA:*-AA1A.JR["[$<6-EQM,CH>6]3/]$?Z*.$!>I$VQB
-M%<A<6M3`V26<W+*Z!G>S<[&PJ6(2HS1O!C*'$JEMTL:OP^PQJ7(^?>B_IV:B
-M#U=210;!F/;Q=7?1I0KZP4X!)X%;[D)/.4UQ"ZGRK=63L1UW#;,(3/@.[-V/
-M5V]$0:A/YFQCS=>#L:I/DSZSMYA>>*]W=/=9?`_`JKH.J)A5&.,&AZMZ<%B+
-MT2.[5]WZU3D4S6)`^FV[#]:O>DT<WZJ]#B@$:#T#/GE]]::,Z_4IE3B^JD\8
-M45(Y%Q(4?E7AR^%Y8?\JO5(._J_Z*8V7<%YP6.UCW%V`*VSVC92@.$5Y%[8#
-MW-[^/(YOJ:.:T"QUK#HK$B>+5A.[,,Z0-Y`7P)3KPQ@XQ!=&?;=S&1BYNZ$/
-MYNYJPI7Q^#S`X05W(<95[KOK1T8AO+!Z^[FZ.G$PJNG.^.+.)4B\<RT.TQ8"
-MW5<6DX%FU/R]WM$]9/%M@>@^1<F^;>B*:3*%W`&3*33`)K%"G?;[(9W"1`<%
-IPB4\*!`NX4&!<`D/"H1+>%`@7,*#`N&2'A2D.0(RMOL$5&JUB%T.````
+M'XL("%;N+50``VEM9RTV,W@R-34M-3$R+6UB<BYV:&0N;W5T`*V72V_<(!#'
+M[_LI1NHM!PN/`9/+KA0U/5>JVIZQ8T<Y]*%N#SGXPY<QX`6_-MO,FD58P(\_
+MS,-""/\#T!7H'G0'6E&[EJ#OH38`KC,4'.LRO,+0_OK9M7]?7HOP&PX>5HIT
+M5CZ=YF,%TBU2`UI:1#]1&X:(*3X\/M^]_'B..`RXN+#4(!&4@\C%.D9,ZHCT
+MZ>'+Q[FZ:JGN,LNOT_=0]<F(*E57%*<4)]TL-YZ*AEZ.,F/)7K*.%)>I4V(V
+M*Y&Y=JC)9M=P>F_6+;B[0["%=Q7G&+6K!>@2:J2V<YMX#HOB7.7U_-O^.7<S
+M?;CA*CHQQKQ/;F\7@ZM@'!P42!*XMUT8*><Y;L55WG5Z.I\G0\,=@E"Q`\?M
+MYZ=W04&J3Y=BY\RWC;&ISY(^%UO"KM3;'<-#D3\3L&EN`QKAHR/'31MNVA`=
+M`JRBFJ*T#+$:SJ]U[]V*04X^;(_)^35/S/9M^MN`2H&U"^#7J*_=E7&[/F.8
+M[6M&AU$UI7.EP>!;%7Y__+82O\9NI(/_RW[&XC5<%)QF^QQW2G"5#[<+)4E.
+MF=^E[01W]/^(DWOJ*"=T:QV;FU7,SF+-;%YJ9R@[*"L0)O1A#ISL"Q=]]TL9
+MF&UW1Q\LMVL)5^?CRP2'5[8+.:Z9,LN*":^<WG&IKF4V1C./C#=&+D'RR/4X
+MY$T$=LPLS@/=J&6]W3%\+O+'`S%\BMB^;1B2*9M"&8!L"AVP8U9H>;\?.BAD
+KNB@0CO&B0#C&BP+A&"\*A&.\*!".\:)`.-:+@G970"$._P"C#]GF70X`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu
index 7191855..0ba7533 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu
@@ -1,15 +1,15 @@
# $FreeBSD$
begin 644 img-63x255-512-mbr.vhdf.gz
-M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+6UB<BYV:&1F+F]U=`"ME;MNPR`4
-MAO<\Q9&Z9;"XFRR)%#6=*U5M9]?!48:V2X<.?OB"\85C?$DJ[&,+"_C\GPM`
-MB+\`!`-23+SG.^ICAN]ZL]TT-/IQ'U`3J*H(F%F@QY469P=8*V3;L,8K<,+M
-M8ZVDP$W;]@9UUEP']]IG`>[<SXIMOJ/%#=?@;G4?4$HHB@CXVNECBS+NUY>;
-MQ/G53<'('(0$J4"S6Q6^G]Y&"CV.IG+8X]@:KA/L*V@*=PAPW%??0*'!K+#N
-MPG:`V_NGPXDE=382Q$QUS#HKTQ:+MC>>%^89J`'*@>BVCV%@GU\8].UB&0RY
-MNZ`/8G<+A\OQ>!K@V(J[@'%NHPKSB5*X$KU]K*Y,G`PZ7ADWKEP'P2O7XUC:
-MC6#7["RV`NVH^#W?43]G^/9`T0*315"W9YOBH"I0!I1T[5R`VD&N0R##E527
-MWU^F_+G^AAEV.-H?1;&Y^8R[U:)R8(7[B3J[=J#OX7397C\O':[;JKH?"^6"
-M+BU$1.YJ[.[3\>5QK(['0=(H>G0X.'O'4?0.(4[TSAK3;(%T,/2!.B:W*H>3
-79#3KO[GU.)6X5.RYN_D#OC2Q.1`)````
+M'XL("%;N+50``VEM9RTV,W@R-34M-3$R+6UB<BYV:&1F+F]U=`"ME3UOPR`0
+MAO?\BI.Z9;```R9+(D5-YTI5V]EQ<)0A[=*A@W]\[XSM@+'S46$(PCIX\AYW
+MG!ES#X`4P,J)<=[0;+.P-8OEHJ7Q_6-`PX#Q")@AT.$JQ.$"E%DJ&O.:7FDD
+M`Z->X;OMYJY#@X1L@PV?=>;A#L.NN,\;6IS_7-RM'P,J!649`=][?>*JC,?U
+M%39Q?$V;,*H`J4!I,.)>A9^[CY%"A^.I''8X<0O7"W89-(7;>+@<C;6WTF5B
+MM\O/.W_NX=;NU^/D-75X$LQ.&6:=56F3Q6`+]_EQ!FZ!Y\!,9Q,A<(@O7/2M
+M8ADB</>*/HC=+0E7A.NYAQ,WW(40MQ\JRT0(;YS>.E97)0X&']^,.V\N0<*;
+MZW`B;2%8M94%,Q!7Q>.\H7G-PN:`L@,F.T'3?=MT#KH&;4$KFA<2]`H*XP-%
+MF$E-]?UEJY_3KQ]APG%7#"8[[1<YW19=@"CI3_2!YIZ^I]UQ>3H?>UQ?JOH_
+MEIH.72%$1NZ:T-V7[=OS6%T>'Y()3H^33K_LH>/!Z6U\G!R<M;8M@?S2@Y?`
+<,%FJ"*?8:-=_8^MP.G&JX'=W\0?-HVE+$`D`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu
index 0c79f43..fe22486 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu
@@ -1,6 +1,6 @@
# $FreeBSD$
begin 644 img-63x255-512-mbr.vmdk.gz
-M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+6UB<BYV;61K+F]U=`"M7-%NY,81
+M'XL("%?N+50``VEM9RTV,W@R-34M-3$R+6UB<BYV;61K+F]U=`"M7-%NY,81
M?/=7#.2W/"Q8RR6Y?#@[<<X!@B"`$3OV:\CE,!9BWQUT0I`#]/'AD%.C(D4>
M::MUJP/[V%W;W4.U=-4%9=GTX=RE=9>+NW2N*%T&-_S3]')9_FP,KTNZ\?2W
MMW__\<2//YY.3U],8`A1$H),X<28O<_3:?%!N//GHF8WAM=Y%RX/4>V+P`AW
@@ -74,11 +74,11 @@ M(9'6Y29R2*1UN8D<$ER7V\@AP76YC1P2WE0."6\JAX0WE4/"F\HAX4WED/"F
M<DAX4SDDO*D<$MY4#@EO*H>$-Y5#PIO*(>%-Y9#PIG)(]%EF*(=$;RJ'1&\J
MAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'
M1&\JAT1O*H<\9UEF*(<\9Z9RR//+7TU\#.YEL9/<\#*6._WNTI=_;]]X^N8T
-M_Y,`T?XVP.%!Z/L7@"SX@O`H#P[#JRGBQ?#*>RGX!I?[U8*_#G]]=1*XSKA_
-MZ'\;8%&XIGD!^$_F=_YL&K\]O\H;G^]U?&"**OR:W:)TU_/1#'_Z]L=%AA.<
-MF7YV@MO]^D@L:+\%][7`Y=/3]XRBOPE<GSN]%KBOID_"73Z7G2ZHCA5K_*N[
-MK]EU$:?G'+[O!#J0_\L[SP'3^;KG_.J7:9QGY7XF/_>RW/`]5W]YK9[';$QO
-ME.OF<&%0Z7G.CG"G>U^]S.YF?!A8?F4<_,H-(/.OW`GN;#L(ZG&R3*J/EW]O
-=WWCZ[C3_,P%>(J!9!R_A%Y-D7_P?*H?3&&]@````
+M_Y,`T?XVP$D0MP1DP1>,C_+(?C7C_PGS/IAY+P7?!MNO%/SU\&?X^.HD<)UQ
+M_]#_-L"B<$WS`O"?S._\V31^>WZ5-S[?Z_C`%%7X-;M%Z:[GHQG^].V/BPPG
+M.#/][`2W^_616-!^"^YK@0L_#_3B.?M-X/K<Z;7`?35]$N[RN>QT076L6.-?
+MW7W-KHLX/>?P?2?0@?Q?WGD.F,[7/>=7OTSC/"OW,_FYE^6&[[GZRVOU/&9C
+M>J-<-X=KTV19.<*=[GWU,KN;\6%@^95Q\"LW@,R_<B>XL^T@J,?),JD^7OZ]
+=?>/IN]/\SP1XB8!F';R$7TR2??%_%;F-<V]@````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu
index 8572850..75e7cd5 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu
@@ -1,126 +1,126 @@
# $FreeBSD$
begin 644 img-63x255-512-pc98.qcow.gz
-M'XL("+TS(E0``VEM9RTV,W@R-34M-3$R+7!C.3@N<6-O=RYO=70`K9W+CAQ'
-MDD7W^HKD^TVFF45D1/"-!J:!WG$6,[/M?*[U`<1\^U"D5WB5Y;DR:D2*$"AD
-MQT6FUZDCHG7@W&Y__-AL1ML,N\VP;"Z'S;=_;C]M<^L?[O[<?/W/?_[K]>T?
-M7W_[,6;;/WDJ_?-T7N?N;/UOG_,_GCINMLM/S'W[:31WZ]W%7WAWMS[L]=SS
-MWWY\6'[.U6#<&=RTN6U[?R9.;_BY]_<Y?5S[<7J_[N.Z^+BC&MS=&?S2YO[=
-MWI__)5A^ZOW]Q:_OA(._K^]OP*=F-;?\*7V^'?&IO9H[%',[?.JHYD[%W(1/
-MG=7<I9B;X2E37PHKOG-]N^!3XAO-BF\TW^[Q*?&-9C>$IV^T+^O<`9_:J;F[
-MW/W[BKLC/B6XLY*[$SXEN+.2NS,^);BSDKL+/B6XLXH[HZ=<<><5=T:*<L6=
-M5]P9&=D5=UYQ9^0[5]QYQ9V1[UQQYQ5W1KYSQ9U7W!GYSA5W7G%GY#M7W'G)
-M'?DN%'=1<D>^"\5=E-R1[T)Q%R5WY+M0W$7)'?DN%'=1<D>^"\5=E-R1[T)Q
-M%R5WY+M0W$7%G=-3@^)NJ+AS\MV@N!LJ[IQ\-RCNAHH[)]\-BKNAXL[)=X/B
-M;JBX<_+=H+@;*NZ<?#<H[H:*.R??#8J[H>2.?#<J[L:2._+=J+@;2^[(=Z/B
-M;BRY(]^-BKNQY(Y\-RKNQI([\MVHN!M+[LAWH^)N++DCWXV*N['B+NBIG>)N
-M5W$7Y+N=XFY7<1?DNYWB;E=Q%^2[G>)N5W$7Y+N=XFY7<1?DNYWB;E=Q%^2[
-MG>)N5W$7Y+N=XFY7<D>^FQ1W4\D=^6Y2W$TE=^2[27$WE=R1[R;%W51R1[Z;
-M%'=3R1WY;E+<325WY+M)<3>5W)'O)L7=5'$WT%.SXFZNN!O(=[/B;JZX&\AW
-ML^)NKK@;R'>SXFZNN!O(=[/B;JZX&\AWL^)NKK@;R'>SXFZNN!O(=[/B;BZY
-M(]_=_+_P\$+%'?EN4=PM)7?DNT5QMY3<D>\6Q=U2<D>^6Q1W2\D=^6Y1W"TE
-M=^2[17&WE-R1[Q;%W5)Q-])3>\7=ON)N)-_M%7?[BKN1?+=7W.TK[D;RW5YQ
-MMZ^X&\EW>\7=ON)N)-_M%7?[BKN1?+=7W.TK[D;RW5YQMR^Y(]_=_-=0>*'B
-MCGQW4-P=2N[(=P?%W:'DCGQW4-P=2N[(=P?%W:'DCGQW4-P=2N[(=P?%W:'D
-MCGQW4-P=*NYV]-11<7>LN-N1[XZ*NV/%W8Y\=U3<'2ON=N2[H^+N6'&W(]\=
-M%7?'BKL=^>ZHN#M6W.W(=T?%W;'B;D>^.RKNCB5WY+N3XNY4<D>^.RGN3B5W
-MY+N3XNY4<D>^.RGN3B5WY+N3XNY4<D>^.RGN3B5WY+N3XNY4<D>^.RGN3A5W
-M$SVU=D#7+Q3<3>2[L^+N7'$WD>_.BKMSQ=U$OCLK[LX5=Q/Y[JRX.U?<3>2[
-ML^+N7'$WD>_.BKMSQ=U$OCLK[LXE=^2[B^+N4G)'OKLH[BXE=^2[B^+N4G)'
-MOKLH[BXE=^2[B^+N4G)'OKLH[BXE=^2[B^+N4G)'OKLH[BX5=S,\93>_@!<*
-M[F;PG:G@T*K@T&?PG:G@T+85=S/XSK:".\O]W15W,_C.5']G97\W@^],]7=6
-M]G<S^,Y4?V=E?S>#[TSU=U;V=S/XSE1_9V5_-X/O3/5W5O9W,_C.5']G97\W
-M@^],]7=6]G<S^,Y4?V=E?S>#[TSU=U;V=S/XSE1_9V5_-X/O3/5W5O9W"SVE
-M^CLK^[N%?*?Z.RO[NX5\I_H[*_N[A7RG^CLK^[N%?*?Z.RO[NX5\I_H[*_N[
-MA7RG^CLK^[N%?*?Z.RO[NX5\I_H[*_N[A7RG^CLK^[N%?*?Z.RO[NX5\I_H[
-M*_N[A7RG^CLK^[N%?*?Z.RO[NX5\I_H[*_N[A7RG^CLK^[L]/:7Z.RO[NSWY
-M3O5W5O9W>_*=ZN^L[._VY#O5WUG9W^W)=ZJ_L[*_VY/O5']G97^W)]^I_L[*
-M_FY/OE/]G97]W9Y\I_H[*_N[/?E.]7=6]G=[\IWJ[ZSL[_;D.]7?6=G?[<EW
-MJK^SLK_;D^]4?V=E?[<GWZG^SLK^;D^^4_V=E?W=@9Y2_9V5_=V!?*?Z.RO[
-MNP/Y3O5W5O9W!_*=ZN^L[.\.Y#O5WUG9WQW(=ZJ_L[*_.Y#O5']G97]W(-^I
-M_L[*_NY`OE/]G97]W8%\I_H[*_N[`_E.]7=6]G<'\IWJ[ZSL[P[D.]7?6=G?
-M'<AWJK^SLK\[D.]4?V=E?W<@WZG^SLK^[DA/J?[.RO[N2+Y3_9V5_=V1?*?Z
-M.RO[NR/Y3O5W5O9W1_*=ZN^L[.^.Y#O5WUG9WQW)=ZJ_L[*_.Y+O5']G97]W
-M)-^I_L[*_NY(OE/]G97]W9%\I_H[*_N[(_E.]7=6]G='\IWJ[ZSL[X[D.]7?
-M6=G?'<EWJK^SLK\[DN]4?V=E?W>BIU1_9V5_=R+?J?[.RO[N1+Y3_9V5_=V)
-M?*?Z.RO[NQ/Y3O5W5O9W)_*=ZN^L[.].Y#O5WUG9WYW(=ZJ_L[*_.Y'O5']G
-M97]W(M^I_L[*_NY$OE/]G97]W8E\I_H[*_N[$_E.]7=6]G<G\IWJ[ZSL[T[D
-M.]7?6=G?G<AWJK^SLK\[TU.JO[.ROSN3[U1_9V5_=R;?J?[.RO[N3+Y3_9V5
-M_=V9?*?Z.RO[NS/Y3O5W5O9W9_*=ZN^L[._.Y#O5WUG9WYW)=ZJ_L[*_.Y/O
-M5']G97]W)M^I_L[*_NY,OE/]G97]W9E\I_H[*_N[,_E.]7=6]G=G\IWJ[ZSL
-M[\[D.]7?6=G?7>@IU=]9V=]=R'>JO[.RO[N0[U1_9V5_=R'?J?[.RO[N0KY3
-M_9V5_=V%?*?Z.RO[NPOY3O5W5O9W%_*=ZN^L[.\NY#O5WUG9WUW(=ZJ_L[*_
-MNY#O5']G97]W(=^I_L[*_NY"OE/]G97]W85\I_H[*_N["_E.]7=6]G<7\IWJ
-M[ZSJ[V(+3_G-+^"%.]S=<++I<^`[5_V=I_YNT_8VVW4.?.>JO_/4WVT:=YLO
-MZQSXSE5_YZF_VS3N-K^O<^`[5_V=I_X.S@Y\YZJ_\]3?P1SXSE5_YZF_@SGP
-MG:O^SE-_!W/@.U?]G:?^[EZ;N]?GP'>N^CM/_=V]]O;N=>[`=Z[Z.T_]W;W&
-MW;W.'?C.57_GJ;^[U[B[U[D#W[GJ[SSU=W!VX#M7_9VG_@[FP'>N^CM/_1W,
-M@>]<]7>>^KOK.;K_SE5_YZF_N]_F[O<Y\IWJ[SSU=_<;=_=7[NC^.U?]G:?^
-M[G[C[O[*'=U_YZJ_\]3?W6_<W5^YH_OO7/5WGOH[.#ORG>KO//5W,$>^4_V=
-MI_X.YLAWJK_SU-_!'/E.]7>>^KL';>Y!GR/?J?[.4W_WH''WH'-'OE/]G:?^
-M[D'C[D'GCGRG^CM/_=V#QMV#SAWY3O5WGOH[.#ORG>KO//5W,$>^4_V=I_X.
-MYLAWJK_SU-]=S]']=Z[Z.T_]W<,V][#/D>]4?^>IOWO8N'NX<D?WW[GJ[SSU
-M=P\;=P]7[NC^.U?]G:?^[F'C[N'*'=U_YZJ_\]3?P=F1[U1_YZF_@SGRG>KO
-M//5W,$>^4_V=I_X.YLAWJK_SU-\]:G./^ASY3O5WGOJ[1XV[1YT[\IWJ[SSU
-M=X\:=X\Z=^0[U=]YZN\>->X>=>[(=ZJ_\]3?P=F1[U1_YZF_@SGRG>KO//5W
-M,$>^4_V=I_[N>H[NOW/5WWGJ[QZWN<=]CGRG^CM/_=WCQMWCE3NZ_\Y5?^>I
-MOWO<N'N\<D?WW[GJ[SSU=X\;=X]7[NC^.U?]G:?^#LZ.?*?Z.T_]'<R1[U1_
-MYZF_@SGRG>KO//5W,$>^4_V=I_[N29M[TN?(=ZJ_\]3?/6G</>G<D>]4?^>I
-MOWO2N'O2N2/?J?[.4W_WI''WI'-'OE/]G:?^#LZ.?*?Z.T_]'<R1[U1_YZF_
-M@SGRG>KO//5WUW-T_YVK_LY3?_>TS3WM<^0[U=]YZN^>-NZ>KMS1_7>N^CM/
-M_=W3QMW3E3NZ_\Y5?^>IOWO:N'NZ<D?WW[GJ[SSU=W!VY#O5WWGJ[V".?*?Z
-M.T_]'<R1[U1_YZF_@SGRG>KO//5WS]K<LSY'OE/]G:?^[EGC[EGGCGRG^CM/
-M_=VSQMVSSAWY3O5WGOJ[9XV[9YT[\IWJ[SSU=W!VY#O5WWGJ[V".?*?Z.T_]
-M'<R1[U1_YZF_NYZC^^]<]7>>^KOG;>YYGR/?J?[.4W_WO''W?.6.[K]SU=]Y
-MZN^>-^Z>K]S1_7>N^CM/_=WSQMWSE3NZ_\Y5?^>IOX.S(]^I_LY3?P=SY#O5
-MWWGJ[V".?*?Z.T_]'<R1[U1_YZF_>]'F7O0Y\IWJ[SSU=R\:=R\Z=^0[U=]Y
-MZN]>-.Y>=.[(=ZJ_\]3?O6C<O>C<D>]4?^>IOX.S(]^I_LY3?P=SY#O5WWGJ
-M[V".?*?Z.T_]W?4<W7_GJK_SU-^];',O^QSY3O5WGOJ[EXV[ERMW=/^=J_[.
-M4W_WLG'W<N6.[K]SU=]YZN]>-NY>KMS1_7>N^CM/_1V<'?E.]7>>^CN8(]^I
-M_LY3?P=SY#O5WWGJ[V".?*?Z.T_]W:LV]ZK/D>]4?^>IOWO5N'O5N2/?J?[.
-M4W_WJG'WJG-'OE/]G:?^[E7C[E7GCGRG^CM/_1V<'?E.]7>>^CN8(]^I_LY3
-M?P=SY#O5WWGJ[Z[GZ/X[5_V=5_U=T/UWKOH[K_J[H/OO7/5W7O5W0???N>KO
-MO.KO@NZ_<]7?>=7?!=U_YZJ_\ZJ_"[K_SE5_YU5_%W3_G:O^SJO^+NC^.U?]
-MG:?^[DW;>M/GR'>JO_/4W[UIW+WIW)'O5'_GJ;][T[A[T[DCWZG^SE-_]Z9Q
-M]Z9S1[Y3_9VG_@[.CGRG^CM/_1W,D>]4?^>IOX,Y\IWJ[SSU=]=S=/]=W/P"
-M7KC#W;;-;?L<^.[;4\Q=I/YNV[C;KMS1_7>A^KM(_=VV<;==N:/[[T+U=Y'Z
-MNVWC;KMR1_??A>KO(O5W<';@NU#]7:3^#N;`=Z'ZNTC]'<R![T+U=Y'Z.Y@#
-MWX7J[R+U=];FK,^![T+U=Y'Z.VO<6><.?!>JOXO4WUGCSCIWX+M0_5VD_LX:
-M=]:Y`]^%ZN\B]7=P=N"[4/U=I/X.YL!WH?J[2/T=S('O0O5WD?J[ZSFZ_RY4
-M?Q>IO_,VYWV.?*?ZNTC]G3?N?.6.[K\+U=]%ZN^\<><K=W3_7:C^+E)_YXT[
-M7[FC^^]"]7>1^CLX._*=ZN\B]7<P1[Y3_5VD_@[FR'>JOXO4W\$<^4[U=Y'Z
-MNVAST>?(=ZJ_B]3?1>,N.G?D.]7?1>KOHG$7G3ORG>KO(O5WT;B+SAWY3O5W
-MD?H[.#ORG>KO(O5W,$>^4_U=I/X.YLAWJK^+U-]=S]']=Z'ZNTC]W=#FACY'
-MOE/]7:3^;FC<#2MW=/]=J/XN4G\W-.Z&E3NZ_RY4?Q>IOQL:=\/*'=U_%ZJ_
-MB]3?P=F1[U1_%ZF_@SGRG>KO(O5W,$>^4_U=I/X.YLAWJK^+U-^-;6[L<^0[
-MU=]%ZN_&QMW8N2/?J?XN4G\W-N[&SAWY3O5WD?J[L7$W=N[(=ZJ_B]3?P=F1
-M[U1_%ZF_@SGRG>KO(O5W,$>^4_U=I/[N>H[NOPO5WT7J[W9M;M?GR'>JOXO4
-MW^T:=[N5.[K_+E1_%ZF_VS7N=BMW=/]=J/XN4G^W:]SM5N[H_KM0_5VD_@[.
-MCGRG^KM(_1W,D>]4?Q>IOX,Y\IWJ[R+U=S!'OE/]7:3^;FIS4Y\CWZG^+E)_
-M-S7NILX=^4[U=Y'ZNZEQ-W7NR'>JOXO4WTV-NZES1[Y3_5VD_@[.CGRG^KM(
-M_1W,D>]4?Q>IOX,Y\IWJ[R+U=]=S=/]=J/XN4G\WM[FYSY'O5'\7J;^;&W?S
-MRAW=?Q>JOXO4W\V-NWGECNZ_"]7?1>KOYL;=O')']]^%ZN\B]7=P=N0[U=]%
-MZN]@CGRG^KM(_1W,D>]4?Q>IOX,Y\IWJ[R+U=TN;6_H<^4[U=Y'ZNZ5QMW3N
-MR'>JOXO4WRV-NZ5S1[Y3_5VD_FYIW"V=._*=ZN\B]7=P=N0[U=]%ZN]@CGRG
-M^KM(_1W,D>]4?Q>IO[N>H_OO0O5WD?J[MVWN;9\CWZG^+E)_][9Q]W;ECNZ_
-M"]7?1>KOWC;NWJ[<T?UWH?J[2/W=V\;=VY4[NO\N5'\7J;^#LR/?J?XN4G\'
-M<^0[U=]%ZN]@CGRG^KM(_1W,D>]4?Q>IOWO7YM[U.?*=ZN\B]7?O&G?O.G?D
-M.]7?1>KOWC7NWG7NR'>JOXO4W[UKW+WKW)'O5'\7J;^#LR/?J?XN4G\'<^0[
-MU=]%ZN]@CGRG^KM(_=WU'-U_%ZJ_B]3?O6]S[_L<^4[U=Y'ZN_>-N_<K=W3_
-M7:C^+E)_][YQ]W[ECNZ_"]7?1>KOWC?NWJ_<T?UWH?J[2/T=G!WY3O5WD?H[
-MF"/?J?XN4G\'<^0[U=]%ZN]@CGRG^KM(_=V'-O>ASY'O5'\7J;_[T+C[T+DC
-MWZG^+E)_]Z%Q]Z%S1[Y3_5VD_NY#X^Y#YXY\I_J[2/T=G!WY3O5WD?H[F"/?
-MJ?XN4G\'<^0[U=]%ZN^NY^C^NU#]7:3^[F.;^]CGR'>JOXO4WWULW'U<N:/[
-M[T+U=Y'ZNX^-NX\K=W3_7:C^+E)_][%Q]W'ECNZ_"]7?1>KOX.S(=ZJ_B]3?
-MP1SY3O5WD?H[F"/?J?XN4G\'<^0[U=]%ZN\^M;E/?8Y\I_J[2/W=I\;=I\X=
-M^4[U=Y'ZNT^-NT^=._*=ZN\B]7>?&G>?.G?D.]7?1>KOX.S(=ZJ_B]3?P1SY
-M3O5WD?H[F"/?J?XN4G]W-3=LX:GAYA?PPAWN;H+>SWT.?#>H_N[;"W>X^]RX
-M^[Q=Y\!W@^KOAM3??6YO[_.7=0Y\-ZC^;DC]W>?&W>??USGPW:#ZNR'U=W!V
-M].=MJR]%?^'KZ_3CZV_/OP^.W[^V@V^V>_B[?N'K/U[?_6L=_'XWSU\8',?-
-M_GKPO]H''K_?S;,,F^-`G^MRZ3^K#_QCCOZL][]S?L,O/K^)OMG^SCN<SK_X
-M'<[?W^$X;89Q,^XVL__L._R?__AO^)+,I(/_WP?^,0<ZN#MW\X;CHN8^W9J+
-M'YCU%;OUU-'Z;_QN__K6W,?7M_X5/I,.^MP?XCS3"_+#_F(=S%=73M[^.G^_
-MRSDVVYO_=.-W!]>O[Z:_/TK\[WS</WE_F^N/^_VW&-/=_[W=FO/BXV[NSGW_
-M+<:MK^>=+V%Q>A^OWQW]$?=_YXMQ=7'B3W[G_C%R]SOWQYS_6A$LW\WRQ[].
-B]_!W_<+7+Z_O_O5C<&B#O^P$AV^X;+>__1^"\<L6HZ@`````
+M'XL("%?N+50``VEM9RTV,W@R-34M-3$R+7!C.3@N<6-O=RYO=70`K9W;CA19
+M<T;OYRF*,S2GBHC,JDP.W<B2+?D.7]B^_>MX/0^`_.R&9G?N[JCU33`:&#0"
+M%?DI*VOU`LTL;=;KG]]6J]%6PV8US*OS?O7]Y^V[K>[]Y.'WU;?_^H__?'?_
+MV[<_?H[9^B^N2C_?GI:Y!UO_U^?\QU6'U7K^A;GOWXWF[MU=_(V[N_=F+^>N
+M_OCY9ODZ5X/Q8'#5YM;M_DP\O>'7[N]+>KOV\^G]OK?KXNV.:G#S8/!KF_M7
+MNS__6[#\TOW]S<]WBX-_+O<WX%63FIO_DCY?CWC53LWMB[D-7G50<\=B;HM7
+MG=3<N9B;X"I3'X457[F^GO$J\85FQ1>:KW=XE?A"LSO"TQ?:UV5NCU=MU-Q#
+M[OYUP=T!KQ+<6<G=$:\2W%G)W0FO$MQ9R=T9KQ+<6<6=T56NN/.*.R-%N>+.
+M*^Z,C.R*.Z^X,_*=*^Z\XL[(=ZZX\XH[(]^YXLXK[HQ\YXH[K[@S\ITK[KSD
+MCGP7BKLHN2/?A>(N2N[(=Z&XBY([\ETH[J+DCGP7BKLHN2/?A>(N2N[(=Z&X
+MBY([\ETH[J+BSNFJ07$W5-PY^6Y0W`T5=TZ^&Q1W0\6=D^\&Q=U0<>?DNT%Q
+M-U3<.?EN4-P-%7=.OAL4=T/%G9/O!L7=4')'OAL5=V/)'?EN5-R-)7?DNU%Q
+M-Y;<D>]&Q=U8<D>^&Q5W8\D=^6Y4W(TE=^2[47$WEMR1[T;%W5AQ%W351G&W
+MJ;@+\MU&<;>IN`ORW49QMZFX"_+=1G&WJ;@+\MU&<;>IN`ORW49QMZFX"_+=
+M1G&WJ;@+\MU&<;<IN2/?;15WVY([\MU6<;<MN2/?;15WVY([\MU6<;<MN2/?
+M;15WVY([\MU6<;<MN2/?;15WVY([\MU6<;>MN!OHJDEQ-U7<#>2[27$W5=P-
+MY+M)<3=5W`WDNTEQ-U7<#>2[27$W5=P-Y+M)<3=5W`WDNTEQ-U7<#>2[27$W
+ME=R1[^[^*SR\4'%'OIL5=W/)'?EN5MS-)7?DNUEQ-Y?<D>]FQ=U<<D>^FQ5W
+M<\D=^6Y6W,TE=^2[67$W5]R-=-5.<;>KN!O)=SO%W:[B;B3?[11WNXJ[D7RW
+M4]SM*NY&\MU.<;>KN!O)=SO%W:[B;B3?[11WNXJ[D7RW4]SM2N[(=W?_-Q1>
+MJ+@CW^T5=_N2._+=7G&W+[DCW^T5=_N2._+=7G&W+[DCW^T5=_N2._+=7G&W
+M+[DCW^T5=_N*NPU==5#<'2KN-N2[@^+N4'&W(=\=%'>'BKL-^>Z@N#M4W&W(
+M=P?%W:'B;D.^.RCN#A5W&_+=07%WJ+C;D.\.BKM#R1WY[JBX.Y;<D>^.BKMC
+MR1WY[JBX.Y;<D>^.BKMCR1WY[JBX.Y;<D>^.BKMCR1WY[JBX.Y;<D>^.BKMC
+MQ=V6KEHZH,L7"NZVY+N3XNY4<;<EWYT4=Z>*NRWY[J2X.U7<;<EW)\7=J>)N
+M2[X[*>Y.%7=;\MU)<7>JN-N2[TZ*NU/)'?GNK+@[E]R1[\Z*NW/)'?GNK+@[
+ME]R1[\Z*NW/)'?GNK+@[E]R1[\Z*NW/)'?GNK+@[E]R1[\Z*NW/%W017V=T/
+MX(6"NPE\9RHXM"HX]`E\9RHXM'7%W02^L[7@SG)_=\'=!+XSU=]9V=]-X#M3
+M_9V5_=T$OC/5WUG9WTW@.U/]G97]W02^,]7?6=G?3>`[4_V=E?W=!+XSU=]9
+MV=]-X#M3_9V5_=T$OC/5WUG9WTW@.U/]G97]W02^,]7?6=G?3>`[4_V=E?W=
+M3%>I_L[*_FXFWZG^SLK^;B;?J?[.ROYN)M^I_L[*_FXFWZG^SLK^;B;?J?[.
+MROYN)M^I_L[*_FXFWZG^SLK^;B;?J?[.ROYN)M^I_L[*_FXFWZG^SLK^;B;?
+MJ?[.ROYN)M^I_L[*_FXFWZG^SLK^;B;?J?[.ROYN)M^I_L[*_FY'5ZG^SLK^
+M;D>^4_V=E?W=CGRG^CLK^[L=^4[U=U;V=SORG>KOK.SO=N0[U=]9V=_MR'>J
+MO[.RO]N1[U1_9V5_MR/?J?[.ROYN1[Y3_9V5_=V.?*?Z.RO[NQWY3O5W5O9W
+M._*=ZN^L[.]VY#O5WUG9W^W(=ZJ_L[*_VY'O5']G97^WIZM4?V=E?[<GWZG^
+MSLK^;D^^4_V=E?W=GGRG^CLK^[L]^4[U=U;V=WORG>KOK.SO]N0[U=]9V=_M
+MR7>JO[.RO]N3[U1_9V5_MR??J?[.ROYN3[Y3_9V5_=V>?*?Z.RO[NSWY3O5W
+M5O9W>_*=ZN^L[._VY#O5WUG9W^W)=ZJ_L[*_.]!5JK^SLK\[D.]4?V=E?W<@
+MWZG^SLK^[D"^4_V=E?W=@7RG^CLK^[L#^4[U=U;V=P?RG>KOK.SO#N0[U=]9
+MV=\=R'>JO[.ROSN0[U1_9V5_=R#?J?[.RO[N0+Y3_9V5_=V!?*?Z.RO[NP/Y
+M3O5W5O9W!_*=ZN^L[.\.Y#O5WUG9WQWI*M7?6=G?'<EWJK^SLK\[DN]4?V=E
+M?W<DWZG^SLK^[DB^4_V=E?W=D7RG^CLK^[LC^4[U=U;V=T?RG>KOK.SOCN0[
+MU=]9V=\=R7>JO[.ROSN2[U1_9V5_=R3?J?[.RO[N2+Y3_9V5_=V1?*?Z.RO[
+MNR/Y3O5W5O9W1_*=ZN^L[.].=)7J[ZSL[T[D.]7?6=G?G<AWJK^SLK\[D>]4
+M?V=E?W<BWZG^SLK^[D2^4_V=E?W=B7RG^CLK^[L3^4[U=U;V=R?RG>KOK.SO
+M3N0[U=]9V=^=R'>JO[.ROSN1[U1_9V5_=R+?J?[.RO[N1+Y3_9V5_=V)?*?Z
+M.RO[NQ/Y3O5W5O9W9[I*]7=6]G=G\IWJ[ZSL[\[D.]7?6=G?G<EWJK^SLK\[
+MD^]4?V=E?W<FWZG^SLK^[DR^4_V=E?W=F7RG^CLK^[LS^4[U=U;V=V?RG>KO
+MK.SOSN0[U=]9V=^=R7>JO[.ROSN3[U1_9V5_=R;?J?[.RO[N3+Y3_9V5_=V9
+M?*?Z.ZOZNUC#57[W`WCA`7=WG*SZ'/C.57_GJ;];M;W5>ID#W[GJ[SSU=ZO&
+MW>KK,@>^<]7?>>KO5HV[U9_+'/C.57_GJ;^#9P>^<]7?>>KO8`Y\YZJ_\]3?
+MP1SXSE5_YZF_@SGPG:O^SE-_]ZC-/>ISX#M7_9VG_NY1N[U'G3OPG:O^SE-_
+M]ZAQ]ZAS![YSU=]YZN\>->X>=>[`=Z[Z.T_]'3P[\)VK_LY3?P=SX#M7_9VG
+M_@[FP'>N^CM/_=WE')U_YZJ_\]3?/6YSC_L<^4[U=Y[ZN\>-N\<+=W3^G:O^
+MSE-_][AQ]WCACLZ_<]7?>>KO'C?N'B_<T?EWKOH[3_T=/#ORG>KO//5W,$>^
+M4_V=I_X.YLAWJK_SU-_!'/E.]7>>^KLG;>Y)GR/?J?[.4W_WI''WI'-'OE/]
+MG:?^[DGC[DGGCGRG^CM/_=V3QMV3SAWY3O5WGOH[>';D.]7?>>KO8(Y\I_H[
+M3_T=S)'O5'_GJ;^[G*/S[USU=Y[ZNZ=M[FF?(]^I_LY3?_>T<?=TX8[.OW/5
+MWWGJ[YXV[IXNW-'Y=Z[Z.T_]W=/&W=.%.SK_SE5_YZF_@V='OE/]G:?^#N;(
+M=ZJ_\]3?P1SY3O5WGOH[F"/?J?[.4W_WK,T]ZW/D.]7?>>KOGC7NGG7NR'>J
+MO_/4WSUKW#WKW)'O5'_GJ;][UKA[UKDCWZG^SE-_!\^.?*?Z.T_]'<R1[U1_
+MYZF_@SGRG>KO//5WEW-T_IVK_LY3?_>\S3WO<^0[U=]YZN^>-^Z>+]S1^7>N
+M^CM/_=WSQMWSA3LZ_\Y5?^>IOWO>N'N^<$?GW[GJ[SSU=_#LR'>JO_/4W\$<
+M^4[U=Y[Z.Y@CWZG^SE-_!W/D.]7?>>KO7K2Y%WV.?*?Z.T_]W8O&W8O.'?E.
+M]7>>^KL7C;L7G3ORG>KO//5W+QIW+SIWY#O5WWGJ[^#9D>]4?^>IOX,Y\IWJ
+M[SSU=S!'OE/]G:?^[G*.SK]SU=]YZN]>MKF7?8Y\I_H[3_W=R\;=RX4[.O_.
+M57_GJ;][V;A[N7!'Y]^YZN\\]7<O&W<O%^[H_#M7_9VG_@Z>'?E.]7>>^CN8
+M(]^I_LY3?P=SY#O5WWGJ[V".?*?Z.T_]W:LV]ZK/D>]4?^>IOWO5N'O5N2/?
+MJ?[.4W_WJG'WJG-'OE/]G:?^[E7C[E7GCGRG^CM/_1T\._*=ZN\\]7<P1[Y3
+M_9VG_@[FR'>JO_/4WUW.T?EWKOH[3_W=59N[ZG/D.]7?>>KOKAIW5PMW=/Z=
+MJ_[.4W]WU;B[6KBC\^]<]7>>^KNKQMW5PAV=?^>JO_/4W\&S(]^I_LY3?P=S
+MY#O5WWGJ[V".?*?Z.T_]'<R1[U1_YZF_>]WF7O<Y\IWJ[SSU=Z\;=Z\[=^0[
+MU=]YZN]>-^Y>=^[(=ZJ_\]3?O6[<O>[<D>]4?^>IOX-G1[Y3_9VG_@[FR'>J
+MO_/4W\$<^4[U=Y[ZN\LY.O_.57_GJ;][T^;>]#GRG>KO//5W;QIW;Q;NZ/P[
+M5_V=I_[N3>/NS<(=G7_GJK_SU-^]:=R]6;BC\^]<]7>>^CMX=N0[U=]YZN]@
+MCGRG^CM/_1W,D>]4?^>IOX,Y\IWJ[SSU=V_;W-L^1[Y3_9VG_NYMX^YMYXY\
+MI_H[3_W=V\;=V\X=^4[U=Y[ZN[>-N[>=._*=ZN\\]7?P[,AWJK_SU-_!'/E.
+M]7>>^CN8(]^I_LY3?W<Y1^??N>KOO.KO@LZ_<]7?>=7?!9U_YZJ_\ZJ_"SK_
+MSE5_YU5_%W3^G:O^SJO^+NC\.U?]G5?]7=#Y=Z[Z.Z_ZNZ#S[USU=U[U=T'G
+MW[GJ[SSU=^_;UOL^1[Y3_9VG_NY]X^Y]YXY\I_H[3_W=^\;=^\X=^4[U=Y[Z
+MN_>-N_>=._*=ZN\\]7?P[,AWJK_SU-_!'/E.]7>>^CN8(]^I_LY3?W<Y1^??
+MQ=T/X(4'W*W;W+K/@>^^7\7<1>KOUHV[]<(=G7\7JK^+U-^M&W?KA3LZ_RY4
+M?Q>IOULW[M8+=W3^7:C^+E)_!\\.?!>JOXO4W\$<^"Y4?Q>IOX,Y\%VH_BY2
+M?P=SX+M0_5VD_L[:G/4Y\%VH_BY2?V>-.^O<@>]"]7>1^CMKW%GG#GP7JK^+
+MU-]9X\XZ=^"[4/U=I/X.GAWX+E1_%ZF_@SGP7:C^+E)_!W/@NU#]7:3^[G*.
+MSK\+U=]%ZN^\S7F?(]^I_BY2?^>-.U^XH_/O0O5WD?H[;]SYPAV=?Q>JOXO4
+MWWGCSA?NZ/R[4/U=I/X.GAWY3O5WD?H[F"/?J?XN4G\'<^0[U=]%ZN]@CGRG
+M^KM(_5VTN>ASY#O5WT7J[Z)Q%YT[\IWJ[R+U=]&XB\X=^4[U=Y'ZNVC<1>>.
+M?*?ZNTC]'3P[\IWJ[R+U=S!'OE/]7:3^#N;(=ZJ_B]3?7<[1^7>A^KM(_=W0
+MYH8^1[Y3_5VD_FYHW`T+=W3^7:C^+E)_-S3NAH4[.O\N5'\7J;\;&G?#PAV=
+M?Q>JOXO4W\&S(]^I_BY2?P=SY#O5WT7J[V".?*?ZNTC]'<R1[U1_%ZF_&]O<
+MV.?(=ZJ_B]3?C8V[L7-'OE/]7:3^;FS<C9T[\IWJ[R+U=V/C;NS<D>]4?Q>I
+MOX-G1[Y3_5VD_@[FR'>JOXO4W\$<^4[U=Y'ZN\LY.O\N5'\7J;_;M+E-GR/?
+MJ?XN4G^W:=QM%N[H_+M0_5VD_F[3N-LLW-'Y=Z'ZNTC]W:9QMUFXH_/O0O5W
+MD?H[>';D.]7?1>KO8(Y\I_J[2/T=S)'O5'\7J;^#.?*=ZN\B]7?;-K?M<^0[
+MU=]%ZN^VC;MMYXY\I_J[2/W=MG&W[=R1[U1_%ZF_VS;NMIT[\IWJ[R+U=_#L
+MR'>JOXO4W\$<^4[U=Y'Z.Y@CWZG^+E)_=SE'Y]^%ZN\B]7=3FYOZ'/E.]7>1
+M^KNI<3<MW-'Y=Z'ZNTC]W=2XFQ;NZ/R[4/U=I/YN:MQ-"W=T_EVH_BY2?P?/
+MCGRG^KM(_1W,D>]4?Q>IOX,Y\IWJ[R+U=S!'OE/]7:3^;FYS<Y\CWZG^+E)_
+M-S?NYLX=^4[U=Y'ZN[EQ-W?NR'>JOXO4W\V-N[ES1[Y3_5VD_@Z>'?E.]7>1
+M^CN8(]^I_BY2?P=SY#O5WT7J[R[GZ/R[4/U=I/[N0YO[T.?(=ZJ_B]3??6C<
+M?5BXH_/O0O5WD?J[#XV[#PMW=/Y=J/XN4G_WH7'W8>&.SK\+U=]%ZN_@V9'O
+M5'\7J;^#.?*=ZN\B]7<P1[Y3_5VD_@[FR'>JOXO4WWUL<Q_['/E.]7>1^KN/
+MC;N/G3ORG>KO(O5W'QMW'SMWY#O5WT7J[SXV[CYV[LAWJK^+U-_!LR/?J?XN
+M4G\'<^0[U=]%ZN]@CGRG^KM(_=WE')U_%ZJ_B]3??6ISG_H<^4[U=Y'ZNT^-
+MNT\+=W3^7:C^+E)_]ZEQ]VGACLZ_"]7?1>KO/C7N/BW<T?EWH?J[2/T=/#OR
+MG>KO(O5W,$>^4_U=I/X.YLAWJK^+U-_!'/E.]7>1^KO/;>YSGR/?J?XN4G_W
+MN7'WN7-'OE/]7:3^[G/C[G/GCGRG^KM(_=WGQMWGSAWY3O5WD?H[>';D.]7?
+M1>KO8(Y\I_J[2/T=S)'O5'\7J;^[G*/S[T+U=Y'ZN^LV=]WGR'>JOXO4WUTW
+M[JX7[NC\NU#]7:3^[KIQ=[UP1^??A>KO(O5WUXV[ZX4[.O\N5'\7J;^#9T>^
+M4_U=I/X.YLAWJK^+U-_!'/E.]7>1^CN8(]^I_BY2?W?3YF[Z'/E.]7>1^KN;
+MQMU-YXY\I_J[2/W=3>/NIG-'OE/]7:3^[J9Q=].Y(]^I_BY2?P?/CGRG^KM(
+M_1W,D>]4?Q>IOX,Y\IWJ[R+U=Q=SPQJN&NY^`"\\X.XNZ/W2Y\!W@^KOOK_P
+M@+LOC;LOZV4.?#>H_FY(_=V7=GM?OBYSX+M!]7=#ZN^^-.Z^_+G,@>\&U=\-
+MJ;^#9T=_W[;Z*/H+W]ZE;]_^N+H='&\_V\%7ZQW\6[_P[=_>/?QG&;P]F^=O
+M#([C:G<Y^-_M#8^W9_/,P^HPT/MJ]C/]AF^6-_QSCOZN]W_R_(;?_/RV],7V
+M3^YP>_K-=SC=WN&X70WC:MRL)O_5._S??_^?=(<_YW[;1_)S#G3P<.[NAI??
+M.B_F;N[-_=#!^=ZOO`_;ZF#]#W[W?WQO[OK=O=_")])!G_LASA.](-_L;];!
+M=''DY/W/^?8LYUBM[_[7C3\<7#[?5;\_2OP?O-V_N+_5Y=N]_2/&]N&OMWMS
+M7KS=U<.YVS]BW/L\'WR$Q=.[OKP[^BON_\F'<7%PXB]^Y?X8>?B5^W/.?Z\(
+IYENS_/CM=`?_UB]\^_KNX3\_!X<V^-N>X/`=E_7ZC_\'#.+&':.H````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu
index 85e22d7..2d392cd 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu
@@ -1,22 +1,22 @@
# $FreeBSD$
begin 644 img-63x255-512-pc98.qcow2.gz
-M'XL("+0[(U0``VEM9RTV,W@R-34M-3$R+7!C.3@N<6-O=S(N;W5T`*V8VY+3
-M,`Q`W_L5Y@X+E%BR<^'271:6&=[@`7ANN\U7=/AVZMJ-$D6*NR5M)M..1V=D
-M^UBQ4Q3Q8XRWQI7&-:;=F,/_=('I_1E>9O_SV_=E_[-?1)@ME"BAH=IUN`'K
-M+^%`PQ5VW&!E7"\[%'!PBAJ#<CBG9C?5(."N%L>A.TY&S2+P$F#$J9-Q47X0
-M\^,1[L+\8.[\4!X_?XKC#>5T?ACSXU&5AJNS.!"B&@VWSN)0B-IHN&T6YX2H
-M>PVGK-P>S@M1K8*S&54.N%*(LAH.LKA*B$(-Y[*X6HC2O+-Y[QHA2O/.YKU;
-M"U&:=S;OW4:(TKRS>>^V0I3FG<U[=R]$:=Z!XITAW$Z(TKP#YMVCA'M,N%:(
-MTKP#YMV3A'O:X:P4I7D'S+MG"?><<$*]`\T[8-Z]2+B7A!/J'6C>`?/N5<)=
-M$4ZH=Z!Y!\R[UPGWAG!"O0/-.V#>O1UY9X5Z!YIWR+Q[EU@%X81ZAYIWR+RS
-M"0>$$^H=:MXA\PX3SA%.J'>H>8?,.Y]P)>&$>H>:=\B\JQ*N)IQ0[U#S#IEW
-M3<*])YQ0[U#S#IEW'Q+N(^&$>H>:=\B\^Y1P*\()]0XU[QSS[CKA;@@GU#NG
-M>>>8=Y\3[I9P0KUSFG>.>?<EX;YV.)"B.N^*0KX2[FZT9F'>_:>C_;$5[GK#
-M!+!^"'`JPXAK9NVPCQT.&JR%N]ZPOUT.OQWP*,P#@-Z;]1CX*W;81V$:9[9.
-MZE?;TG7&^/FYA?%A2F8=/Q!/:/^18;6;.<,ZOG"HPKKUI:GAW`S_W/T6IJ2>
-M[PP9<?H+A]1P2AA;#7?=PV'4C"B]E6JVE@I\_W</MUI2L3_@)E\XA%/43FI0
-M.^OGE:7NRM7IZL]SV+R',];I^<TVW]W\&LI/*%<PZ.Y$?F;<W;`OZ,[O;#X"
-M#C+=-4-<V!?TYW,PA9G16XVSV\X\&9:OC#-7;H`,5V[$P;R%H#E6EH.!H8J/
-<[GK#_L=R^(U`EX"SC:`KP]-M\0^92;H")14`````
+M'XL("%?N+50``VEM9RTV,W@R-34M-3$R+7!C.3@N<6-O=S(N;W5T`*V8VW+3
+M,!!`W_,5X@X%@K4K^<(E*84RPQL\`,^)FWQ%AF\GBA1+7N]:;5#B\32C[IF5
+M]F@CIZK\2RFKE:F5Z=1^JXZ?PP4J^3"^U.'GM^_+]'58>)BNA"AFH-D-N!'K
+M;\2!A*OT=$#SN"0[9'!PCIJ"<C@C9C<WP."N%J>E.Q6C)1%X"=#CQ&)<E!_X
+M_&B$N3`_*)T?\NMGSW%TH)[/#WU^-*J1<&T6!TQ4)^$V61PR45L)UV=QAHFZ
+MDW#"SDUPEHG:"SB=4>6(JYDH+>$@BVN8*)1P)HMKF2C).YWWKF.B).]TWKL-
+M$R5YI_/>;9DHR3N=]ZYGHB3O=-Z[.R9*\@X$[U3$[9@HR3L@WCT*N,<1MV>B
+M).^`>/<DX)X..,U%2=X!\>Y9P#V/.*;?@>0=$.]>!-S+B&/Z'4C>`?'N5<!=
+M11S3[T#R#HAWKP/N3<0Q_0XD[X!X]W;BG6;Z'4C>(?'N76!5$<?T.Y2\0^*=
+M#CB(.*;?H>0=$N\PX$S$,?T.)>^0>&<#KHXXIM^AY!T2[YJ`:R..Z7<H>8?$
+MNR[@WD<<T^]0\@Z)=Q\"[F/$,?T.)>^0>/<IX%81Q_0[E+PSQ+MUP%U''-/O
+MC.2=(=Y]#KB;B&/ZG9&\,\2[+P'W=<`!%S5X5U7\%7"WDST+9<^?)IZ/-7.7
+M!V:`[4.`<QEZ7%=TPM9/V&FP8>[RP.%F.7X/P),P#P!:JS93X"\_8>N%Z8SJ
+M#3>OL$^T/.%UNGZVM##6E:3H^@'[A/8?&3:[PAFV_@>'QNU;6ZL6[IOAG]O?
+M4Z6/N&(E\3CY!X<P<$YX:+(3W#K!N3/+/OG/5#;5Z]C@T[\3W&H9F_T1-_N#
+M@WN*VG$#XF1M65G:H5V=K[3.[O#NGK'.W]_D\#W45\7\F'8%H^G.Y*>FTW7G
+M@N'YG=3#X2`S737&N7-!6L]1"3.KMYIFUQ<NAJ8[XYX[UT'&.]?CH&PCZ$Z=
+BY6B@Z^*3NSQP^+$<OSW0!&"Q%32U^W9;_`,76K<))14`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu
index 1a19b11..029e51d 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu
@@ -1,12 +1,12 @@
# $FreeBSD$
begin 644 img-63x255-512-pc98.raw.gz
-M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N<F%W+F]U=`"ME,V.A"`,
-MQ^\^1<][,*7"BA<GF63O<YG=LVOT*7SX!<&5BOB1`$@PA5_^;:&(K@%(`NQV
-MYK1A>I:\3\5',=/$>`^H%'0Q\&V`,XZLOD9"+\&L-@/&<1W,,)6;MN"$,<8@
-M?RIIV,%Y=V7F^!$>"KFOL!XR*]2S0E6#5*`^0=-5A3]?WSLIT9@M)0Y'9[A%
-M<#6F<(\`5[EKME)$<*H74`W^)UP'N-9]"TX>J3.1P&'/D'16Y;TLVG1^+LPS
-MB`%$!:B]C3CP/[^PZFMB&<3</=`'L;N=Q=5\OPAP=.(N<-ROQ07Y9"D\B5X;
-MJ^LS)T-L7\;%EVLA_.4Z'.4M!,U<6<P-M%4\FM.&Z57R[H#2`[-%T%8^Q.(/
-(W!$BDN<&````
+M'XL("%?N+50``VEM9RTV,W@R-34M-3$R+7!C.3@N<F%W+F]U=`"ME$V/@R`0
+MAN_^BO>\!P,C5+VT29/>][*[9VOT5_CCER\M(WZT":"(&7CR#C.,$+X!BB"Z
+MC7'?,-U+WJ?BJW`T.7X&U!I="OPQ0(<CJZ]5Z!7,;/6@&MU,)H:I#.T6OC-.
+M&F,*"KMV#0NN7'#!797Y_$@<"OE<83UD5M@XA;J&TM`7-/2NPK_'[TJAQV4+
+MB<?1&6X6'))G`W>+<)4QCM'*.-G02U1#^(GG$>[JWQFGCM29DQ##EF'769TW
+M61K3^;XXSI`#9`71!!MQX!)?O/2UJ0QB[A[H0^IN9W$U7R\C')VX"XY[6EP4
+M3Q;"D].[INKZS,&0ZYOQYLVU$'YS/8[R%H+651:3@;:*)^.^8?HN>?=`%8#9
+/3M!6/B&*?U("+YGG!@``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
index f474436..dd48100 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-512-pc98.vhd.gz
-M'XL("/S%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD+F]U=`"METUOXR`0
-MAN_Y%2/MK0<+CP&32RM5VYXK5>V>B=>N>NANU>RA!__X,@:2P5])ML0.P@(>
-MWOD`A!#^!Z`KT!WH%K2B>BU!;Z$V`*XQO#B49?B$OOG[IVW^O7X6X==O/*P4
-M?%0ZG,9C!=)-4@-:FD3_ICKT$5/\N'NY>GU[B3@,N#BQU"`1E(/(R3Q&'-01
-MZ?[V\>=87355=QSEY^DZJ#K6H^+JBN*&XZ0;Y?K3JZ&3@\SX)A])`\<EZI08
-MC6(RYYS*C)W#Z;51E^"N-B$6/E5<8M2N%*!+J)'J+FVB'R:O2Y7/_;O]V+<C
-M?;B0*IH%8]PFE\W%D"H8.P<%D@2NF0L#93_&S:3*M[RGTW$R5)P3A(H-.)B?
-M>N^(`JY/EV+%Y\O!6-1G29];6\+.E,L-_6V1/@?@KKL,J!38*?`I&MR0OJV$
-M1L[YG1MYUNIH%K+OO^/;9O8?VE4AERLT)K-",RA4-6WH2H/!<Q7^NGN>"8FQ
-MV4+B<7@*%P7S_3[%W3!<Y=/L2&';$S0E5&WXX'6&N_;_B)-KZFA7:.<:%HU5
-MF9/%FM$X'F<H6R@K$":T80H\Q!>.^K93&9B8NZ(/IN9:PM5I_Y+A\(2YD.)V
-MX>2-/9,0GO#>]51=DSD8N_'*.'/E$B1=N1Z'>3<".^PL+@-I%Y^4RPW]0Y$^
-M'HCA,,IVNF$X/;(IE`&83:$,YT=&A;993;9+LU`'A9FN"H3+>%4@7,:K`N$R
->7A4(E_&J0+B,5P7"9;TJ:'<)%&+S!5&O-H=?#@``
+M'XL("%CN+50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD+F]U=`"METU/["`4
+MAO?S*T[BSD5#3X$R&R<QZMK$Z%TSO:UQ<=4X+ESTQ\LI,(72=APOTPZA`1[>
+M\P$$QNP/0%8@.Y`M2$'UFH/<0JT`3*-[<2A+]PE]\_;:-I\O7X7[]1L+*UDX
+M*AY.X[$";B:I`35-(O]2'7J/*2YNGR]?_CU['#J<GYA+X`C"0'@RCV)'=42Z
+MNWZXF:JK4G7C*#M/UT'5!3VJ4%U1[$(<-Z-,?WHE='R0Z=_H(VH(<9$ZP2:C
+M`IES3@V,G</)M5'GX"XW+A8V54QBU*9D($NHD>HF;;P?DM>DRM?A77\<VHD^
+M7$@5&01CVL:7S467*N@[.P6<!*Z9"P/E,,7-I,I_>4_&X[BK&"<PX1MP,#_V
+MWHB"4)\LV8K/EX.QJ$^3/K.VF)XIEQOZZR)^CL!]=QY0"-`I\-$;W)"^+8>&
+MS_G=+=DD8T:#=W%\FX7L^W5\V\S^0[TJY'R%2F56J`:%HJ8-74A0^%.%?VZ?
+M9E:PTME"8G%X"N<%A_M]C-L%N,HNN)$2)!LT)52M^PCK`>[*_CV.KZFC7:&=
+M:U@T5F1.%JTFX\(X0]E"60%3K@UCX#&^,.K;IC(P,G=%'Z3F:L+5<?\RP.$)
+M<R'&[=W)ZWM&(3SAO:M479,Y&/OIROCARB5(O'(M#O-N!'K864P&TBZ>E,L-
+M_7T1/Q:([C#*=KJA.SVR*>0.F$TA=^='1H6Z64VV<[-0.H69K@J$RWA5(%S&
+BJP+A,EX5")?QJD"XC%<%PF6]*DAS"61L\PVA;@PG7PX`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu
index dce8fa3..5600c7a 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu
@@ -1,15 +1,15 @@
# $FreeBSD$
begin 644 img-63x255-512-pc98.vhdf.gz
-M'XL("/S%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD9BYO=70`K94];X,P
-M$(;W_(J3NF6(_(U9$BEJ.E>JVLZ4FBA#VZ5#!WY\?1B"#T.25L8&&1U^>._.
-M/C,6+@`E@%4SSV5#N]_0UJ[6JX[&F[\!M88J!3Y[8(<3J*]44"OPHTF'IAD[
-M,;2;R37@N#>FH'[6HF$&U[NK,L=/L(M"_JZP<)D5VDZA+D!IT`:LN%7AZ^%E
-M)B6694M)P(EKN$&P;)9PNP@GPS(;*3R:57.0KG^)QQ%N&^X!IRZI\Y%@;LZP
-MZ*S.NUBL;W1>G&?@#K@$9GN;H,!S?F'45Z8R!''W@CY(W:T05]#O>8035]P%
-MBGM#7)1/DL(KT=NFZNK,R>#3G7'CSD4(W;D!)_(6@K*K+'X%8A5/GLN&]G%#
-M6P"J'I@M@K8_W8P$TX!Q8#2."P6FA,+&0$%74EM_?;KZ^_039QAQ?'+FQ!WG
-M"XF[Q10@*OR)><=QI._N<%R?/HX#;BA5PX^5P:!K#U&)NY:Z^[!_NI^JDVF0
-M+(D>1YUQV?..D^CM8IPZ.^M<5P+YV,D+,<R6*L1I-IGUW]P&G,F\5/S!N_H%
-(/-'XFQ()````
+M'XL("%CN+50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD9BYO=70`K94[;X,P
+M$,?W?(J3NF5`?F.61(J:SI6JMC.E)LJ0=NG0@0]?&QOBPY!'94R(T>$?_WOX
+M(,0?`((!J6>NRX9N5^#1K=:KGD;;^X!20IT"7RVPQS&GKQ+0"+"SR0F\[6<T
+M,71%.+;A?\!1:TQ!8=6B8<05(RZX*S+'CY&+0NY76)K,"G6O4)8@)$@%FMVJ
+M\'W_-E'H<=E2XG'L&FX0'(IG!K>-<-P:V^C)N-B@H<!-N(GG$6[C?P-.7%)G
+M(T',G&'169FW6+0=>%V<9Z`&*`>B@XUAX)A?..NK4AD,N7M!'Z3NU@Y7XN=I
+MA&-7W`6,^W"X*)\HA5>BMTG5-9F30:<[X\:=ZR!XYWH<R]L(JKZSV`IT73RY
+M+ANZYP(/#Q0!F"V".GS=%`?5@C*@I)N7`E0%I8Z!#%=2UWQ_F>;G^!MGV.&H
+M;P:SIUO/N-LMJ@16NY>H3S>/]#WL#^OCZ3#@AE8UO%@H%W1I(2)Q5V-WGW8O
+MCU-U/`V21M&C3F?<]JSC*'K;&"=&9XWI6R`]G^@&&69;E<-),EGUW]QZG,I<
+.*O;#N_H#>\I9F1()````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu
index 7279c4b..b2d29cc 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu
@@ -1,84 +1,84 @@
# $FreeBSD$
begin 644 img-63x255-512-pc98.vmdk.gz
-M'XL("/W%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FUD:RYO=70`K5Q=C]S&
-M$7SWKQB<W_*P8"V_E@]R$D<.$`0!#-NQ7T,NR?@06Q).AR`"]L>'0T[-%;FD
-M2/OZM">PQ>[:[I[=OE-U89-D^G(N:UR6N:QU>>$2N.&?IH=+TA=C>&3QQNWO
-M;__QXXE??SJ=;E],8/!1$H)$X<28/<_MM/@BW/ES4;,;P^.\"Y?ZJ.8N,,"=
+M'XL("%CN+50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FUD:RYO=70`K5Q=C]S&
+M$7SWKQB<W_*P8"V_E@^R$T<.$`0!C-BQ7T,NR?@06Q).AR`"]L>'0T[-%;FD
+M2/OZM">PQ>[:[I[=OE-U89-D^G(N:UR6N:QU>>$2N.&?IH=+TA=C>&3QQNUO
+M;__^XXE??SR=;E],8/!1$H)$X<28/<_MM/@BW/ES4;,;P^.\"Y?ZJ.8N,,"=
M-VYLP@W]<.>U$&97C[=;?R%P+@*Y&5R^4M-FL9_+[@]?A.;Y_%*?PW"\1>7*
MU!5-,%V1CW;JRO-X+W'EX-0/@%^ZMX\?_^/>=A^O3X\?GM^'_,[^;`?GK/#^
-MQ=4C#(65A;_P-SQ<Y2&*SJ6M2^%ON]O37Q]_Z4[_[9X^/KY_]P8L]^S/-DM=
-M5OETO'_R\I@9_DD25\`_A[O]Y6]OWX17;G+Z4#\1SD<-B0S//=2AN$7A_/?]
+MQ=4C#(65A;_P-SQ<Y2&*SJ6M2^%ON]O37QY_Z4[_[9X^/KY_]P8L]^S/-DM=
+M5OETO'_R\I@9_DD25\`_A[O]^:]OWX17;G+Z4#\1SD<-B0S//=2AN$7A_/?]
M8\RN>_?L$?OP%;/S9QN:DX_/G?F+/'-EY<9T<H]]'FZWH>2Q=]>GKG[N?OCT
MH7OS\.O[=[%W_FQ]RZH1Z#(V*G5YZJ%":;Y]N4?T+YOQU-SME\?GGQ^OWP]E
-M?NP>3E\ZPA6^=\,!7D)>4]5#2+%YLD/:MV_^]SS4Z]IPLH^$&Y,8BQB>.S^[
-MO/18PP&F0^_2U*47EX[P0\)#)1F\D[N]?W?Z[B>'(KUD[OMO__P=X2X#W.`Y
-M)#B$#`7-:LJG^O/ER]+=OO_&/?@B?_BY&U^!A*NFMYEWGLX!HWGV%Z%K$[P?
-M8IF_,9ZL>UL_U^[K^F-W^O+MVZ_CR=:^V&Q\#*EU'J68H/WK>VSGT+CII*>#
-M'H^B;9M3W=8?GKLG?[SQ*!K_:FU#I?Y8LY=CG#]/.9Y4[U\Q[O;&/3RVPYEZ
-MV']W[W\EW'5Z&0]Y^)=$-0:F_F)X]8SP77B&Z17CC\G#=<]/GT[73[\\OFN'
-M-YI[0[AVZMV0SG":4U(QIV52\6F'WCW@);4!FW"=;]&4U"6\,0:L*8^7+J3#
-M(_>/T(7;I]//7=T.:;F'<YX_Q*/HET>A+5IT83KHH1?3483$/IT^=M<`ER;A
-M`/M9<Z:<_$MY>"5/&<T'Z//[IS&U(GW0>9PN?Y:]=AYG=S]2R]\).,%9YU<D
-M>S_/^$AG@$[`DI?\"I]?)IZY1A5BE#.XX;>)T[?#][^&[P\"YU]B%_&L-*H6
-MHSG2O<+_O+B*9ZM1G1C](;@LM(B_H$"NQZ;22/5&A'.+WN6A=_3,-:H0HYS!
-M;?6N"+VC9Z51M1C-:G;+8LO0.WJV&M6)T1^"NX3>\1<PR/78.QIILO9;WK)W
-M5>@=/7.-*L0H9W!;O:M#[^A9:50M1K.:W;+8)O2.GJU&=6+TA^"NH7<<*Y#K
-ML7<T4KVQV;LV](Z>N4858I0SN*W>=:%W]*PTJA:C6<UN66P?>D?/5J,Z,?HC
-M<&42>I=)[W@]]HY&JC>V>E=RWM$SUZA"C'(&M]&[DO..GI5&U6(TJ]DMB^6\
-MHV>K49T8_2$XSKM<>L?KL7<T4KVQV3O..WKF&E6(4<[@MGK'>4?/2J-J,9K5
-M[);%<M[1L]6H3HS^$!SG72&]X_78.QJIWMCL'><=/7.-*L0H9W!;O>.\HV>E
-M4;48S6IVRV(Y[^C9:E0G1G\(CO..OSI!KL?>T4CUQF;O.._HF6M4(48Y@]OJ
-M'><=/2N-JL5H5K-;%LMY1\]6HSHQ^B-PER3T[B*]X_78.QJIWMCJW87SCIZY
-M1A5BE#.XC=Y=.._H66E4+4:SFMVR6,X[>K8:U8G1'X+CO*ND=[P>>T<CU1N;
-MO>.\HV>N4848Y0QNJW><=_2L-*H6HUG-;EDLYQT]6XWJQ.@/P7'>\3]>D.NQ
-M=S12O;'9.\X[>N8:58A1SN"V>L=Y1\]*HVHQFM7LEL5RWM&SU:A.C/X0'.<=
-M64O(]=@[&JG>V.P=YQT]<XTJQ"AG<%N]X[RC9Z51M1C-:G;+8CGOZ-EJ5"=&
-M?P2N2D+OKM([7H^]HY'JC:W>59QW],PUJA"CG,%M]*[BO*-GI5&U&,UJ=LMB
-M.>_HV6I4)T9_"([SKI7>\9JL=NQ=>P>W[!WG'3USC2K$*&=P6[WCO*-GI5&U
-M&,UJ=LMB.>_HV6I4)T9_"([SKI/>\7KL'8U4;VSVCO..GKE&%6*4,[BMWG'>
-MT;/2J%J,9C6[9;&<=_1L-:H3HS\$QWG72^]X/?:.1JHW-GO'>4?/7*,*,<H9
-MW%;O.._H66E4+4:SFMVR6,X[>K8:U8G1'X&KDZEW<><&N?:]BT:J-[9Z5X=Y
-M%SUSC2K$*&=P&[VKP[R+GI5&U6(TJ]DMBPWS+GJV&M6)T1^""_,.PM]!^3L(
-M?X==_JX.\P["WT'Y.PA_AUW^K@[S#L+?0?D["'^WDMVRV##O(/P=E+^#\'<'
-MX,*\@_!W4/X.PM]AE[^KP[R#\'=0_@["WV&7OZO#O(/P=U#^#L+?K62W+#;,
-M.PA_!^7O(/S=`;@P[R#\'92_@_!WV.7OZC#O(/P=E+^#\'?8Y>_J,.\@_!V4
-MOX/P=RO9+8L-\P["WT'Y.PA_MP_7)*%WPM]!^3L(?X==_J[AO!/^#LK?0?@[
-M[/)W#>>=\'=0_@["WZUDMRR6\T[X.RA_!^'O#L!QW@E_!^7O(/P==OF[AO-.
-M^#LH?P?A[[#+WS6<=\+?0?D["'^WDMVR6,X[X>^@_!V$OSL`QWDG_!V4OX/P
-M=]CE[QK..^'OH/P=A+_#+G_7<-X)?P?E[R#\W4IVRV(Y[X2_@_)W$/[N`!SG
-MG?!W4/X.PM]AE[]K..^$OX/R=Q#^#KO\7<-Y)_P=E+^#\'<KV2V+Y;P3_@[*
-MWT'XNWVX:Q)Z)_P=E+^#\'?8Y>^NG'?"WT'Y.PA_AUW^[LIY)_P=E+^#\'<K
-MV2V+Y;P3_@[*WT'XNP-PG'?"WT'Y.PA_AUW^[LIY)_P=E+^#\'?8Y>^NG'?"
-MWT'Y.PA_MY+=LEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>^NG'?"WT'Y.PA_
-MAUW^[LIY)_P=E+^#\'<KV2V+Y;P3_@[*WT'XNP-PG'?"WT'Y.PA_AUW^[LIY
-M)_P=E+^#\'?8Y>^NG'?"WT'Y.PA_MY+=LEC..^'OH/P=A+_;AVN3T#OA[Z#\
-M'82_PRY_UW+>"7\'Y>\@_!UV^;N6\T[X.RA_!^'O5K);%LMY)_P=E+^#\'<'
-MX#COA+^#\G<0_@Z[_%W+>2?\'92_@_!WV.7O6LX[X>^@_!V$OUO);EDLYYWP
-M=U#^#L+?'8#CO!/^#LK?0?@[[/)W+>>=\'=0_@["WV&7OVLY[X2_@_)W$/YN
-M);MEL9QWPM]!^3L(?W<`CO-.^#LH?P?A[[#+W[6<=\+?0?D["'^'7?ZNY;P3
-M_@[*WT'XNY7LEL5RW@E_!^7O(/S=/ER73+V+$CS(]2ACI)'JC=O8M.';#=^)
-M>X$+\VY5T;?R3[%W;CV[.RW^,;C[8B>Y(4:Y8=Q$3.7^/L`)SE@.B4OH^C[@
-M$3DDXKJ<CU?)(1'7Y7R\2@Z)N"[GXU5R2,1UN8D<$G%=;B*'1%R7F\@A$=?E
-M)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7
-MY29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1
-MU^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A
-M$=?E)G)(<%UN(X<$U^4V<DAP76XCAP37Y39R2'!=;B.'!-?E-G)(<%UN(X<$
-MU^4V<DAP76XCAP37Y39R2'!=;B.'!-?E-G)(<%UN(X<$U^4V<DAP76XCAP37
-MY39R2'!=;B.'!-?E-G)(<%UN(X<$U^4V<DAP76XCAP37Y39R2'!=;B.'!-?E
-M-G)(<%UN(X<$U^4V<DAP76XCAP37Y39R2'!=;B.'!-?E-G)(<%UN(X<$U^4V
-M<DC$=7GRTKO?+X=$7)?3\U5R2,1U.3U?)8=$7)?3\U5R2,1UN8D<$G%=;B*'
-M1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XB
-MAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN
-M(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=
-M;B*'1%R7F\@A$=?E)G)(<%UN(X<$U^4V<DATIG)(=*9R2'2F<DATIG)(=*9R
-M2'2F<DATIG)(=*9R2'2F<DATIG)(=*9R2'2F<DATIG)(=*9R2/1)8BB'1&\J
-MAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'
-M1&\JAT1O*H=$;RJ'/"=)8BB'/">F<LCS_4<3'X.[+W:2&V9CN=-GE][_O7WC
-M]O5I_B<"HO]M@'GNZGO`?X:"L_'3A*O,7;.UNOK^Y;%7\`1G+-?,,N/^%<EG
-M$_GM&9:=<8:7,<.\]!^TFQ?N<CZ:X4_?_+C(<((S.Y();O<=$GG0?@ONCP*7
-M3B^S%Q3]+/`K7,IIK-<"]]7T3;CL<]GIBNI8L<8?WGU)+HLX/6?_D\<3@OQ_
-MWGD.&,_7O>17W:=QGI7[F?S<?;G^IZY^?*V>QVQ0;Y3KYG#^IZZ>Y^P(=[KW
-MU7UV5^/#P/*=<?"=ZT'F[]P)[FP["*IQLDRZC_N_MV_<OCW-_TR`60`TZV#F
-./YHD^>+_!_V[IW%@````
+M?NP>3E\ZPA6^=\,!7D)>4]5#2+%YLD/:MV__]SS4Z]IPLH^$&Y,8BQB>.S^[
+MO/18PP&F0^_2U*47EX[P0\)#)1F\D[N]?W?ZQT\.17K)W/??_>D?A+L,<(/G
+MD.`0,A0TJRF?ZL^7+TMW^_Y;]^"+_.'G;GP%$JZ:WF;>>3H'C.;97X2N3?!^
+MB&7^QGBR[FW]7+MOZH_=Z<NW;[^))UO[8K/Q,:36>91B@O:O[[&=0^.FDYX.
+M>CR*MFU.=5M_>.Z>_/'&HVC\J[4-E?ICS5Z.<?X\Y7A2O7_%N-L;]_#8#F?J
+M8?_=O?^5<-?I93SDX5\2U1B8^HOAU3/"=^$9IE>,/R8/UST_?3I=/_WR^*X=
+MWFCN#>':J7=#.L-I3DG%G)9)Q:<=>O>`E]0&;,)UOD534I?PQABPICQ>NI`.
+MC]P_0A=NGTX_=W4[I.4>SGG^$(^B7QZ%MFC1A>F@AUY,1Q$2^W3ZV%T#7)J$
+M`^QGS9ER\B_EX94\930?H,_OG\;4BO1!YW&Z_%GVVGF<W?U(+7\GX`1GG5^1
+M[/T\XR.=`3H!2U[R*WQ^F7CF&E6(4<[@AM\F3M\-W_\:OC\(G'^)7<2STJA:
+MC.9(]PK_\^(JGJU&=6+TA^"RT"+^@@*Y'IM*(]4;$<XM>I>'WM$SUZA"C'(&
+MM]6[(O2.GI5&U6(TJ]DMBRU#[^C9:E0G1G\([A)ZQU_`(-=C[VBDR=IO><O>
+M5:%W],PUJA"CG,%M]:X.O:-GI5&U&,UJ=LMBF]`[>K8:U8G1'X*[AMYQK$"N
+MQ][12/7&9N_:T#MZYAI5B%'.X+9ZUX7>T;/2J%J,9C6[9;%]Z!T]6XWJQ.B/
+MP)5)Z%TFO>/UV#L:J=[8ZEW)>4?/7*,*,<H9W$;O2LX[>E8:58O1K&:W+);S
+MCIZM1G5B](?@..]RZ1VOQ][12/7&9N\X[^B9:U0A1CF#V^H=YQT]*XVJQ6A6
+MLUL6RWE'SU:C.C'Z0W"<=X7TCM=C[VBD>F.S=YQW],PUJA"CG,%M]8[SCIZ5
+M1M5B-*O9+8OEO*-GJU&=&/TA.,X[_NH$N1Y[1R/5&YN]X[RC9ZY1A1CE#&ZK
+M=YQW]*PTJA:C6<UN62SG'3U;C>K$Z(_`79+0NXOTCM=C[VBD>F.K=Q?..WKF
+M&E6(4<[@-GIWX;RC9Z51M1C-:G;+8CGOZ-EJ5"=&?PB.\ZZ2WO%Z[!V-5&]L
+M]H[SCIZY1A5BE#.XK=YQWM&STJA:C&8UNV6QG'?T;#6J$Z,_!,=YQ_]X0:['
+MWM%(]<9F[SCOZ)EK5"%&.8/;ZAWG'3TKC:K%:%:S6Q;+>4?/5J,Z,?I#<)QW
+M9"TAUV/O:*1Z8[-WG'?TS#6J$*.<P6WUCO..GI5&U6(TJ]DMB^6\HV>K49T8
+M_1&X*@F]NTKO>#WVCD:J-[9Z5W'>T3/7J$*,<@:WT;N*\XZ>E4;58C2KV2V+
+MY;RC9ZM1G1C](3C.NU9ZQVNRVK%W[1W<LG><=_3,-:H0HYS!;?6.\XZ>E4;5
+M8C2KV2V+Y;RC9ZM1G1C](3C.NTYZQ^NQ=S12O;'9.\X[>N8:58A1SN"V>L=Y
+M1\]*HVHQFM7LEL5RWM&SU:A.C/X0'.==+[WC]=@[&JG>V.P=YQT]<XTJQ"AG
+M<%N]X[RC9Z51M1C-:G;+8CGOZ-EJ5"=&?P2N3J;>Q9T;Y-KW+AJIWMCJ71WF
+M7?3,-:H0HYS!;?2N#O,N>E8:58O1K&:W+#;,N^C9:E0G1G\(+LP["'\'Y>\@
+M_!UV^;LZS#L(?P?E[R#\'7;YNSK,.PA_!^7O(/S=2G;+8L.\@_!W4/X.PM\=
+M@`OS#L+?0?D["'^'7?ZN#O,.PM]!^3L(?X==_JX.\P["WT'Y.PA_MY+=LM@P
+M[R#\'92_@_!W!^#"O(/P=U#^#L+?89>_J\.\@_!W4/X.PM]AE[^KP[R#\'=0
+M_@["WZUDMRPVS#L(?P?E[R#\W3Y<DX3>"7\'Y>\@_!UV^;N&\T[X.RA_!^'O
+ML,O?-9QWPM]!^3L(?[>2W;)8SCOA[Z#\'82_.P#'>2?\'92_@_!WV.7O&LX[
+MX>^@_!V$O\,N?]=PW@E_!^7O(/S=2G;+8CGOA+^#\G<0_NX`'.>=\'=0_@["
+MWV&7OVLX[X2_@_)W$/X.N_Q=PWDG_!V4OX/P=RO9+8OEO!/^#LK?0?B[`W"<
+M=\+?0?D["'^'7?ZNX;P3_@[*WT'X.^SR=PWGG?!W4/X.PM^M9+<LEO-.^#LH
+M?P?A[_;AKDGHG?!W4/X.PM]AE[^[<MX)?P?E[R#\'7;YNROGG?!W4/X.PM^M
+M9+<LEO-.^#LH?P?A[P[`<=X)?P?E[R#\'7;YNROGG?!W4/X.PM]AE[^[<MX)
+M?P?E[R#\W4IVRV(Y[X2_@_)W$/[N`!SGG?!W4/X.PM]AE[^[<MX)?P?E[R#\
+M'7;YNROGG?!W4/X.PM^M9+<LEO-.^#LH?P?A[P[`<=X)?P?E[R#\'7;YNROG
+MG?!W4/X.PM]AE[^[<MX)?P?E[R#\W4IVRV(Y[X2_@_)W$/YN'ZY-0N^$OX/R
+M=Q#^#KO\7<MY)_P=E+^#\'?8Y>]:SCOA[Z#\'82_6\EN62SGG?!W4/X.PM\=
+M@..\$_X.RM]!^#OL\G<MYYWP=U#^#L+?89>_:SGOA+^#\G<0_FXENV6QG'?"
+MWT'Y.PA_=P".\T[X.RA_!^'OL,O?M9QWPM]!^3L(?X==_J[EO!/^#LK?0?B[
+ME>R6Q7+>"7\'Y>\@_-T!.,X[X>^@_!V$O\,N?]=RW@E_!^7O(/P==OF[EO-.
+M^#LH?P?A[U:R6Q;+>2?\'92_@_!W^W!=,O4N2O`@UZ.,D4:J-VYCTX9O-WPG
+M[@4NS+M51=_*/\7>N?7L[K3XQ^#NBYWDAACEAG$3,97[^P`G.&,Y)"ZAZ_N`
+M1^20B.MR/EXEAT1<E_/Q*CDDXKJ<CU?)(1'7Y29R2,1UN8D<$G%=;B*'1%R7
+MF\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<
+MEYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$
+M7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'
+M1%R7F\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P2
+M7)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<
+ME]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7
+MV\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;
+MR"$1U^7)2^]^OQP2<5U.SU?)(1'7Y?1\E1P2<5U.SU?)(1'7Y29R2,1UN8D<
+M$G%=;B*'1%R7F\@A$=?E)G)(Q'6YB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)
+M'!)Q76XBAT1<EYO((1'7Y29R2,1UN8D<$G%=;B*'1%R7F\@A$=?E)G)(Q'6Y
+MB1P2<5UN(H=$7)>;R"$1U^4F<DC$=;F)'!)Q76XBAT1<EYO((1'7Y29R2,1U
+MN8D<$G%=;B*'1%R7F\@AP76YC1P27)?;R"'1F<HAT9G*(=&9RB'1F<HAT9G*
+M(=&9RB'1F<HAT9G*(=&9RB'1F<HAT9G*(=&9RB'1F<HAT9G*(=$GB:$<$KVI
+M'!*]J1P2O:D<$KVI'!*]J1P2O:D<$KVI'!*]J1P2O:D<$KVI'!*]J1P2O:D<
+M$KVI'!*]J1P2O:D<\IPDB:$<\IR8RB'/]Q]-?`SNOMA);IB-Y4Z?77K_]_:-
+MVS>G^9\(B/ZW`>:YJ^\!_QD*SL9/$ZXR=\W6ZDJGX\1VP5_/^I>=C>6:66;<
+MOR+Y;"*_/<.R,\[P,F:8E_Z#=O/"7<Y',_SIVQ\7&4YP9D<RP>V^0R(/VF_!
+M?2UP_C>"7CQGGP5^A4LYC?5:X+Z:O@F7?2X[75$=*];XP[LOR641I^?L?_)X
+M0I#_SSO/`>/YNI?\JOLTSK-R/Y.?NR_7_]35CZ_5\Y@-ZHURW1S._]35\YP=
+MX4[WOKK/[FI\&%B^,PZ^<SW(_)T[P9UM!T$U3I9)]W'_]_:-VW>G^9\),`N`
+29AW,_$>3)%_\'XGNMJQQ8```
`
end
diff --git a/usr.bin/w/w.c b/usr.bin/w/w.c
index 1b9af5f..ca5b79e 100644
--- a/usr.bin/w/w.c
+++ b/usr.bin/w/w.c
@@ -68,6 +68,7 @@ static const char sccsid[] = "@(#)w.c 8.4 (Berkeley) 4/16/94";
#include <fcntl.h>
#include <kvm.h>
#include <langinfo.h>
+#include <libgen.h>
#include <libutil.h>
#include <limits.h>
#include <locale.h>
@@ -121,7 +122,6 @@ static struct entry {
static void pr_header(time_t *, int);
static struct stat *ttystat(char *);
static void usage(int);
-static int this_is_uptime(const char *s);
char *fmt_argv(char **, char *, char *, size_t); /* ../../bin/ps/fmt.c */
@@ -144,7 +144,7 @@ main(int argc, char *argv[])
use_comma = (*nl_langinfo(RADIXCHAR) != ',');
/* Are we w(1) or uptime(1)? */
- if (this_is_uptime(argv[0]) == 0) {
+ if (strcmp(basename(argv[0]), "uptime") == 0) {
wcmd = 0;
p = "";
} else {
@@ -512,17 +512,3 @@ usage(int wcmd)
(void)fprintf(stderr, "usage: uptime\n");
exit(1);
}
-
-static int
-this_is_uptime(const char *s)
-{
- const char *u;
-
- if ((u = strrchr(s, '/')) != NULL)
- ++u;
- else
- u = s;
- if (strcmp(u, "uptime") == 0)
- return (0);
- return (-1);
-}
diff --git a/usr.sbin/autofs/common.c b/usr.sbin/autofs/common.c
index cefbcc8..e6db682 100644
--- a/usr.sbin/autofs/common.c
+++ b/usr.sbin/autofs/common.c
@@ -169,17 +169,12 @@ create_directory(const char *path)
if (component == NULL)
break;
concat(&partial, &component);
- //log_debugx("checking \"%s\" for existence", partial);
- error = access(partial, F_OK);
- if (error == 0)
- continue;
- if (errno != ENOENT)
- log_err(1, "cannot access %s", partial);
- log_debugx("directory %s does not exist, creating",
- partial);
+ //log_debugx("creating \"%s\"", partial);
error = mkdir(partial, 0755);
- if (error != 0)
- log_err(1, "cannot create %s", partial);
+ if (error != 0 && errno != EEXIST) {
+ log_warn("cannot create %s", partial);
+ return;
+ }
}
free(tofree);
diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
index b955ecc..a5a6559 100644
--- a/usr.sbin/bhyve/acpi.c
+++ b/usr.sbin/bhyve/acpi.c
@@ -492,7 +492,7 @@ basl_fwrite_fadt(FILE *fp)
EFPRINTF(fp,
"[0012]\t\tPM Timer Block : [Generic Address Structure]\n");
EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 32\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 20\n");
EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
EFPRINTF(fp,
"[0001]\t\tEncoded Access Width : 03 [DWord Access:32]\n");
@@ -502,7 +502,7 @@ basl_fwrite_fadt(FILE *fp)
EFPRINTF(fp, "[0012]\t\tGPE0 Block : [Generic Address Structure]\n");
EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 80\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
index 394b116..c66ad68 100644
--- a/usr.sbin/bhyve/pci_virtio_block.c
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -94,6 +94,8 @@ struct vtblk_config {
struct virtio_blk_hdr {
#define VBH_OP_READ 0
#define VBH_OP_WRITE 1
+#define VBH_OP_FLUSH 4
+#define VBH_OP_FLUSH_OUT 5
#define VBH_OP_IDENT 8
#define VBH_FLAG_BARRIER 0x80000000 /* OR'ed into vbh_type */
uint32_t vbh_type;
@@ -217,6 +219,10 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vqueue_info *vq)
MIN(iov[1].iov_len, sizeof(sc->vbsc_ident)));
err = 0;
break;
+ case VBH_OP_FLUSH:
+ case VBH_OP_FLUSH_OUT:
+ err = fsync(sc->vbsc_fd);
+ break;
default:
err = -ENOSYS;
break;
diff --git a/usr.sbin/bhyve/xmsr.c b/usr.sbin/bhyve/xmsr.c
index c0ab7c5..1ed1ea1 100644
--- a/usr.sbin/bhyve/xmsr.c
+++ b/usr.sbin/bhyve/xmsr.c
@@ -80,6 +80,13 @@ emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val)
case MSR_DRAM_ENERGY_STATUS:
*val = 0;
break;
+ case MSR_RAPL_POWER_UNIT:
+ /*
+ * Use the default value documented in section
+ * "RAPL Interfaces" in Intel SDM vol3.
+ */
+ *val = 0x000a1003;
+ break;
default:
error = -1;
break;
diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index 1cacf64..19ee806 100644
--- a/usr.sbin/ctladm/ctladm.8
+++ b/usr.sbin/ctladm/ctladm.8
@@ -34,7 +34,7 @@
.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
.\" $FreeBSD$
.\"
-.Dd September 13, 2014
+.Dd October 8, 2014
.Dt CTLADM 8
.Os
.Sh NAME
@@ -961,6 +961,9 @@ This allows to offload copying between different iSCSI targets residing
on the same host in trusted environments.
.It Va readcache
Set to "off", disables read caching for the LUN, if supported by the backend.
+.It Va readonly
+Set to "on", blocks all media write operations to the LUN, reporting it
+as write protected.
.It Va reordering
Set to "unrestricted", allows target to process commands with SIMPLE task
attribute in arbitrary order. Any data integrity exposures related to
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index ff9e937..b63234b 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -1968,8 +1968,8 @@ do_sigwork(struct sigwork_entry *swork)
*/
if (errno != ESRCH)
swork->sw_pidok = 0;
- warn("can't notify %s, pid %d", swork->sw_pidtype,
- (int)swork->sw_pid);
+ warn("can't notify %s, pid %d = %s", swork->sw_pidtype,
+ (int)swork->sw_pid, swork->sw_fname);
} else {
if (verbose)
printf("Notified %s pid %d = %s\n", swork->sw_pidtype,
diff --git a/usr.sbin/nmtree/Makefile b/usr.sbin/nmtree/Makefile
index 8cba6f8..5789ad8 100644
--- a/usr.sbin/nmtree/Makefile
+++ b/usr.sbin/nmtree/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.include <bsd.own.mk>
+.include <src.opts.mk>
.PATH: ${.CURDIR}/../../contrib/mtree
@@ -24,4 +24,8 @@ LDADD+= ${LIBNETBSD}
LINKS= ${BINDIR}/mtree ${BINDIR}/nmtree
MLINKS= mtree.8 nmtree.8
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/nmtree/tests/Makefile b/usr.sbin/nmtree/tests/Makefile
new file mode 100644
index 0000000..1df81d0
--- /dev/null
+++ b/usr.sbin/nmtree/tests/Makefile
@@ -0,0 +1,32 @@
+# $FreeBSD$
+
+TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.sbin/mtree
+.PATH: ${TESTSRC}
+
+TESTSDIR= ${TESTSBASE}/usr.sbin/nmtree
+
+ATF_TESTS_SH= nmtree_test
+ATF_TESTS_SH_SRC_nmtree_test= t_mtree.sh
+
+FILESDIR= ${TESTSDIR}
+
+# NOTE: the output from FreeBSD's nmtree displays sha256digest instead of
+# sha256; we need to mangle the specfiles to reflect this.
+.for f in mtree_d_create.out netbsd6_d_create.out
+CLEANFILES+= $f $f.tmp
+FILES+= $f
+$f: ${TESTSRC}/$f
+ sed -e 's/sha256/sha256digest/g' < ${.ALLSRC} > ${.TARGET}.tmp
+ mv ${.TARGET}.tmp ${.TARGET}
+.endfor
+
+FILES+= d_convert.in
+FILES+= d_convert_C.out
+FILES+= d_convert_C_S.out
+FILES+= d_convert_D.out
+FILES+= d_convert_D_S.out
+FILES+= d_merge.in
+FILES+= d_merge_C_M.out
+FILES+= d_merge_C_M_S.out
+
+.include <bsd.test.mk>
diff --git a/usr.sbin/nscd/query.c b/usr.sbin/nscd/query.c
index c233e19..270992e 100644
--- a/usr.sbin/nscd/query.c
+++ b/usr.sbin/nscd/query.c
@@ -1253,8 +1253,8 @@ init_query_state(int sockfd, size_t kevent_watermark, uid_t euid, gid_t egid)
retval->read_func = query_socket_read;
get_time_func(&retval->creation_time);
- memcpy(&retval->timeout, &s_configuration->query_timeout,
- sizeof(struct timeval));
+ retval->timeout.tv_sec = s_configuration->query_timeout;
+ retval->timeout.tv_usec = 0;
TRACE_OUT(init_query_state);
return (retval);
diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c
index 36c5d9d..efb2901 100644
--- a/usr.sbin/pw/pw_user.c
+++ b/usr.sbin/pw/pw_user.c
@@ -615,7 +615,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name);
pwd->pw_shell = pw_shellpolicy(cnf, args, NULL);
lc = login_getpwclass(pwd);
- if (lc == NULL || login_setcryptfmt(lc, "md5", NULL) == NULL)
+ if (lc == NULL || login_setcryptfmt(lc, "sha512", NULL) == NULL)
warn("setting crypt(3) format");
login_close(lc);
pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name);
@@ -690,7 +690,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
} else {
lc = login_getpwclass(pwd);
if (lc == NULL ||
- login_setcryptfmt(lc, "md5", NULL) == NULL)
+ login_setcryptfmt(lc, "sha512", NULL) == NULL)
warn("setting crypt(3) format");
login_close(lc);
pwd->pw_passwd = pw_pwcrypt(line);
diff --git a/usr.sbin/pw/tests/Makefile b/usr.sbin/pw/tests/Makefile
index 577ea93..3003c8f 100644
--- a/usr.sbin/pw/tests/Makefile
+++ b/usr.sbin/pw/tests/Makefile
@@ -2,7 +2,7 @@
TESTSDIR= ${TESTSBASE}/usr.sbin/pw
-ATF_TESTS_SH= pw_delete
+ATF_TESTS_SH= pw_delete pw_modify
FILES= group helper_functions.shin master.passwd
FILESDIR= ${TESTSDIR}
diff --git a/usr.sbin/pw/tests/pw_modify.sh b/usr.sbin/pw/tests/pw_modify.sh
new file mode 100755
index 0000000..28a89e1
--- /dev/null
+++ b/usr.sbin/pw/tests/pw_modify.sh
@@ -0,0 +1,34 @@
+# $FreeBSD$
+
+# Import helper functions
+. $(atf_get_srcdir)/helper_functions.shin
+
+
+# Test adding & removing a user from a group
+atf_test_case groupmod_user
+groupmod_user_body() {
+ populate_etc_skel
+ atf_check -s exit:0 pw -V ${HOME} addgroup test
+ atf_check -s exit:0 pw -V ${HOME} groupmod test -m root
+ atf_check -s exit:0 -o match:"^test:\*:1001:root$" \
+ grep "^test:\*:.*:root$" $HOME/group
+ atf_check -s exit:0 pw -V ${HOME} groupmod test -d root
+ atf_check -s exit:0 -o match:"^test:\*:1001:$" \
+ grep "^test:\*:.*:$" $HOME/group
+}
+
+
+# Test adding and removing a user that does not exist
+atf_test_case groupmod_invalid_user
+groupmod_invalid_user_body() {
+ populate_etc_skel
+ atf_check -s exit:0 pw -V ${HOME} addgroup test
+ atf_check -s exit:67 -e match:"does not exist" pw -V ${HOME} groupmod test -m foo
+ atf_check -s exit:0 pw -V ${HOME} groupmod test -d foo
+}
+
+
+atf_init_test_cases() {
+ atf_add_test_case groupmod_user
+ atf_add_test_case groupmod_invalid_user
+}
OpenPOWER on IntegriCloud